[기본 개념] 6 | (1.7) HashSet
1 컬렉션 프레임웍의 핵심 인터페이스
2 ArrayList
3 LinkedList
4 Stack과 Queue
5 Iterator, Listlterator, Enumeration
6 Arrays
7 Comparator와 Comparable
8> HashSet
9 TreeSet
10 HashMap과 Hashtable
11 TreeMap
12 Properties
13 Collections
14 컬렉션 클래스 정리 & 요약
8. HashSet
HashSet은 Set인터페이스를 구현한 가장 대표적인 컬렉션이며, Set인터페이스 특징처럼 중복된 요소를 저장하지 않는다. 그리고 HashSet은 저장순서를 유지하지 않으므로 저장순서를 유지하고 싶으면 LinkedHashSet을 사용해야 한다.
add메서드는 객체를 추가할 때 HashSet에 이미 같은 객체가 있으면 중복으로 간주하고 저장하지 않고 false를 반환한다. 그렇지만 String인스턴스 "1"과 Integer인스턴스 1은 둘 다 '1'로 출력되지만 서로 다른 객체이므로 중복으로 간주하지 않는다.
출력된 값을 크기순으로 정렬하기 위해 Collections클래스의 sort(List list)를 사용하려면 List인터페이스 타입이 필요하기 때문에 LinkedList클래스의 생성자 LinkedList(Collection c)를 이용해서 HashSet에 저장된 객체를 LinkedList에 담아서 처리해야 한다.
예제/HashSetEx3.java
import java.util.*;
public class HashSetEx3 {
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 + "살";
}
}
실행결과
[abc, David : 10살, David : 10살]
두 인스턴스의 name과 age의 값이 같음에도 'David : 10살'이 2번 출력되었다. 이 두 인스턴스를 같은 것으로 인식하게 해야한다.
HashSet의 add메서드는 새로운 요소를 추가하기 전 저장된 요소와 추가하려는 요소의 equals( )와 hashCode( )를 호출하기 때문에 equals( )와 hashCode( )를 목적에 맞게 오버라이딩 해야한다.
우선 두 인스턴스의 name과 age가 서로 같으면 true를 반환하도록 equals( )를 오버라이딩 해야한다.
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person tmp = (Person) obj ;
return name.equals(tmp.name) && age == tmp.age ;
}
return false ;
}
그리고 hashCode( )도 오버라이딩 해야하는데 String클래스의 hashCode( )를 활용하면 된다.
public int hashCode( ) {
return (name + age).hashCode( ) ;
}
위의 코드도 좋지만 새로 추가된 java.util.Objects클래스의 hash( )를 이용해서 작성할 수도 있다. 가능하면 아래의 코드가 낫다.
public int hashCode( ) {
return Objects.hash(name, age) ; // int hash(Object. . . values)
}
오버라이딩을 통해 작성된 hashCode( )는 다음조건을 만족시켜야 한다.
1 실행중인 애플리케이션 내의 동일한 객체에 대해 여러번 hashCode( )를 호출해도 동일한 int값을 반환해야 하지만 실행 시마다 동일한 int값을 반환할 필요는 없다.
2 equals메서드를 이용한 비교에 의해 true를 얻은 두 객체에 대해 hashCode( )를 호출해서 얻은 결과는 같아야 한다.
3 equals메서드를 호출했을 때 false를 반환하는 두 객체는 hashCode( )호출에 같은 in값을 반환할 수도 있지만 가능한 서로 다른 int값을 반환하는 것이 좋다.
두 객체에 대해 equals메서드를 호출한 결과가 true이면, 두 해시코드는 반드시 같아야하지만,
해시코드가 같다고 해서 equals메서드를 호출한 결과가 항상 true는 아니다.
출처 | Java의 정석 (남궁 성)
'💠프로그래밍 언어 > Java' 카테고리의 다른 글
[기본 개념] 6 | (1.9) HashMap, Hashtable (0) | 2022.01.03 |
---|---|
[기본 개념] 6 | (1.8) TreeSet (0) | 2021.12.03 |
[기본 개념] 6 | (1.6) Arrays, Comparator, Comparable (0) | 2021.12.03 |
[기본 개념] 6 | (1.5) Iterator, ListIterator, Enumeration (0) | 2021.12.03 |
[기본 개념] 6 | (1.4) Stack, Queue (0) | 2021.12.02 |