본문 바로가기
java

collections framework - HashSet

by proudev 2023. 9. 2.

HashSet - 순서 X, 중복 X,

 

  Set
HashSet SortedSet
  TreeSet

HashSet

- Set 인터페이스를 구현한 대표적인 컬렉션 클래스

- 순서를 유지하려면, LinkedHashSet클래스를 사용하면 된다.

- HashSet은 객체를 저장하기전에 기존에 같은 객체가 있는지 확인 후

같은 객체가 없으면 저장하고, 있으면, 저장하지 않는다.

- boolean add(Object o)는 저장할 객체의 equals()와 hashCode()를 호출

- equals() 와 hashCode()가 

 

 

TreeSet

- 범위 검색과 정렬에 유리한 컬레션 클래스

- from ~ to

- HashSet보다 데이터 추가, 삭제에 시간이 더 걸림


 HashSet - 주요 매서드

생성자 매서드

HashSet() HashSet 기본생성자
HashSet(Collection c) Collection c를 HashSet 객체로 만듬
HashSet(int initialCapacity) HashSet의 초기 용량 설정
HashSet(int initialCapacity, float loadFactor) HashSet의 초기 용량 설정하고 해당 용량의 몇퍼센트가 되면 객체의 용량을 늘이는지에 대한 기준은 float loadFactor의 의해 결정(예: 0.8f이면 용량의 80퍼센트가 차면 2배로 늘림)

 

기타 매서드

boolean add(Object o) Object o 객체추가
boolean addAll(Collection c) Collection c 컬렉션 추가(합집합)
boolean remove(Object o) Object o 객체 삭제
boolean removeAll(Collection c) Collection c 컬렉션 삭제(교집합)
boolean retainAll(Collection c) Collection c 조건부 삭제(차집합)
void clear() 전부 삭제
boolean contains(Object o) Object o 객체가 포함되어 있는지
boolean containsAll(Collection c) Collection c 컬렉션이 포함되어 있는지
Iterator iterator() 컬렉션 요소 읽어올 수 있는 매서

 

boolean isEmpty() 비어있는지
int size() 저장된 객체의 개수
Object[ ] toArray() Set저장된 객체를 객체 배열로 반
Object[ ] toArray(Object[] a) Object[] a 요소를 채워서 반환, 만약 배열의 크기가 넘치면 공간이 여유있는 새로운 객체로 생성해서 반환
public void main(String[] args){
   Object[] objArr = {"1",new Integer(1), "2","3","2","2"}
   Set set = new HashSet();
   
   for(int i=0;i<objArr.length;i++){
      set.add(objArr[i]);
   }
   
   System.out.println(set); 
   [1,1,2,3] 중복된 2는 사라졌지만, 1은 2개가 있다.
   이는 언뜻보기에 똑같은 1이 중복되는 것처럼 보이나
   사실 문자열 1과 Integer 1이라 서로 타입이 달라서 중복되지 않는 것이다.
   그래서 Set안에 1이 2번 표현될 수 있다.
   
   Iterator it = set.iterator();
   
   while(it.hasNext){
     System.out.println(it.next());
   }
}

 

Set은 순서가 없기 때문에 정렬이 되지 않는다.

순서가 있는 List 타입인 경우에는 정렬할 수 있다.

그래서 Set을 List 타입 생성자 매서드 매겨변수에 넣고 

해당 List에 있는 매서드를 활용해서(new ArrayList(Set set))

publis static void main(String[] args){
   Set set = new HashSet();
   
   for(int i=0;set.size() < 6; i++){
      int num = (int)(Math.random()*45) + 1;
      set.add(num);
   }

   System.out.println(set); [16,35,2,22,44]
   set은 순서가 없기 때문에 정렬되지 않는다(Set 정렬불가) 그래서 정렬을 하고 싶으면
   set을 List에 담아서 정렬해준다. 
   List list = new ArrayList(set);
   Collection.sort(list);
   System.out.println(list); [2,16,22,35,44]

}

HashSet 예제

HashSet은 객체를 저장하기전에 기존에 같은 객체가 있는지확인 같은 객체가 없으면 저장하고, 있으면 저장하지 않는다.

boolean add(Object o)는 저장할 객체의 equals()와 hashCode()를 호출 equals()와 hashCode()가 오버라이딩 되어 있어야 함

public boolean equals(Object obj){
   if(!(obj instanceof Person)) return false;
   
   Person tmp = (Person)obj;
   return name.equals(tmp.name) && age == tmp.age;
}

public int hashCode(){
   return (name+age).hashCode();
   // return Objects.hash(name,age) 동일함
}

 

Set은 중복된 것을 저장하지 않는다. 그러나 객체 내의 인스턴스 변수 값이 같아도 주소값이 다르기에 중복을 제거하지 않는다. 해당 예시는 아래와 같다.

public static void main(String[] args){
   HashSet set = new HashSer();
   
   set.add("abc");
   set.add("abc");
   set.add(new Person("David",10));
   set.add(new Person("David",10));
   
   System.out.println(set); // [abc, abc, David:10, David:10]
}

class Person{
   String name;
   int age;
   
   Person(String name, int age){
      this.name = name;
      this.age = age;
   }
   
   public String toString(){
      return name + ":" + age;
   }
}

그래서 new Person("David",10))을 2번 저장하면 인스턴스 변수가 같아도 주소값이 다르기 때문에 중복 제거를 하지 않는다.

그래서 equals만 오버라이딩만 하는 것이 아닌  주소값을 비교하는 hashcode매서드를 오버라이딩해서 수정해주어야한다. 

class Person{
   String name;
   int age;
   
   Person(String name, int age){
      this.name = name;
      this.age = age;
   }
   
   @Override
   public boolean equals(Object obj){
      if(!(obj instanceof Person)) return false;
      
      Person p = (Person)obj;
      
      return name.equals(obj.name) && age==obj.age;
   }
   
   @Override
   public int hashCode(){
       return Objects.hash(name,age);
   }
   
   @Override
   public String toString(){
      return name + ":" + age;
   }
}

 

class Ex11_12 {
  public static void main(String args[]){
     HashSet setA   = new HashSet();
     HashSet setB   = new HashSet();
     HashSet setHab = 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");
     
     // 교집합
     Iterator it = SetA.iteraotr();
     while(it.hasNext()){
        Object tmp = it.next();
        if(setB.contain(tmp)){
           setKyo.add(tmp);
        }
     }
     setA.retainAll(setB); 교집합    
     
     // 합집합
     it = setA.iterator();
     while(it.hasNext()){
        Object tmp = it.next();
        setHab.add(tmp);     
     }
     it = setB.iterator();
     while(it.hasNext()){
        Object tmp = it.next();
        setHab.add(tmp);     
     }
     
     setA.addAll(setB); 합집합
     
     // 차집합
     it = setA.iterator();
     while(it.hasNext()){
        Object tmp = it.next();
        if(!setB.contain(tmp)){
          setCha.add(tmp);
        }
     }
     setA.removeAll(setB); 차집합
  }
}

 

댓글