본문 바로가기

BackEnd/Java

[java] 이것이 자바다 ch15 컬렉션 2

728x90
반응형

4. Map 컬렉션

   ▷ 키와 값으로 구성된 엔트리 객체를 저장

   ▷ 키는 중복 저장할 수 없지만 값은 중복 저장할 수 있음. 기존에 저장된 키와 동일한 키로 값을 저장하면 새로운 값으로 대치

 

NO 기능 메소드 설명
1 객체 추가 V put(K key, V value) 주어진 키와 값을 추가,
저장이 되면 값을 리턴
2 객체 검색 boolean containsKey(Object key) 주어진 키가 있는지 여부
3 boolean containsValue(Object value) 주어진 값이 있는지 여부
4 Set<Map.Entry<K,V>> entrySet() 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴
5 V get(Object Key) 주어진 키의 값을 리턴
6 boolean isEmpty() 컬렉션이 비어있는지 여부
7 Set<K> keySet() 모든 키를 Set 객체에 담아서 리턴
8 int size() 저장된 키의 총 수를 리턴
9 Collection<V> values() 저장된 모든 값 Collection에 담아서 리턴
10 객체 삭제 void clear() 모든 Map.Entry(키와 값)을 삭제
11 V remove(Object key) 주어진 키와 일치하는 Map.Entry 삭제,
삭제가되면 값을 리턴

 

◎ HashMap

   ▷ 키로 사용할 객체가 hashCode() 메소드의 리턴값이 같고 equals() 메소드가 true를 리턴할 경우 동일 키로 보고 중복 저장을 허용하지 않음

 

◎ HashMap 예제

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class HashMapExample {
	public static void main(String[] args) {
		// Map 컬렉션 생성
		Map<String, Integer> map = new HashMap<>();
		
		// 객체 저장
		map.put("신용권", 85);
		map.put("홍길동", 90);
		map.put("동장군", 80);
		map.put("홍길동", 95);
		System.out.println("총 Entry 수: " + map.size());
		System.out.println();
		
		// 키로 값 얻기
		String key = "홍길동";
		int value = map.get(key);
		System.out.println(key + ": " + value);
		System.out.println();
		
		// 키 Set 컬렉션을 얻고, 반복해서 키와 값을 얻기
		// set의 경우 하나만 저장되어서 key를 우선적으로 set으로 만들어줍니다.
		Set<String> keySet = map.keySet();	// key로 set을 만들고
		Iterator<String> keyIterator = keySet.iterator();	// keySet 이용해서 Iterator
		while(keyIterator.hasNext()) {		// set에 값이 있는지 확인 : 값 없으면 실행 X
			String k = keyIterator.next();	// set에서 값을 하나 가져오기
			Integer v = map.get(k);
			System.out.println(k + " : " + v);
		}
		System.out.println();

		// 엔트리 Set 컬렉션을 얻고, 반복해서 키와 값을 얻기
		Set<Entry<String, Integer>> entrySet = map.entrySet();
		Iterator<Entry<String, Integer>> entryIterator = entrySet.iterator();
		while(entryIterator.hasNext()) {
			Entry<String, Integer> entry = entryIterator.next();
			String k = entry.getKey();
			Integer v = entry.getValue();
			System.out.println(k + " : " + v);
		}
		System.out.println();
		
		// 키로 엔트리 삭제
		map.remove("홍길동");
		System.out.println("총 Entry 수: " + map.size());
		System.out.println();
	}
}

//	출력 : 
//	총 Entry 수: 3
//	
//	홍길동: 95
//	
//	홍길동 : 95
//	신용권 : 85
//	동장군 : 80
//	
//	홍길동 : 95
//	신용권 : 85
//	동장군 : 80
//	
//	총 Entry 수: 2

 

◎ Hashtable

   ▷ 동기화된 메소드로 구성되어 있어 멀티 스레드가 동시에 Hashtable의 메소드들을 실행 불가

   ▷ 멀티 스레드 환경에서도 안전하게 객체를 추가, 삭제할 수 있습니다.

 

◎ Hashtable 예제

import java.util.Hashtable;
import java.util.Map;
import java.util.HashMap;

