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
자동으로 오름차순 정렬되는 컬렉션도 있고 검색 기능이 추가된 컬렉션들도 있습니다.
이런 컬렉션들을 잘 사용하면 훨씬 빠르게 출력을 낼 수 있을 것 같아요!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~
'BackEnd > Java' 카테고리의 다른 글
[java] 이것이 자바다 ch16 람다식(rambda) (0) | 2023.01.27 |
---|---|
[java] 이것이 자바다 ch15 컬렉션 3 (0) | 2023.01.26 |
[java] 이것이 자바다 ch15 컬렉션 1 (0) | 2023.01.25 |
[java] 이것이 자바다 ch14 스레드(thread) 2 (0) | 2023.01.25 |
[java] 이것이 자바다 ch14 스레드(thread) (2) | 2023.01.25 |