본문 바로가기
교육/Java

JAVA 개발자 수업 28일차 - HashSet

by yhyuk 2021. 5. 6.
728x90
반응형

1. HashSet


1. HashSet

[정의]

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

- 순서가 없는 배열이다. --> 방 번호가 존재하지않으며, 첨자(index)를 사용하지 않는다.

- 요소가 중복값을 가질 수 없다.

 

[ArrayList와 HashSet의 비교1]

ArrayList<String> list = new ArrayList<String>();
HashSet<String> set = new HashSet<String>();

//ArrayList & HashSet 데이터 추가
list.add("사과");
list.add("딸기");
list.add("바나나");
list.add("딸기");

set.add("사과");
set.add("딸기");
set.add("바나나");
set.add("딸기");

System.out.println("ArrayList & HashSet 개수");
System.out.println(list.size());
System.out.println(set.size());

//출력용X... -> 개발자 확인용
System.out.println("ArrayList & HashSet 덤프");
System.out.println(list);
System.out.println(set);

System.out.println("ArrayList & HashSet 요소 접근/탐색");
for (String item : list) {
    System.out.println(item);
}

set.iterator();
Iterator<String> iter = set.iterator();

while (iter.hasNext()) {
    System.out.println(iter.next());
}


//OUTPUT
ArrayList & HashSet 개수
4
3

ArrayList & HashSet 덤프
[사과, 딸기, 바나나, 딸기]
[사과, 바나나, 딸기]

ArrayList & HashSet 요소 접근/탐색
사과
딸기
바나나
딸기

사과
바나나
딸기

----> ArrayList는 각 방 마다 중복 값("딸기")이 포함해서 들어가 있다.
----> HashSet은 중복값("딸기")은 포함하지 않는다.


 

[ArrayList와 HashSet의 비교2 - 중복값 없는 로또 번호 만들기]

Random rnd = new Random();

//List
ArrayList<Integer> lotto = new ArrayList<Integer>();

for (int i=0; i<6; i++) {
    int n = rnd.nextInt(45) + 1;
    boolean flag = false;
    
    //같은 숫자 검사
    for (int j=0; j<i; j++) {
        if (n == lotto.get(j)) {
            flag = true;
            break;
        }
    }
    if (flag) i--;
    else lotto.add(n);
}
Collections.sort(lotto);
System.out.println(lotto);

//Set
HashSet<Integer> lotto2 = new HashSet<Integer>();

while (lotto2.size() < 6) {
    int n = rnd.nextInt(45) + 1;
    lotto2.add(n);
}
System.out.println(lotto);


//OUTPUT
[3, 6, 24, 42, 44, 45]
[32, 17, 4, 20, 13, 31]


----> ArrayList는 같은숫자를 조건문을 통해 걸러주지 않으면 중복값이 나올 수 있다.
----> HashSet은 중복값이 안되므로, 코드가 List와 비교해서 간결하다.

 

[HashSet 중복값 허용 예시1]

class Keyboard {

    private String model;
    private int price;
    
    public Keyboard(String model, int price) {
    this.model = model;
    this.price = price;
	}
    
    @Override
    public String toString() {
        return "[model=" + model + ", price=" + price + "]";
    }
}

HashSet<Integer> set1 = new HashSet<Integer>();

set1.add(10);
set1.add(20);
set1.add(10); //중복값 허용X

System.out.println(set1);

HashSet<Keyboard> set2 = new HashSet<Keyboard>();

set2.add(new Keyboard("K810", 200000));
set2.add(new Keyboard("K310", 50000));
set2.add(new Keyboard("K810", 200000));

System.out.println(set2);


//OUTPUT
[10, 20]
[model=K810, price=200000], [model=K310, price=50000], [model=K810, price=200000]


----> set2에서의 첫번째값과, 세번째값은 똑같은 값이 아니다!
----> 모든 참조형(객체)는 아무리 상태(멤버 변수의 값)가 동일해도, 다른 객체로 취급한다. (쌍둥이 개념)

 

[HashSet 중복값 허용 예시2 - hashCode+equals Override]

class Keyboard {

    private String model;
    private int price;
    
    public Keyboard(String model, int price) {
    this.model = model;
    this.price = price;
	}
    
    @Override
    public String toString() {
        return "[model=" + model + ", price=" + price + "]";
    }
    
    //hashCode 오버라이딩 + equals 오버라이딩
    @Override
    public int hashCode() {
        //본인의 상태에 따라 달라지는 값을 반환하도록 재정의
        //k1: "K810", 200000 -> "K810200000"
        //k2: "K810", 200000 -> "K810200000" -> 100
        //k4: "K990", 350000 -> "K990350000" -> 200
        return (this.model + this.price).hashCode();
	}
	
	@Override
    public boolean equals(Object obj) {
         return this.hashCode() == obj.hashCode();
    }
}

Keyboard k1 = new Keyboard("K810", 200000);
Keyboard k2 = new Keyboard("K810", 200000);
Keyboard k3 = k1;
Keyboard k4 = new Keyboard("K990", 350000);

System.out.println("===참조형 객체의 비교===");
System.out.println(k1 == k2);		
System.out.println(k1.equals(k2)); 	
System.out.println(k1.equals(k3));

System.out.println("===참조형 객체의 hashCode===");
System.out.println(k1.hashCode());	//hashCode: 객체의 위치(메모리 주소값)
System.out.println(k2.hashCode());
System.out.println(k4.hashCode());

//hashCode + euqals :오버라이드(재정의)
System.out.println(k1 == k2);		
System.out.println(k1.equals(k2));	
System.out.println(k1.equals(k4)); 	


//OUTPUT
===참조형 객체의 비교===
false
true
true

===참조형 객체의 hashCode===
634282602
634282602
-82344313
false
true
false


----> 문자열(참조형)은 불변이다. 모든 참조형 변수의 비교는 주소값을 비교한다.
----> "equals":OK / "==":NO
----> hashCode에서의 객체 중복을 허용 하려면, hashCode와 equals 메소드를 오버라이드 해줘야 한다.

 

 


MEMO >

 

# 나중에 면접에서 List와 Set의 차이를 물어볼 수 있으니 핵심 키워드와 차이점을 명확히 알자!

   --> List는 순서가 있는 배열이며, 요소가 중복값을 가질 수 있다!

   --> Set은 순서가 없는 배열이며, 요소가 중복값을 가질 수 없다!

 

# 컬렉션에서의 덤프(toString) 사용은 절대 출력용으로 사용하지 않는다

   --> why? 개발자만 확인 할 수 있는 용도이다.

 

# 문자열(참조형) 비교에서 "==" 사용금지!! "equals()" 무조건 사용!! 

 

# 프로젝트 진행 중인데, 클래스 설계가 중요한걸 점점 깨닫고 있으며... ArrayList사용과 파일입출력 하는 부분이 계속 막힌다...... 그래도 화이팅!

 

728x90
반응형

댓글