public class HashTableExample {
	public static void main(String[] args) {
		// Hashtable 컬렉션 생성
		Map<String, Integer> map = new Hashtable<>();

		// HashMap 컬렉션 생성
//		Map<String, Integer> map = new HashMap<>();
		
		// 작업 스레드 객체 생성
		Thread threadA = new Thread() {
			@Override
			public void run() {
				// 엔트리 1000개 추가
				for(int i = 1; i<=1000; i++) {
					map.put(String.valueOf(i), i);
				}
			}
		};
		
		// 작업 스레드 객체 생성
		Thread threadB = new Thread() {
			@Override
			public void run() {
				// 엔트리 1000개 추가
				for(int i = 1001; i<=2000; i++) {
					map.put(String.valueOf(i), i);
				}
			}
		};
		
		// 작업 스레드 실행
		threadA.start();
		threadB.start();
		
		// 작업 스레드들이 모두 종료될 때까지 메인 스레드를 기다리게 함
		try {
			threadA.join();
			threadB.join();
		} catch (Exception e) {
		}
		
		// 저장된 총 엔트리 수 얻기
		int size = map.size();
		System.out.println("총 엔트리 수: " + size);
		System.out.println();
	}
}

//	Hashtable 출력 : 
//	총 엔트리 수: 2000
	
//	HashMap 출력 :
//	총 엔트리 수: 1964

 

자료 구조 : 데이터베이스

LIST, SET : 일반 SQL 데이터베이스, oracle db, mysql, mssql

MAP : NoSQL 데이터베이스

 

Properties

   ▷ Properties는 Hashtable의 자식 클래스. 키와 값을 String 타입으로 제한한 컬렉션

   ▷ 주로 확장자가 .properties인 프로퍼티 파일을 읽을 때 사용

   ▷ 프로퍼티 파일은 키와 값이 = 기호로 연결된 텍스트 파일(ISO 8859-1 문자셋, 한글은 \u+유니코드)

   ▷ Properties 객체를 생성하고, load() 메소드로 프로퍼티 파일의 내용을 메모리로 로드

 

1. database.properties 텍스트 파일
driver = oracle.jdbc.OracleDriver
url = jdbc:oracle:thin:@localhost:1521:orcl
username = scott
password = tiger
admin = \uD64D\uAE38\uB3D9​

 

2. PropertiesExample 클래스
import java.util.Properties;

public class PropertiesExample {

	public static void main(String[] args) throws Exception {
		Properties properties = new Properties();
		
		properties.load(PropertiesExample.class.getResourceAsStream("database.properties"));
		
		String driver = properties.getProperty("driver");
		String url = properties.getProperty("url");
		String username = properties.getProperty("username");
		String password = properties.getProperty("password");
		String admin = properties.getProperty("admin");
		
		System.out.println("driver : " + driver);
		System.out.println("url : " + url);
		System.out.println("username : " + username);
		System.out.println("password : " + password);
		System.out.println("admin : " + admin);
	}
}

//	출력 : 
//	driver : oracle.jdbc.OracleDriver
//	url : jdbc:oracle:thin:@localhost:1521:orcl
//	username : scott
//	password : tiger
//	admin : 홍길동​

 

 

5. 검색 기능 강화시킨 컬렉션

 

◎ TreeSet

   ▷ 이진 트리를 기반으로 한 Set 컬렉션

   ▷ 여러 개의 노드가 트리 형태로 연결된 구조. 루트 노드에서 시작해 각 노드에 최대 2개의 노드를 연결할 수 있음

   ▷ TreeSet에 객체를 저장하면 부모 노드의 객체와 비교해서 낮은 것은 왼쪽 자식 노드에, 높은 것은 오른쪽 자식 노드에 저장

 

◎ TreeSet 컬렉션을 생성하는 방법

   ▷ Set 타입 변수에 대입해도 되지만 TreeSet 타입으로 대입한 이유는 검색 관련 메소드가 TreeSet에만 정의되어 있기 때문

 

