본문 바로가기
JAVA

컬렉션 프레임워크 Set 컬렉션

by 요리하다그만둠 2022. 5. 30.

List 컬렉션은 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지되지는 않습니다. 또한 객체를 중복 저장할 수 없고

하나의 null만 저장할 수 있어 set 컬렉션은 수학의 집합에 비유될 수 있습니다.

사진 출처 : JAVA EE: Java : Collection Framework : Hierarchy(Iterable, Collection) (ramj2ee.blogspot.com)

 

 

Set컬렉션에는 

HashSet, LinkedHashSet, TreeSet 등이 있습니다.

 

 

위에 메소드는 Set 컬렉션에서 공통적으로 사용 가능한 Set 인퍼에이스의 메서드입니다. 인덱스로 관리하지 않기 때문에 매개 값으로 갖는 메서드가 없습니다.

Set<String> set = ...;
set.add("홍길동"); // 객체를 추가합니다.
set.add("홍길순");
set.remove("홍길동"); // 객체를 삭제합니다.

Set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드가 없는데 대신 전체 객체를 대상으로 한 번씩 반복해서 가져오는

반복자(Iterator)를 제공합니다.

반복자는 Iterator 인터페이스를 구현한 객체인데 Iterator() 메서드를 호출하면 얻을 수 있습니다.

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

 

리턴 타입 메소드명 설명
boolean hasNext() 가져올 객체가 있으면 true을 리턴 없으면 false를 리턴합니다.
E next() 컬렉션에서 하나의 객체를 가져옵니다.
void remove() Set 컬렉션에서 객체를 제거합니다.
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) { // 저장된 객체 수만큼 루핑합니다.
	//String 객체 하나를 가져옵니다.
    String str = iterator.next();
}
// Iterator를 사용하지 않더라도 향상된 for문을 이용해서 전체 객체를 반복 가능

Set<String> set = ...;
for(String str : set) {
// 저장된 객체 수만큼 루핑합니다.
}

Set컬렉션에서 Iterator의 next() 메소드로 가져온 객체를 제거하고 싶다면 remove() 메서드를 호출하면 됩니다.

Iterator의 메소드이지만 실제 Set 컬렉션에서 객체가 됩니다.

while(iterator.hasNext()) {

	String str = iterator.next();
    if(str.equals("홍길동")) {
    	iterator.remove();
        // Set 컬렉션에서 홍길동 제거
    }
}

 

HashSet

HashSet은 Set 인터페이스의 구현 클래스이고 HashSet을 생성하기 위해서는 밑에처럼 기본 생성자를 호출하면 됩니다.

Set<E> set = new HashSet<E>();

타입 파라미터 E에는 컬렉션에서 저장할 객체 타입을 지정하면 됩니다. 예를 들어서 String 객체를 저장하는 HashSet은

Set<String> set = new HashSet<String>();

이렇게 생성할 수 있습니다.

HashSet은 객체들을 순서 없이 저장하고 동일한 객체는 저장 하지 않습니다. HashSet이 판단하는 동일한 객체는 꼭 같은 인스턴스를 뜻하지 않고 HashSet은 객체를 저장하기 전에 먼저 객체의 hashCode() 메서드를 호출해서 해시 코드를 얻어냅니다. 그리고 이미 저장되어 있는 객체들의 해시 코드를 비교하고 만약 동일한 해시 코드가 있다면 equlas() 메서드로 두 객체를 비교해보고 true가 나오면 동일한 객체로 판단하고 중복 저장을 하지 않습니다.

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

public class Ex5 {

	public static void main(String[] args) {
		Set<String> set = new HashSet<String>();
		
		set.add("Java");
		set.add("Spring");
		set.add("JSP");
		set.add("Java");
		set.add("phyton");
		// Java는 중복이라 하나의 객체만 저장될것임
		int size = set.size(); // 저장된 객체 수 얻기
		System.out.println("set의 사이즈 : " + set.size());
		
		Iterator<String> it = set.iterator(); // 반복자 생성
		while(it.hasNext()) { // it의 객체수만큼 반복한다
			String element = it.next(); //한개의 객체만 들고온다.
			System.out.println("\t"+element);
		}
	}
}

 

코드 실행시 Java 객체 하나가 중복이라 저장되지 않는 것을 확인할 수 있다.

 

 

 

 

 

다시 저장된값을 삭제하는 방법

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

public class Ex5 {

	public static void main(String[] args) {
		Set<String> set = new HashSet<String>();
		
		set.add("Java");
		set.add("Spring");
		set.add("JSP");
		set.add("Java");
		set.add("phyton");
		// Java는 중복이라 하나의 객체만 저장될것임
		int size = set.size(); // 저장된 객체 수 얻기
		System.out.println("set의 사이즈 : " + set.size());
		
		Iterator<String> it = set.iterator(); // 반복자 생성
		while(it.hasNext()) { // it의 객체수만큼 반복한다
			String element = it.next(); //한개의 객체만 들고온다.
			System.out.println("\t"+element);
		}
        ========================================================================
		
        set.remove("JSP"); // 한개의 객체 삭제
		set.remove("phyton"); // 한개의 객체 삭제
		
		System.out.println("총 객체수 : " + set.size());
		// 저장된 객체수 얻기
		
		it = set.iterator(); // 반복자 얻기
		
		while(it.hasNext()) { // it의 객체수만큼 반복
			String element = it.next(); //한개의 객체만 들고온다.
			System.out.println("\t"+element);
		}
		
		set.clear(); // 모든 객체를 제거하고 비웁니다.
		if(set.isEmpty()) {
			System.out.println("비어 있습니다.");
		}
	}
 }

출력 결과.

 

 

 

 

 

 

 

 

 

인스턴스를 사용하여 이름과 나이가 동일한 객체 추가 시 중복 저장 안 되는지 확인해보자

package Ex00;

public class Member {
	// 필드생성
	public String name;
	public int age;
	
	// 생성자
	public Member(String name, int age) {
		this.name = name;
		this.age =age;
	}
	@Override 
	public boolean equals(Object obj) {
		// name과 age가 값이 같으면 true를반환
		if(obj instanceof Member) {
			// instanceof 연산자를 이용 
			// object가 type이거나 type을 상속받는 클래스라면 true리턴할것임
			Member member = (Member) obj;
			return member.name.equals(name) && (member.age == age);
		}else {
			return false;
		}
	}
	@Override
	public int hashCode() { // name과 age가 같으면 동일한 hashcode를 리턴해준다.
		return name.hashCode() + age;
	} 	// String의 hashCode() 이용한다.
}

먼저 hashCode()와 equlas() 메서드를 재정의 해준다

다음 데이터 저장이 한 개만 되는지 확인해본다.

package Ex00;

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

public class HashSetEx {

	public static void main(String[] args) {
		Set<Member> set = new HashSet<Member>();
		
		set.add(new Member("홍길동",15));
		set.add(new Member("홍길동",15));
		// 인스턴스는 다르지만 내부 데이터가 동일하여 한가지만 등록될것임
		
		System.out.println("총 객체수 : " + set.size());
	}

}

실행결과 객체수 1개만 등록되었습니다.

'JAVA' 카테고리의 다른 글

멀티 스레드  (0) 2022.06.02
Map 컬렉션  (0) 2022.05.31
컬렉션 프레임워크 LinkedList  (0) 2022.05.30
컬렉션 프레임워크 Vector  (0) 2022.05.30
컬렉션 프레임워크 ArrayList  (0) 2022.05.30