본문 바로가기
BackEnd/Java

[Java] Hash set

by summer_light 2021. 7. 19.

Hash set

- 순서 X 중복 X


HashSet은 객체들을 순서없이 저장하고 동일한 객체는 중복 저장하지 않는다.
HashSet이 판단하는 동일 객체란 꼭 같은 인스턴스를 뜻하지 않는다.


HashSet은 객체를 저장하기 전에 객체의 hashCode()메소드를 호출해서 해시코드를 얻어내고,
그리고 이미 저장된 객체의 해시코드와 비교한다.  
만약 동일한 해시코드가 나온다면 equals() 메소드로 두 객체를 비교해서 
true가 나온다면 동일한 객체로 판단하고 중복 저장을 하지 않는다.

 

이런 순서로 동일 객체인지 확인하기 때문에

서로 다른 String 객체인 경우에도 같은 문자열을 갖고 있을 때 중복으로 취급될 수 있다.

 

문자열을 HashSet에 저장하는 경우, 
같은 문자열을 갖는 String 객체는 동등한 객체로 간주되고 
다른 문자열을 갖는 String 객체는 다른 객체로 간주되는데, 
그 이유는 String 클래스가 hashCode()와 equals()메소드를 재정의해서
같은 문자열의 경우 hashCode()의 리턴값을 같게, 
equals()의 리턴값을 참으로 나오게 하기 때문이다.

 

String 객체 뿐 아니라 임의의 객체들도 hashCode()메소드와 equals()메소드를 재정의하면

서로 다른 객체들이라도 중복으로 취급되게 만들 수 있다. (아래의 EX01 참고)

 

자주 사용하는 메소드

  • .add( ): 중복 값은 추가해도, 변화 X
  • .clear()
  • .size()
    package collection;
    import java.util.HashSet;
    import java.util.Scanner;
    
    public class Set01 {
    public static void main(String[] args) {
    HashSet<Integer> set = new HashSet<Integer>();
    
    //set.add()
    set.add(104);
    set.add(10);
    set.add(1100);
    set.add(104); //중복 값 추가해도 변화 X
    
    System.out.println(set.size()); //4개를 추가 했지만, size는 3
    
    }
    }
    ※ 왜 System.out.println(set.add(r)); 을 하면 true/false로 출력되는 지 모르겠어서, 일단 적어둔다.  
    set.clear();
    System.out.println(set); //[]
    while (set.size() < 6) {
    	int r = (int)(Math.random() * 45 + 1);
    	set.add(r);
    	System.out.println(set.add(r)); //이게 왜 true false? 
    }
    System.out.println(set);
  • .addAll() 
    • set에 .addAll() : 순서가 섞이며 연결됨(기준?)
    • list에 .addAll() : 순서가 유지되며 연결됨
      //.addAll()
      Set<Integer> set = new HashSet<Integer>();
      set.add(100);
      set.add(100);
      set.add(10);
      set.add(10);
      
      System.out.println(set); //[100, 10]
      
      List<Integer> list = new ArrayList<Integer>();
      list.add(5);
      list.add(60);
      list.add(65);
      
      //set에 .addAll(list) 
      //순서가 섞이며 연결됨 (기준?)
      set.addAll(list); 
      System.out.println(set); //[65, 100, 5, 10, 60]
      
      //list에 .addAll(set)
      //순서 유지되며 연결됨(list 뒤에 set)
      list.addAll(set);
      System.out.println(list); //[5, 60, 65, 65, 100, 5, 10, 60]
  • .remove()
  • .contains()
    //set도 .remove(), .contains() 등 사용가능
    set.remove(60);//set에서 60이 삭제됨 [65, 100, 5, 10, 60] -> [65, 100, 5, 10]
    System.out.println(set); //[65, 100, 5, 10]
    
    //출력
    for (Integer i : set) {
    System.out.println(i);
    }

 

Set에서 Iterator 사용하기

Set 객체는 .get() 메서드가 제공되지 않으므로 다음과 같이 iterator를 활용하여 객체를 순회함 

Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());

 

 

 

 

EX01. HashSet의 동일 객체 취급 기준 확인하기 

package collection;

import java.util.HashSet;
import java.util.Set;

class Member{
	public String name;
	public int age;
	
	public Member(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int hashCode() {
		return name.hashCode() + age;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Member){
			Member member = (Member) obj;
			return member.name.equals(name) && member.age == age;
		}else {
			return false;
		}
	}
}

public class Set04 {
	public static void main(String[] args) {
		
		Set<Member> set = new HashSet<Member>();
		
		//Member m1 = new Member("홍길동", 150);
		//Member m2 = new Member("홍길동", 150);
		
		set.add(new Member("홍길동", 150));
		set.add(new Member("홍길동", 150));
		
		System.out.println(set.size()); //1
		System.out.println(set); //[collection.Member@33a4444] 
		
	}

}

→ hashCode() 메소드와 equals() 메소드를 재정의하면,

같은 객체로 취급되어 중복으로 추가되지 않는 다는 것을 알 수 있다.

'BackEnd > Java' 카테고리의 다른 글

[Java] 스택(Stack), 큐(Queue)  (0) 2021.07.19
[Java] 맵 Map  (0) 2021.07.19
[Java] VirtualBox 설치  (0) 2021.07.19
[Java] Linked List  (0) 2021.07.18
[Java] ArrayList  (0) 2021.07.15

댓글