ν‹°μŠ€ν† λ¦¬ λ·°

πŸ”Ž Set μ»¬λ ‰μ…˜ 클래슀

Set μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ λͺ¨λ“  Set μ»¬λ ‰μ…˜ ν΄λž˜μŠ€λŠ” λ‹€μŒκ³Ό 같은 νŠΉμ§•μ„ κ°€μ§‘λ‹ˆλ‹€.

 

1. μš”μ†Œμ˜ μ €μž₯ μˆœμ„œλ₯Ό μœ μ§€ν•˜μ§€ μ•ŠλŠ”λ‹€.

2. 같은 μš”μ†Œμ˜ 쀑볡 μ €μž₯을 ν—ˆμš©ν•˜μ§€ μ•ŠλŠ”λ‹€.

 

λŒ€ν‘œμ μΈ Set μ»¬λ ‰μ…˜ ν΄λž˜μŠ€μ— μ†ν•˜λŠ” ν΄λž˜μŠ€λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

1. HashSet<E>

2. TreeSet<E>

 

❓ HashSet<E> 클래슀

HashSet ν΄λž˜μŠ€λŠ” Set μ»¬λ ‰μ…˜ ν΄λž˜μŠ€μ—μ„œ κ°€μž₯ 많이 μ‚¬μš©λ˜λŠ” 클래슀 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

JDK1.2λΆ€ν„° μ œκ³΅ν•œ HashSet ν΄λž˜μŠ€λŠ” ν•΄μ‹œ μ•Œκ³ λ¦¬μ¦˜(hash algorithm)을 μ‚¬μš©ν•˜μ—¬ 검색 속도가 맀우 λΉ λ¦…λ‹ˆλ‹€.

μ΄λŸ¬ν•œ HashSet ν΄λž˜μŠ€λŠ” λ‚΄λΆ€μ μœΌλ‘œ HashMap μΈμŠ€ν„΄μŠ€λ₯Ό μ΄μš©ν•˜μ—¬ μš”μ†Œλ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.

 

HashSet ν΄λž˜μŠ€λŠ” Set μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λ―€λ‘œ, μš”μ†Œλ₯Ό μˆœμ„œμ— 상관없이 μ €μž₯ν•˜κ³  μ€‘λ³΅λœ 값은 μ €μž₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

 

HashSet은 λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•©λ‹ˆλ‹€.

HashSet<E> name = new HashSet<E>();

HashSet은 μˆœμ„œ 상관없이, 쀑볡 없이 값을 μ €μž₯ν•œλ‹€κ³  ν–ˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒ μ½”λ“œλ₯Ό 톡해 확인해 λ΄…μ‹œλ‹€.

HashSet<String> bloodTypeSet = new HashSet<String>();
bloodTypeSet.add("A");
bloodTypeSet.add("B");
bloodTypeSet.add("O");
bloodTypeSet.add("AB");
bloodTypeSet.add("AB");
bloodTypeSet.add("AB");
bloodTypeSet.add("AB");
bloodTypeSet.add("AB");
bloodTypeSet.add("AB");
bloodTypeSet.add("AB");

System.out.println(bloodTypeSet); // [A, AB, B, O]

쀑볡이 없이 값을 μ €μž₯ν•œλ‹€λŠ” 것은 ν™•μΈν–ˆμ§€λ§Œ, λΆ„λͺ…νžˆ μ‚½μž… μ‹œ μˆœμ„œκ°€ μ—†λ‹€κ³  ν–ˆλŠ”λ° 좜λ ₯된 κ²°κ³Όλ₯Ό 보게 되면 무언가 μˆœμ„œκ°€ μžˆλŠ” κ²ƒμ²˜λŸΌ 좜λ ₯이 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μžλ°”μ—μ„œλŠ” μˆœμ„œκ°€ μ—†λ‹€ = κ°€μ Έμ˜¬ 수 μ—†λ‹€

인데 λŒ€μ²΄ μ–΄λ–»κ²Œ κ°€μ Έμ˜¨ 것이며 μ–΄λ–»κ²Œ μ €λ ‡κ²Œ 좜λ ₯이 된 κ±ΈκΉŒμš”?

 

사싀 toString()이 μž¬μ •μ˜ 된 κ²ƒμΈλ°μš”.

μž¬μ •μ˜λœ μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ©΄ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