NO 리턴 타입 메소드 설명
1 E first() 제일 낮은 객체를 리턴
2 E last() 제일 높은 객체를 리턴
3 E lower(E e) 주어진 객체보다 바로 아래 객체를 리턴
4 E higher(E e) 주어진 객체보다 바로 위 객체를 리턴
5 E floor(E e) 주어진 객체와 동등한 객체가 있으면 리턴, 만약 없다면 주어진
객체의 바로 아래의 객체를 리턴
6 E ceiling(E e) 주어진 객체와 동등한 객체가 있으면 리턴, 만약 없다면 주어진
객체의 바로 위의 객체를 리턴
7 E pollFirst() 제일 낮은 객체를 꺼내오고 컬렉션에서 제거함
8 E pollLast() 제일 높은 객체를 꺼내오고 컬렉션에서 제거함
9 Iterator<E> descendingIterator() 내림차순으로 정렬된 Iterator를 리턴
10 NavigableSet<E> descendingSet() 내림차순으로 정렬된 NavigableSet을 리턴
11 NavigableSet<E> headSet(
   E toElement,
   boolean inclusive
)
주어진 객체보다 낮은 객체들을 NavigableSet으로 리턴,
주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐.
12 NavigableSet<E> tailSet(
   E fromElement,
   boolean inclusive
)
주어진 객체보다 높은 객체들을 NavigableSet으로 리턴,
주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐.
13 NavigableSet<E> subSet(
   E fromElement,
   boolean frominclusive,
   E toElement,
   boolean toInclusive
)
시작과 끝으로 주어진 객체 사이의 객체들을 NavigableSet으로 리턴. 시작과 끝 객체의 포함 여부는 두 번째, 네 번째 매개값에 따라 달라짐

 

◎ TreeSet 사용 예제

import java.util.NavigableSet;
import java.util.TreeSet;

public class TreeSetExample {

	public static void main(String[] args) {
		// TreeSet 컬렉션 생성
		TreeSet<Integer> scores = new TreeSet<>();
		
		// Integer 객체 저장
		scores.add(87);
		scores.add(98);
		scores.add(75);
		scores.add(95);
		scores.add(80);
		
		// 정렬된 Integer 객체를 하나씩 가져오기
		for(Integer s : scores) {
			System.out.print(s + " ");
		}
		System.out.println("\n");
		
		// 특정 Integer 객체를 가져오기
		System.out.println("가장 낮은 점수 : " + scores.first());
		System.out.println("가장 높은 점수 : " + scores.last());
		System.out.println("95점 아래 점수 : " + scores.lower(95));
		System.out.println("95점 위의 점수 : " + scores.higher(95));
		System.out.println("95점이거나 바로 아래 점수 : " + scores.floor(95));
		System.out.println("85점이거나 바로 위의 점수 : " + scores.ceiling(85) + "\n");
		
		// 내림차순으로 정렬하기
		// 오름차순 : ASC, 내림차순 : DESC
		NavigableSet<Integer> descendingScores = scores.descendingSet();
		for(Integer s : descendingScores) {
			System.out.print(s + " ");
		}
		System.out.println("\n");
		
		// 범위 검색(80 <= )
		NavigableSet<Integer> rangeSet = scores.tailSet(80, true);
		for(Integer s : rangeSet) {
			System.out.print(s + " ");
		}
		System.out.println("\n");
		
		// 범위 검색 (80 <= score < 90)
		rangeSet = scores.subSet(80, true, 90, false);
		for(Integer s : rangeSet) {
			System.out.print(s + " ");
		}
	}
}

//	출력 : 
//	75 80 87 95 98 
//	
//	가장 낮은 점수 : 75
//	가장 높은 점수 : 98
//	95점 아래 점수 : 87
//	95점 위의 점수 : 98
//	95점이거나 바로 아래 점수 : 95
//	85점이거나 바로 위의 점수 : 87
//	
//	98 95 87 80 75 
//	
//	80 87 95 98 
//	
//	80 87

 

◎ TreeMap

   ▷ 이진 트리를 기반으로 한 Map 컬렉션, 키와 값이 저장된 엔트리 저장

   ▷ 부모키 값과 비교해서 낮은 것이 왼쪽, 높은 것ㅇ니 오른쪽 자식 노드에 Entry 객체를 저장

 

