-
[ch11 컬렉션 프레임웍] HashSet & HashMap의 메서드 및 사용법프로그래밍 언어/JAVA 2022. 8. 4. 13:18
HashSet 이란?
HashSet은 Set 인터페이스를 구현한 가장 대표적인 컬렉션이며, Set인터페이스의 특징대로 HashSet은 중복된 요소를 저장하지 않는다. (순서 x 중복 x) List랑 반대된다고 생각하면 되겠다.
<예제 1번>
package ch11; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Ex11_6 { public static void main(String[] args) { Object [] objArr = {"1", new Integer(1), "2","2","3","3","4","4","4"}; Set set = new HashSet(); for(int i=0; i<objArr.length;i++) { boolean save = set.add(objArr[i]); System.out.print(save + ", "); } System.out.println(); System.out.println(set); Iterator it = set.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } }
HashSet은 중복된 값은 저장하지 않는 것을 알 수 있다. add메서드는 객체를 추가할 때 이미 같은 객체가 있으면 중복으로 간주하고 false를 반환한다.
<예제 2번 >
package ch11; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; public class Ex11_10 { public static void main(String[] args) { Set set = new HashSet(); for(int i=0; set.size()<6; i++) { int random = (int)((Math.random()*45)+1); set.add(new Integer(random)); } List list = new LinkedList(set); Collections.sort(list); System.out.println(list); } }
중복된 값은 저장되지 않는 HashSet의 성질을 이용해서 로또번호를 만드는 예제이다. Math.random()을 사용했기 때문에 실행할 때 마다 결과가 다를 것이다. 출력한 결과를 번호 크기 순으로 정렬하기 위해 Collections클래스의 sort를 사용했다. 이 메서드는 인자로 List 인터페이스 타입을 필요로 하기 때문에 LinkedList클래스의 생성자를 이용해 HashSet에 저장된 객체들을 LinkedList에 담아서 처리했다.
<예제 3번>
package ch11; import java.util.HashSet; import java.util.Objects; public class Ex11_11 { public static void main(String[] args) { HashSet set = new HashSet(); set.add("abc"); set.add("abc"); set.add(new Person("David",10)); set.add(new Person("David",10)); System.out.println(set); } } class Person{ String name; int age; Person(String name, int age){ this.name = name; this.age = age; } public String toString() { return name + " : " +age; } @Override public int hashCode() { return Objects.hash(name,age); } @Override public boolean equals(Object obj) { if(!(obj instanceof Person)) return false; Person p = (Person)obj; return name.equals(p.name) && age==p.age; } }
Person 클래스는 name과 age를 멤버변수로 갖는다. 이름과 나이가 같으면 같은 사람으로 인식하여 저장하지 않도록 작성하였다. 만약) equlas랑 hashCode() 메서드를 오버라이딩하지 않았다면 같은 값이라고 인식하지 않고 David:10이 2번 출력되었을텐데 오버라이딩 해서 이미 저장된 객체랑 이름이 같고 나이가 같다면 true를 반환해서 저장하지 않도록 했다.
이는 HashSet의 add메서드는 새로운 요소를 추가하기 전에 기존에 저장된 요소와 같은 것인지 판별하기 위해 추가하려는 요소의 equals()와 hashCode() 메서드를 호출하기 때문이다.! 따라서 목적에 맞게 오버라이딩 해야한다.
★ 참고로!! 목록에서 source에 getter setter 자동 생성이 있듯이 hashCode와 equals 또한 존재하므로 사용하기
<예제 4번>
package ch11; import java.util.HashSet; import java.util.Iterator; public class Ex11_12 { public static void main(String[] args) { HashSet setA = new HashSet(); HashSet setB = new HashSet(); HashSet setHap = new HashSet(); HashSet setKyo = new HashSet(); HashSet setCha = new HashSet(); setA.add("1"); setA.add("2"); setA.add("3"); setA.add("4"); setA.add("5"); setB.add("4"); setB.add("5"); setB.add("6"); setB.add("7"); setB.add("8"); //Kyo Iterator it = setA.iterator(); while(it.hasNext()) { Object obj = it.next(); if(setB.contains(obj)) { setKyo.add(obj); } } //Hap it = setA.iterator(); while(it.hasNext()) { Object obj = it.next(); setHap.add(obj); } it = setB.iterator(); while(it.hasNext()) { Object obj = it.next(); setHap.add(obj); } //Cha it = setA.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!(setB.contains(obj))) { setCha.add(obj); } } System.out.println("A : " +setA); System.out.println("B : " +setB); System.out.println("A ∩ B : "+ setKyo); System.out.println("A ∪ B : "+ setHap); System.out.println("A - B : "+ setCha); } }
HashMap이란?
HashMap은 Map의 특징처럼, key와 value를 묶어서 하나의 데이터(entry)로 저장한다는 특징을 갖는다.
즉) 순서x, 중복(키x, 값 o )
해싱(hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는데 있어 뛰어난 성능을 보인다.
HashMap은 Entry라는 내부 클래스를 정의하고, 다시 Entry 타입의 배열을 선언하고 있다. 키(key)와 값(value)은 별개의 값이 아니라 서로 관련된 값이기 때문에 각각의 배열로 선언하기 보다는 하나의 클래스로 정의해서 하나의 배열로 다루는 것이 데이터의 무결성(integrity)적인 측면에서 더 바람직하다.
HashMap의 키(key)와 값(value)
HashMap은 키와 값을 각각 Object타입으로 저장한다. 즉 (Object, Object) 형태로 저장하기 때문에 어떠한 객체도 저장할 수 있지만 키는 주로 String을 대문자 또는 소문자를 통일해서 사용한다.
키는 유일(unique)해야 한다. 즉) HashMap에 저장된 데이터를 하나의 키로 검색했을 때 결과가 단 하나이어야 한다. 예를들어 사용자 ID가 키, 비밀번호가 값으로 연결되어 저장된 데이터의 집합이 있을 때 로그인 시 비밀번호를 확인하기 위해 ID는 하나여야 되는 것 처럼!
해시함수란? key값을 넣으면 저장되어 있는 배열의 index를 알려준다.
해싱이란? 해쉬함수를 이용해서 저장 & 읽어오기 하는 과정
HashMap 주요 메서드
생성자 / 메서드 설명 boolean containsKey(Object key) HashMap에 지정된 키(key)가 포함되어 있는지 알려준다. 포함되면 true boolean containsValue(Object value) HashMap에 지정된 값(value)가 포함되어 있는지 알려준다. 포함되면 true Object get(Object key) 지정된 키의 값을 반환. 못 찾으면 null Object put(Object key, Object value) 지정된 키와 값을 HashMap에 저장 Object replace(Object key, Object value) 지정된 키의 값을 지정된 객체(value)로 대체 Set entrySet() HashMap에 저장된 키와 엔트리(키와 값의 결합)의 형태로 Set에 저장해서 변환 Set keySet() HashMap에 저장된 모든 키가 저장된 Set을 반환한다.
<예제 5번>
package ch11; import java.util.HashMap; import java.util.Scanner; public class Ex11_13 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("myId", "1234"); map.put("asdf", "1111"); map.put("asdf", "1234"); //이미 존재하는 키 추가 가능, but 기존 값은 사라짐 //이걸 예방하려면 유효성검사 해야한다. while(true) { System.out.println("id와 password를 입력하세요."); Scanner sc = new Scanner(System.in); System.out.print("id >> "); String id = sc.nextLine().trim(); System.out.print("Password >> "); String pwd = sc.nextLine().trim(); System.out.println(); if(map.containsKey(id)) { if(map.get(id).equals(pwd)) { System.out.println("id와 비밀번호가 일치합니다."); break; //System.exit(0) }else { System.out.println("비밀번호가 일치하지 않습니다."); //continue; } }else{ System.out.println("아이디가 불일치 합니다. 다시 입력해주세요."); //continue; } } } }
3개의 데이터를 저장했지만 실제로는 중복된 키가 있기 때문에 세 번째로 저장한 데이터의 키인 'asdf'는 이미 존재하기 때문에 새로 추가되는 대신 덮어쓰기를 한다. Map에서 값은 중복을 허용하지만 키는 중복을 허용하지 않기 때문에 저장하려는 두 데이터 중에서 어느 쪽을 키로 할 것인지 잘 결정해야 한다.
<예제 6번>
package ch11; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Ex11_17 { public static void main(String[] args) { HashMap map = new HashMap(); map.put("김자바",100); map.put("이자바",100); map.put("강자바",80); map.put("안자바",90); //entrySet() : HashMap에 저장된 키와 엔트리(키와 값의 결합)의 형태로 Set에 저장해서 변환 Set set = map.entrySet(); Iterator it = set.iterator(); System.out.println(set); while(it.hasNext()) { //Map.Entry의 하나 개의 클래스에 저장 키와 값 함께 모두 한 번에 얻을 수 있다. Map.Entry e = (Map.Entry)it.next(); System.out.println("이름 : " + e.getKey() + ", 점수 : " + e.getValue()); } set = map.keySet(); //HashMap에 저장된 모든 키가 저장된 Set을 반환한다. System.out.println("참가자 명단" + set); Collection values = map.values(); it = values.iterator(); int total =0; while(it.hasNext()) { int i = (int)it.next(); total += i; } System.out.println("총점 : " + total); System.out.println("평균 : " + (float)total/map.size()); System.out.println("최고점수 : " + Collections.max(values)); System.out.println("최저점수 : " + Collections.min(values)); //Collection은 인터페이스 Collections는 클래스 } }
Iterator는 List, Set만 가능하기 때문에 객체 map을 entrySet과 keySet으로 Set에 저장해서 반환한다.
<예제 7번>
package ch11; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class Ex11_18 { public static void main(String[] args) { String [] data = {"A","D","K","Z","D","A","K","K","A","K"}; HashMap map = new HashMap(); for(int i=0; i<data.length;i++) { if(map.containsKey(data[i])) { int value = (int)map.get(data[i]); map.put(data[i], value+1); }else { map.put(data[i], 1); } } Iterator it = map.entrySet().iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); int count = (int)entry.getValue(); Ex11_18 ex = new Ex11_18(); System.out.println(entry.getKey() + " : "+ ex.printBar('#',count)+ " " + count); } } public String printBar(char ch, int count) { // String str = "#"; // for(int i=1; i<count; i++) { // str += String.valueOf(ch); // } // // return str; char [] bar = new char[count]; for(int i=0; i<bar.length;i++) bar[i] = ch; return new String(bar); } }
문자열 배열(data) 에 담긴 문자열을 하나씩 읽어서 HashMap의 키로 저장하고 값이 없으면 초기 값을 1로 지정한다. constrainsKey를 통해 이미 저장되어 있는 키면 value값을 1씩 증가한다. 저장된 value의 값을 printBar 메서드를 이용해서 그래프로 표현했다. 바로 빈도수 구하는 예제인 것.
반응형'프로그래밍 언어 > JAVA' 카테고리의 다른 글
[JAVA] JVM이란? 자바 가성 머신 실행과정, 구조 알아보기 (0) 2022.09.19 [ch11 JAVA ] Comparator와 Comparable 비교, 배열 정렬하기 (0) 2022.08.05 [ch9 JAVA] StringBuffer 클래스의 생성자와 메서드 알아보기 (0) 2022.08.04 [ch9 JAVA] String 클래스 생성자 & String, new String() 차이 (0) 2022.08.04 [ch11 컬렉션 프레임웍] Arrays의 중요 메서드 (복사, 정렬, 비교..) (0) 2022.08.03