ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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
Designed by Tistory.