NO 리턴 타입 메소드 설명
1 Map.Entry<K,V> firstEntry() 제일 낮은 Map.Entry를 리턴
2 Map.Entry<K,V> lastEntry() 제일 높은 Map.Entry를 리턴
3 Map.Entry<K,V> lowerEntry(K key) 주어진 키보다 바로 아래 Map.Entry를 리턴
4 Map.Entry<K,V> higherEntry(K key) 주어진 키보다 바로 위 Map.Entry를 리턴
5 Map.Entry<K,V> floorEntry(K key) 주어진 키와 동등한 키가 있으면 해당 Map.Entry를 리턴, 없다면 주어진 키 바로 아래의 Map.Entry를 리턴
6 Map.Entry<K,V> ceilingEntry(K key) 주어진 키와 동등한 키가 있으면 해당 Map.Entry를 리턴, 없다면 주어진 키 바로 위의 Map.Entry를 리턴
7 Map.Entry<K,V> pollFirstEntry() 제일 낮은 Map.Entry를 꺼내오고 컬렉션에서 제거함
8 Map.Entry<K,V> pollLastEntry() 제일 높은 Map.Entry를 꺼내오고 컬렉션에서 제거함
9 NavigableSet<K> descendingKeySet() 내림차순으로 정렬된 키의 NavigableSet을 리턴
10 NavigableMap<K,V> descendingMap() 내림차순으로 정렬된 Map.Entry의 NavigableMap을 리턴
11 NavigableMap<K,V> headMap(
   K toKey,
   boolean inclusive
)
주어진 키보다 낮은 Map.Entry들을 NavigableMap으로 리턴.
주어진 키의 Map.Entry 포함 여부는 두 번째 매개값에 따라 달라짐
12 NavigableMap<K,V> tailMap(
   K fromKey,
   boolean inclusive
)
주어진 객체보다 높은 Map.Entry들을 NavigableSet으로 리턴.
주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐
13 NavigableMap<K,V> subSet(
   K fromKey,
   boolean frominclusive,
   K toKey,
   boolean toInclusive
)
시작과 끝으로 주어진 키 사이의 Map.Entry들을 NavigableMap 컬렉션으로 반환. 시작과 끝 키의 Map.Entry 포함 여부는 두 번째, 네 번째 매개값에 따라 달라짐

 

 

◎ TreeMap 사용 예제

import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;

public class TreeMapExample {

	public static void main(String[] args) {
		
		// TreeMap 컬렉션 생성
		TreeMap<String, Integer> treeMap = new TreeMap<>();
		
		// 엔트리 저장
		treeMap.put("apple", 10);
		treeMap.put("forever", 60);
		treeMap.put("description", 40);
		treeMap.put("ever", 50);
		treeMap.put("zoo", 80);
		treeMap.put("base", 20);
		treeMap.put("guess", 70);
		treeMap.put("cherry", 30);

		// 정렬된 엔트리를 하나씩 가져오기
		Set<Entry<String, Integer>> entrySet = treeMap.entrySet();
		for(Entry<String, Integer> entry : entrySet) {
			System.out.println(entry.getKey() + "-" + entry.getValue());
		}
		System.out.println();
		
		// 특정 키에 대한 값 가져오기
		Entry<String, Integer> entry = null;
		entry = treeMap.firstEntry();
		System.out.println("제일 앞 단어 : " + entry.getKey() + "-" + entry.getValue());
		entry = treeMap.lastEntry();
		System.out.println("제일 뒤 단어 : " + entry.getKey() + "-" + entry.getValue());
		entry = treeMap.lowerEntry("ever");
		System.out.println("ever 앞 단어 : " + entry.getKey() + "-" + entry.getValue() + "\n");
		
		// 내림차순으로 정렬하기
		NavigableMap<String, Integer> descendingMap = treeMap.descendingMap();
		Set<Entry<String, Integer>> descendingEntrySet = descendingMap.entrySet();
		for(Entry<String, Integer> e : descendingEntrySet) {
			System.out.println(e.getKey() + "-" + e.getValue());
		}
		System.out.println();
		
		// 범위 검색
		System.out.println("[c~h 사이의 단어 검색]");
		NavigableMap<String, Integer> rangeMap = treeMap.subMap("c", true, "h", false);
		for(Entry<String, Integer> e : rangeMap.entrySet()) {
			System.out.println(e.getKey() + "-" + e.getValue());
		}
	}
}

