Java/객체지향

[객체지향][자바의 정석] - 20. HashSet

얄루몬 2022. 1. 31. 17:55

📖본 포스팅은 '자바의 정석 - 남궁성 저자' 님의 책과 유튜브 강의를 보고 작성되었습니다.

 


[HashSet -  순서가 없고, 중복이 허용되지 않는다.]

 

HashSet

  • Set인터페이스를 구현한 대표적인 컬렉션 클래스
  • 순서를 유지라하면 LinkedHashSet 클래스를 사용하면 된다.

 

TreeSet

  • 범위 검색과 정렬에 유리한 컬렉션 클래스
  • HashSet보다 데이터 추가, 삭제에 시간이 더 걸린다.

 

 

 

[HashSet - 주요메서드]

hashset method

 

 

 

 

[실습]

package javajungsuk;

import java.util.Iterator;
import java.util.Set;
import java.util.*;

public class Java11_8_1 {

	public static void main(String[] args) {
		Object[] objArr = {"1", new Integer(1),"2","2","3","3","4","4"};
		Set set = new HashSet();
		
		for(int i = 0; i < objArr.length; i++) {
			set.add(objArr[i]); //HashSet에 objArr의 요소들을 저장
		}
		
		System.out.println(set);
		
		Iterator it = set.iterator();
		
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		
	}

}
[출력 값]

[1, 1, 2, 3, 4]
1
1
2
3
4
  • 요소들을 HashSet에 추가 -> 중복값은 빼고 저장
    • 그러나 1은 왜 두개? 하나는 String 하나는 int라서임.

 

  • Iterator을 사용해서 이터레이터 메소드로 받아온 뒤 읽어올 요소가 있는지 확인하고 요소를 하나씩 꺼내서 출력해주기.
  • 저장 순서와 일치해보이지만, Set은 순서 유지가 되지 않기 때문에 어떻게 저장되었는지는 모름 

 

 

 

[set을 정렬하려면?]

  • 정렬이 안되는 Set을 정렬하기 위해서는 리스트로 만들어 준 뒤 이를 정렬해주면 된다.

 

 

 

[TreeSet - 주요 생성자와 메서드]

 

 

 

 

[HashSet] 

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

 

  • Booolean add(Object o)는 저장할 객체의 equals()와 hashCode()를 호출한다.
    • 이때 equals( )와 hashCode( )가 오버라이딩 되어 있어야 한다.

 

 

[equals( )와 hashCode( ) 오버라이딩을 해주지 않아서 중복이 허용된 코드]

package javajungsuk;

import java.util.HashSet;

public class Java11_11 {
	public static void main(String[] args) {

		HashSet set = new HashSet();
		
		set.add("abc");
		set.add("abc"); //중복으로 저장 X
		set.add(new Person("David",10));
		set.add(new Person("David",10));
		
		System.out.println(set);
	}

}

// equals()와 hashCode()를 오버라이딩해야 HashSet이 바르게 동작한다.
class Person{
	String name;
	int age;
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public String toString() {
		return name +":" + age;
	}
}
[결과]

[David:10, abc, David:10]
  • 이는 equals()와 hashCode()를 오버라이딩 해주지 않아서 중복을 허용하고 있는 모습이다. 
  • 또한 HashSet은 순서가 없기 때문에 순서를 지 마음대로 저장한다.

 

 

[equals( )와 hashCode( ) 오버라이딩을 해서 중복을 허용하지 않는 코드]

package javajungsuk;

import java.util.HashSet;
import java.util.Objects;

public class Java11_11 {
	public static void main(String[] args) {
		HashSet set = new HashSet();
		
		set.add("abc");
		set.add("abc"); //중복으로 저장 X
		set.add(new Person("David",10));
		set.add(new Person("David",10));
		
		System.out.println(set);
	}

}

// equals()와 hashCode()를 오버라이딩해야 HashSet이 바르게 동작한다.
class Person{
	String name;
	int age;
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public String toString() {
		return name +":" + age;
	}
	
	
	// equals 재정의
    @Override
    public boolean equals(Object o) {
    	if(!(o instanceof Person)) return false;
    	
    	Person p = (Person)o;
    	//나 자신(this)의 이름과 나이를 p와 비교
    	return this.name.equals(p.name) && this.age == p.age;
    }
    
    // hashcode 재정의
    @Override
    public int hashCode() {
        return Objects.hash(name,age);
    }
}

 

 

[HashSet으로 만든 합집합, 차집합, 교집합 코드]

package javajungsuk;

import java.util.HashSet;
import java.util.Iterator;

public class Java11_11_2 {

	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"); 
		System.out.println("A = "+setA);
		
		setB.add("4"); setB.add("5"); setB.add("6");
		setB.add("7"); setB.add("8"); 
		System.out.println("B = "+setB);
		
		// 교집합
		Iterator it = setB.iterator();
		while(it.hasNext()) {
			Object tmp = it.next();
			if(setA.contains(tmp))
				setKyo.add(tmp);
		}
		
		//차집합
		it = setA.iterator();
		while(it.hasNext()) {
			Object tmp = it.next();
			if(!setB.contains(tmp))
				setCha.add(tmp);
		}
		
		//합집합
		it = setA.iterator();
		while(it.hasNext()) {
			setHab.add(it.next());
		}
		
		it = setB.iterator();
		while(it.hasNext()) {
			setHab.add(it.next());
		}
		
		System.out.println("A ⋂ B = " + setKyo);
		System.out.println("A ∪ B = " + setHab);
		System.out.println("A - B = " + setCha);
	}
	
	
}

 

[함수를 사용해서 위의 코드 만들기]

		setA.retainAll(setB);// 교집합 공통된 요소만 남기고 삭제 
		setA.addAll(setB); // 합집합 setB의 모든 요소를 추가(중복 제거)
		setA.remove(setB); // 차집합 setB와 공통요소를 제거