μœ„ μ½”λ“œμ—μ„œ 두 번재 쀄 였λ₯Έμͺ½ ν•­ iterator() μ•žμ—λŠ” .thisκ°€ μƒλž΅λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

즉, 이 λ©”μ†Œλ“œμ„ μ μš©μ‹œν‚¨ 객체의 μ£Όμ†Œκ°’μ΄ λ“€μ–΄μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μ‹œλ§ν•΄, 우리 μ˜ˆμ œμ—μ„œ λ§ν•˜λ©΄ bloodTypeSetμ΄λΌλŠ” 객체의 μ£Όμ†Œκ°’μ— iterator() λ©”μ†Œλ“œλ₯Ό μ μš©μ‹œν‚¨ κ²ƒμž…λ‹ˆλ‹€.

 

iteratorλŠ” iterator만의 μˆœμ„œλ₯Ό λΆ€μ—¬ν•΄ μ€λ‹ˆλ‹€.

μš°λ¦¬κ°€ μ•Œκ³  μžˆλŠ” μˆœμ„œμΈ index 말고도 iterator만의 μˆœμ„œκ°€ μžˆλŠ”λ°μš”.

이 μˆœμ„œλŠ” λ‹€μŒ, λ‹€μŒ, λ‹€μŒ μ •λ„λ‘œ 이해할 수 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ μˆœμ„œκ°€ μ—†λ˜ Setμ΄λΌλŠ” νƒ€μž…μ—μ„œ iterator()λ₯Ό μ“°λŠ” μˆœκ°„ Iterator νƒ€μž…μœΌλ‘œ λ°”λ€ŒλŠ” κ²ƒμž…λ‹ˆλ‹€.

 

이제 이 λ‹€μŒ λ‹€μŒ λ‹€μŒ μš”μ†Œλ₯Ό κ°€μ Έμ˜€λ©΄μ„œ [κ³Ό ] 사이에 담아놓고 화면에 λ³΄μ—¬μ£ΌλŠ” 것이 toString()을 μž¬μ •μ˜ν•œ λ‚΄μš©μ΄μ˜€λ˜ κ²ƒμž…λ‹ˆλ‹€.

 

κ·ΈλŸ¬λ―€λ‘œ λ§Œμ•½μ— Set에 담겨 μžˆλŠ” μš”μ†Œ ν•˜λ‚˜ν•˜λ‚˜λ₯Ό 좜λ ₯ν•˜κ³  μ‹Άλ‹€λ©΄ λ‹€μŒκ³Ό 같은 방법을 μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.

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

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

좜λ ₯ν™”λ©΄

 

πŸ“Œ 이미 μ‘΄μž¬ν•˜λŠ” μš”μ†ŒμΈμ§€λ₯Ό νŒŒμ•…ν•˜λŠ” 방법 - hashCode와 equals μž¬μ •μ˜μ— κ΄€ν•΄μ„œ

κΈ°μ–΅λ‚˜μ‹œλ‚˜μš”? μžλ°”μ—μ„œλŠ” 객체λ₯Ό λ©”λͺ¨λ¦¬μ— ν• λ‹Ήν•΄μ„œ 좜λ ₯을 해보면 λ©”λͺ¨λ¦¬ μ£Όμ†Œμ²˜λŸΌ λ³΄μ΄λŠ” ν•΄μ‹œμ½”λ“œλ₯Ό μ•Œλ €μ£Όκ²Œ λ©λ‹ˆλ‹€.

μ΄λ•Œ 이 ν•΄μ‹œμ½”λ“œλŠ” μ ˆλŒ€ 쀑볡이 μ—†λ‹€κ³  ν–ˆμŠ΅λ‹ˆλ‹€.

그런데 λ§Œμ•½ μš°λ¦¬κ°€ μ‹€μ œ μ„œλΉ„μŠ€λ₯Ό ν•œλ‹€κ³  ν•˜λ©΄ new Student(1, "홍길동")객체와 new Student(1, "홍길동")은 κ°™λ‹€κ³  ν•΄μ•Όν•©λ‹ˆλ‹€.

그런데 μžλ°” μž…μž₯μ—μ„œλŠ” 두 객체의 λ©”λͺ¨λ¦¬ μ£Όμ†Œκ°€ λ‹€λ₯΄κΈ° λ•Œλ¬Έμ— λ‹€λ₯΄λ‹€κ³  μ•Œλ €μ€„κ²λ‹ˆλ‹€.

 