//	출력 : 
//	apple-10
//	base-20
//	cherry-30
//	description-40
//	ever-50
//	forever-60
//	guess-70
//	zoo-80
//	
//	제일 앞 단어 : apple-10
//	제일 뒤 단어 : zoo-80
//	ever 앞 단어 : description-40
//	
//	zoo-80
//	guess-70
//	forever-60
//	ever-50
//	description-40
//	cherry-30
//	base-20
//	apple-10
//	
//	[c~h 사이의 단어 검색]
//	cherry-30
//	description-40
//	ever-50
//	forever-60
//	guess-70

 

◎ Comparable과 Comparator

   ▷ TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체를 정렬

   ▷ Comparable 인터페이스에는 compareTo() 메소드가 정의. 사용자 정의 클래스에서 이 메소드를 재정의해서 비교 결과를 정수 값으로 리턴

NO 리턴 타입 메소드 설명
1 int compareTo(T o) 주어진 객체와 같으면 0을 리턴
주어진 객체보다 적으면 음수를 리턴
주어진 객체보다 크면 양수를 리턴

 

◎ Comparable 사용 예제

1. Person 클래스
public class Person implements Comparable<Person> {
	public String name;
	public int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int compareTo(Person o) {
		if(age<o.age) return -1;
		else if(age == o.age) return 0;
		else return 1;
	}
}​

 

2. ComparableExample 메인 클래스
import java.util.TreeSet;

public class ComparableExample {

	public static void main(String[] args) {
		// TreeSet 컬렉션 생성
		TreeSet<Person> treeSet = new TreeSet<Person>();
		
		// 객체 저장
		treeSet.add(new Person("홍길동", 45));
		treeSet.add(new Person("김자바", 25));
		treeSet.add(new Person("박지원", 31));
		
		// 객체를 하나씩 가져오기
		for(Person person : treeSet) {
			System.out.println(person.name + ":" + person.age);
		}
	}
}

//	출력 : 
//	김자바:25
//	박지원:31
//	홍길동:45​

 

   ▷ 비교 기능이 없는 Comparable 비구현 객체를 저장하려면 비교자 Comparator를 제공

   ▷ 비교자는 compare() 메소드를 재정의해서 비교 결과를 정수 값으로 리턴

NO 리턴 타입 메소드 설명
1 int compare(T o1, T o2) o1과 o2가 동등하다면 0을 리턴
o1이 o2보다 앞에 오게 하려면 음수를 리턴
o1이 o2보다 뒤에 오게 하려면 양수를 리턴

 

◎ Comparator 사용 예제

1. Fruit 클래스
public class Fruit {
	public String name;
	public int price;
	
	public Fruit(String name, int price) {
		this.name = name;
		this.price = price;
	}
}​

 

2. FruitComparator 클래스
import java.util.Comparator;

public class FruitComparator implements Comparator<Fruit> {
	@Override
	public int compare(Fruit o1, Fruit o2) {
		if(o1.price < o2.price) return -1;
		else if(o1.price == o2.price) return 0;
		else return 1;
	}
}​

 

3. ComparableExample 메인 클래스
import java.util.TreeSet;

public class ComparableExample {
	public static void main(String[] args) {
		// 비교자를 제공한 TreeSet 컬렉션 생성
		TreeSet<Fruit> treeSet = new TreeSet<Fruit>(new FruitComparator());
		
		// 객체 저장
		treeSet.add(new Fruit("포도", 3000));
		treeSet.add(new Fruit("수박", 10000));
		treeSet.add(new Fruit("딸기", 6000));

		// 객체를 하나씩 가져오기
		for(Fruit fruit : treeSet) {
			System.out.println(fruit.name + ":" + fruit.price);
		}
	}
}

//	출력 : 
//	포도:3000
//	딸기:6000
//	수박:10000​

 

자동으로 오름차순 정렬되는 컬렉션도 있고 검색 기능이 추가된 컬렉션들도 있습니다.

 

이런 컬렉션들을 잘 사용하면 훨씬 빠르게 출력을 낼 수 있을 것 같아요!!

 

많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~

 

728x90
반응형