Set 구현체
HashSet
Set인터페이스를 구현한 가장 대표적인 컬렉션으로, Set의 특징대로 중복된 요소를 저장하지 않는다.
HashSet의 특징을 이용하면, 컬렉션 내의 중복된 요소들을 쉽게 제거할 수 있다.
(이미지 출처)
ArrayList와 같이 List 인터페이스를 구현한 컬렉션과 달리 HashSet은 저장순서를 유지하지 않으므로 저장순서를 유지하고자 하면 LinkedHashSet을 사용해야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class HashSetTest { public static void main(String[] args){ Integer[] intArr = {4, 4, 5, 6, 1, 1, 1, 2, 2, 3, 3, 7, 8,}; // HashSet은 중복을 허용하지 않고 저장순서가 유지되지않는다. Set<Integer> set = new HashSet<>(); for(Integer i : intArr){ set.add(i); } System.out.println("HashSet : " + set); // LinkedHashSet을 이용하면 저장순서를 유지할 수 있다. Set<Integer> linkedSet = new LinkedHashSet<>(); for(Integer i : intArr){ linkedSet.add(i); } System.out.println("linkedHashSet : " + linkedSet); } } | cs |
-- result --
HashSet : [1, 2, 3, 4, 5, 6, 7, 8]
linkedHashSet : [4, 5, 6, 1, 2, 3, 7, 8]
linkedHashSet을 이용하면 삽입한 저장순서를 유지하고 있는 것을 볼 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class HashSetTest2 { public static void main(String[] args){ Set set = new HashSet(); set.add("duplication"); set.add("duplication"); set.add("duplication"); set.add(new Person("kang", 28)); set.add(new Person("kang", 28)); System.out.println("set : " + set); } } class Person{ private String name; private int age; Person(String name, int age){ this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } } | cs |
-- result --
set : [Person [name=kang, age=28], Person [name=kang, age=28], duplication]
"duplication"문자열은 중복이 되었으므로, 결과값에서 하나만 출력된 것을 볼 수 있다.
위의 코드를 보면 이름과 나이가 같은 사람(Person 인스턴스)으로 인식하도록 하려는 의도로 작성하였지만, kang이 2번 출력된 것을 볼 수 있다.
이 두 인스턴스를 같은 인스턴스로 인식하게 하려면 어떻게할까?
HashSet의 add 메소드는 요소를 추가하기 전에 기존에 저장된 요소와 같은 것인지 판별하기 위해 추가하려는 요소의 equals() 와 hashcode()를 호출하기 때문에 equals()와 hashCode()를 목적에 맞게 오버라이딩해줘야 한다.
=> 이클립스의 기능을 활용하면 hashCode(), equals()를 자동으로 알맞게 오버라이딩 해준다.(ctrl + shift + r)
이클립스의 기능을 활용하여 Person class에 hashCode(), equals() 메소드를 오버라이딩하게 되면 아래와 같은 결과값을 얻게 된다.
-- result --
set : [Person [name=kang, age=28], duplication]
적절한 hashCode메서드를 만들기 위해서는 아래의 세 가지 조건을 만족시켜야 한다.
- 실행 중인 애플리케이션 내의 동일한 객체에 대해서 여러분 hashCode()를 호출해도 동일한 int 값을 반환해야 한다. 하지만 실행시마다 동일한 int 값을 반환할 필요는 없다.
- equals메서드를 이용한 비교에 의해서 true를 얻은 두 객체에 대해 각각 hashCode()를 호출해서 얻은 결과는 반드시 같아야 한다.
- eqauls메서드를 호출했을 때 false를 반환하는 두 객체는 hashCode() 호출에 대해 같은 int 값을 반환하는 경우가 있어도 괜찮지만, 해싱(hashing)을 사용하는 컬렉션의 성능을 향상시키기 위해서는 다른 int 값을 반환하는 것이 좋다.
(참고서적 : JAVA의 정석)
'프로그래밍 노트 > JAVA' 카테고리의 다른 글
[JAVA] 컬렉션프레임워크(CollectionFramework) 5 - HashMap (0) | 2018.09.13 |
---|---|
[JAVA] 컬렉션프레임워크(CollectionFramework) 4 - TreeSet (0) | 2018.09.12 |
[JAVA] JCA(Java Cryptography Architecture) 자바 암호화와 보안 2 (0) | 2018.09.06 |
[JAVA] JCA(Java Cryptography Architecture) 자바 암호화와 보안 (0) | 2018.09.05 |
[JAVA] 컬렉션프레임워크(CollectionFramework) 2 (0) | 2018.08.13 |