λ”°λΌμ„œ λ°˜λ“œμ‹œ μœ„ 두 객체가 κ°™λ‹€κ³  ν•˜κ³  μ‹Άλ‹€λ©΄ hashCode()와 equals() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•΄μ€˜μ•Όν•©λ‹ˆλ‹€.

 

λ¨Όμ € StudentλΌλŠ” 클래슀λ₯Ό ν•˜λ‚˜ 생성해 λ³΄κ² μŠ΅λ‹ˆλ‹€.

public class Student {
    private int number;
    private String name;
    
    public Student() {;}
    
    public Student(int number, String, name) {
        super();
        this.number = number;
        this.name = name;
    }
}

이제 hashCode()와 equals()λ₯Ό μž¬μ •μ˜ν•˜κΈ° 전에 객체λ₯Ό μƒμ„±ν•΄μ„œ 이 λ‘˜μ΄ 같은지 ν™•μΈν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

public class HashCodeTest {
   public static void main(String[] args) {
      Student student1 = new Student(1, "홍길동");
      Student student2 = new Student(1, "홍길동");
      
      System.out.println(student1.equals(student2)); // false
   }
}

λ‹Ήμ—°νžˆ μœ„μ—μ„œ μ„€λͺ…ν–ˆλ“―이 두 객체의 λ©”λͺ¨λ¦¬ μ£Όμ†Œκ°€ λ‹€λ₯΄κΈ° 떄문에 λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό λΉ„κ΅ν•΄μ£ΌλŠ” μžλ°”λŠ” λ‹€λ₯΄λ‹€κ³  μ•Œλ €μ€€ κ²ƒμž…λ‹ˆλ‹€.

이제 Student 클래슀둜 λŒμ•„κ°€ hashCode()와 equals()λ₯Ό μž¬μ •μ˜ ν•΄λ΄…μ‹œλ‹€.

@Override
public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + number;
  return result;
}

@Override
public boolean equals(Object obj) {
  if (this == obj)
     return true;
  if (obj == null)
     return false;
  if (getClass() != obj.getClass())
     return false;
  Student other = (Student) obj;
  if (number != other.number)
     return false;
  return true;
}

이제 λ‹€μ‹œ μœ„ HashCodeTest 클래슀λ₯Ό 싀행해보면 μ•„λž˜μ™€ 같은 좜λ ₯ 화면을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

좜λ ₯ ν™”λ©΄

이제 hashCode() 와 equals() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•¨μœΌλ‘œμ¨ λ™μΌν•œ 클래슀의 ν•„λ“œλ₯Ό ν• λ‹Ή 받은 두 객체의 값이 λͺ¨λ‘ κ°™λ‹€λ©΄ κ°™λ‹€κ³  νŒλ‹¨ν•˜κΈ° λ•Œλ¬Έμ—

이제 두 κ°μ²΄λŠ” 'κ°™λ‹€'라고 νŒλ‹¨λ©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ 학생 Set이 μžˆλ‹€λ©΄ μ—¬κΈ°μ—λŠ” λ™μΌν•œ ν•™μƒμ˜ 정보가 λ“€μ–΄κ°€λ©΄ μ•ˆλ  κ²ƒμž…λ‹ˆλ‹€.

λ§Œμ•½ Setμ•ˆμ— 이미 μžˆλŠ” ν•™μƒμ˜ 정보λ₯Ό λ‹€μ‹œ add ν•˜λ”λΌλ„ ν•˜λ‚˜λ§Œμ΄ μ‘΄μž¬ν•˜κ² μ£ ?

Student student1 = new Student(1, "홍길동");
Student student2 = new Student(1, "홍길동");

HashMap<Student> studentSet = new HashMap<Student>();

studentSet.add(student1);
studentSet.add(student2);

System.out.println(studentSet.size()); // 1

 

βž• HashSet으둜 ArrayListμ—μ„œμ˜ μ€‘λ³΅λœ μš”μ†Œλ₯Ό μ œκ±°ν•˜λŠ” 방법

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(10, 30, 30, 30, 20, 10, 90));
HashSet<Integer> dataSet = new HashSet<Integer>(datas);
datas = new ArrayList<Integer>(dataSet);

System.out.println(datas); // [20, 10, 90, 30]

 

728x90
LIST