[Java] Set 컬렉션의 HashSet을 알아보자!

2021-01-05


오늘은 Set 컬렉션 중 HashSet에 대하여 알아보도록 하자. 우선 Set의 특성은 중복된 타입의 객체는 저장되지 않는다는 점이며, HashSet 역시 이와 같은 특징을 가지고 있다. 어렵지 않은 내용이니 바로 코드로 구현을 해보자.


package hHashSet;

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

public class main {

	public static void main(String[] args) {
		
		Set<String> set = new HashSet<>();
		//순서없이 저장되며, 중복된 값은 저장되지 않는다.
		
		set.add("aaa");
		set.add("bbb");
		set.add("ccc");
		set.add("ddd");
		set.remove("ccc");
		
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String str = it.next();
			System.out.println(str);
		}
	}
}

[ Set< 제네릭 타입(자신이 넣고자 하는 타입) > set변수명 = new HashSet <>(); ] 로 선언을 해주면 된다. 코드와 같이 add 메서드를 통해서 값을 추가할 수 있으며, remove메서드를 통해 원하는 객체를 제거할 수 있다.

Set은 인덱스를 검색해서 가져오는 메서드가 없어 Iterator와 Stream등을 통해 전체 객체를 반복해서 출력할 수 있다. 출력된 내용을 확인해보면, 중복된 객체 "aaa"는 하나만 저장되어 있으며, 제거된 "ccc"는 출력되지 않는 것을 확인할 수 있다.


이제 임이의 클래스를 가지는 HashSet 사용법을 알아보자 우선 사용할 클래스 People은 아래와 같다.

package hHashSet;

public class People {
	
	private String name;
	private int age;
	
	public People(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof People) {
			People human = (People) obj;
			return human.name.equals(name) && human.age == age;
		}else {
			return false;
		}
	}
	
	@Override
	public int hashCode() {
		return name.hashCode() + age;
	}

}

이름과 나이를 필드로 가지면 모두 Getter와 Setter로 접근이 가능하도록 해주었다. 또한 각 필드 값 비교를 위해 equals와 hashCode 값을 재정의 해주었다. 다음 아래는 실행 클래스이다.

package hHashSet;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Stream;

public class main {

	public static void main(String[] args) {
		Set<People> pSet = new  HashSet<>();
		
		pSet.add(new People("aaa", 25));
		pSet.add(new People("bbb", 35));
		pSet.add(new People("ccc", 25));
		pSet.add(new People("aaa", 25));
		
		Iterator<People> itp = pSet.iterator();
		while(itp.hasNext()) {
			People p =itp.next();
			//Iterator객체를 하나씩 받는 People의 p 변수 선언
			System.out.println(p.getName()+ " " + p.getAge());
			//p변수를 통해 name 과 age를 출력
		}
		
		System.out.println("________________________");
		
		
		Stream<People> sSet = pSet.stream();
		//pSet의 스트림 변수 sSet 선언
		sSet.forEach(p -> System.out.println(p.getName() + " " + p.getAge()));
		//forEach를 통해 모든 객체를 하나씩 돌면서 name과 age를 출력한다.
	}
}

사실 사용법은 크게 다르지 않다. 제네릭 타입에 People을 선언해주고 이후 add메서드를 사용해 새로운 People 객체를 하나씩 넣어주면 된다. 다만 이번에는 객체의 출력을 Iterator / Stream 두 가지 모두를 이용해서 출력해 보았다. 사실 Stream을 사용할 줄 알면, Iterator는 사용할 일이 거의 없는데, 해당 내용을 방대하니 나중에 따로 정리하도록 하겠다.

이후 출력된 데이터 확인 결과 Iterator / Stream 모두 동일한 값을 도출하는 것을 확인할 수 있다.