-
[Java] 컬렉션 Set 계열IT/개발(자바, 서블릿, 스프링 등) 2020. 1. 28. 09:13
Set 계열
Set은 List와 다르게 저장되는 데이터 순서가 의미가 없다. Set은 해시코드라는 개념을 사용하여 데이터를 저장하므로 데이터가 저장된 순서를 알 수 없다. 또한 저장되는 데이터의 해시코드는 데이터를 구분하는 값으로 사용되므로 중복될 수 없다. 기본적으로 해시코드는 Object 클래스의 hashCode() 메서드에서 반환하는 값을 사용한다. Set의 가장 큰 장점은 해시코드를 사용하여 데이터를 처리하므로 컬렉션 중에서 가장 빠르게 검색한다.
HashSet 클래스
HashSet 클래스의 역할을 설명할 때 좋은 예가 바로 로또다. 로또는 1부터 45까지의 숫자 중 6개의 숫자를 추첨하는 방식으로 진행한다. 다음은 5개의 로또를 구매한 전표다.
로또 번호를 자동으로 추출하는 프로그램은 숫자 6개를 만들 때 1에서부터 45 사이의 숫자를 순서에 상관없이 랜덤하게 선택하고 중복된 숫자가 있을 때는 중복을 제거하도록 구현되어 있다. 이처럼 저장되는 데이터의 순서가 중요하지 않고 데이터가 중복되지 않는 컬렉션이 필요할 때 HashSet을 사용한다. 로또 번호는 5개의 HashSet 객체가 있고, 각 HashSet에는 중복되지 않는 6개의 숫자들이 저장되어 있다. HashSet에서 데이터가 저장되는 순서는 어떠한 의미도 없다.
package com.ruby.java.ch10; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Random; public class Test { public static void main(String[] args) { lotto_generator(5); } public static void lotto_generator(int n) { Random number = new Random(); HashSet<Integer> lotto = null; for (int i = 0; i < n; i++) { lotto = new HashSet<Integer>(); for (int j = 0; lotto.size() <= 6; j++) { lotto.add(number.nextInt(46)); } List<Integer> L = new ArrayList<Integer>(lotto); Collections.sort(L); System.out.println(L); } } }
Set 계열의 컬렉션 객체들은 중복된 값을 저장할 수 없다. 내부적으로 기존의 저장된 데이터와 새로 저장될 데이터를 비교하는 작업이 수행된다는 의미다. Set 계열 컬렉션 API들은 데이터를 비교할 때 다음과 같은 순서로 작업한다.
Object 클래스의 hashCode() 메서드의 반환값을 비교한다.
Object 클래스의 equals() 메서드의 반환값으로 판단한다.
비교 작업은 대상 객체들의 hashCode()에서 반환되는 값을 비교하고 만일 같으면 equals() 메서드를 실행하여 한 번 더 판단한다. hashCode()와 equals() 메서드 모두 Object 클래스에 선언된 메서드다. 비교 내용을 변경하려면 오버라이딩하면 된다.
package com.ruby.java.ch10; import java.util.HashSet; import java.util.Iterator; class User { String ssn; // 주민번호 String name; // 이름 User(String ssn, String name) { this.ssn = ssn; this.name = name; } @Override public String toString() { return ssn + ":" + name; } @Override public int hashCode() { return Integer.parseInt(ssn); } @Override public boolean equals(Object obj) { boolean result = false; User u = (User) obj; if (this.ssn.equals(u.ssn)) result = true; return result; } } public class Test2 { public static void main(String[] args) { User u1 = new User("123", "김푸름"); User u2 = new User("123", "김푸름"); HashSet<User> users = new HashSet<User>(); users.add(u1); users.add(u2); Iterator<User> iter = users.iterator(); while (iter.hasNext()) System.out.println(iter.next()); } } [실행결과] 123:김푸름 123:김푸름
u1, u2의 해시코드값은 다르게 부여되기 때문에 데이터는 같지만 다른 객체로 처리된다. 아래는 hashCode()와 equals() 메서드를 오버라이딩한 예이다.
class User { String ssn; //주민번호 String name; //이름 User(String ssn, String name){ this.ssn = ssn; this.name = name; } @Override public String toString(){ return ssn+":"+name; } @Override public int hashCode(){ return Integer.parseInt(ssn); } @Override public boolean equals(Object obj){ boolean result = false; User u = (User) obj; if(this.ssn.equals(u.ssn)){ result = true; } return result; } } public class Test3 { public static void main(String[] args) { User u1 = new User("123", "김푸름"); User u2 = new User("123", "김푸름"); HashSet<User> users = new HashSet<User>(); users.add(u1); users.add(u2); Iterator<User> iter = users.iterator(); while (iter.hasNext()) System.out.println(iter.next()); } } [실행결과] 123:김푸름
'IT > 개발(자바, 서블릿, 스프링 등)' 카테고리의 다른 글
[Java] 기본 입출력 작업 (0) 2020.01.30 [Java] 입출력 개요 (0) 2020.01.29 [Java] 컬렉션 Map 계열 (0) 2020.01.28 [Java] 컬렉션 개요 (0) 2020.01.27 [Java] 어노테이션 (0) 2020.01.25