본문 바로가기
JAVA

[JAVA] 컬렉션 - Set 계열

by Amy IT 2022. 6. 1.

Set 계열의 컬렉션 클래스는 저장 순서가 없어 중복 저장이 불가능하고, 저장된 위치를 알 수 없기 때문에 위치값으로 데이터를 얻을 수 없습니다. 데이터 정보를 출력하기 위해서 일반적으로 for-each문 또는 Iterator를 사용할 수 있습니다. 

 

 

▶ Set 인터페이스 메소드

 

Collection 인터페이스의 주요 메소드를 공통적으로 사용할 수 있습니다.

 

메소드 설명
boolean add(Object o)
boolean addAll(Collection c)
지정된 객체 또는 Collection의 객체들을 Collection에 추가
void clear() Collection의 모든 객체를 삭제
boolean isEmpty() Collection이 비어있는지 확인
int size() Collection에 저장된 객체의 개수
Object [] toArray() Collection에 저장된 객체를 배열로 변환
boolean contains(Object o) Collection에 o 요소를 포함하고 있는지 반환
Iterator<E> iterator() Collection에 저장된 데이터를 반복출력하기 위한 Iterator 인터페이스 반환
boolean remove(Object o)
boolean removeAll(Collection c)
지정된 객체 또는 Collection에 포함된 객체들을 삭제

 

 

 

▶ HashSet

 

(1) HashSet 생성 및 데이터 추가

String 타입의 제네릭을 사용하여 HashSet을 생성하고 데이터를 추가해 보겠습니다.

HashSet<String> set = new HashSet<>();
set.add("1");
set.add("2");
set.add("3");
set.add("4");
set.add("5");
//set.add(10); //저장 불가
System.out.println(set); //[1, 2, 3, 4, 5]

제네릭을 사용하였기 때문에 String 타입이 아닌 데이터를 저장하려고 하는 경우 컴파일시 오류가 발생하여 잘못된 데이터 저장을 방지할 수 있습니다. 참조변수 이름만으로도 toString() 메소드가 호출되어 안에 저장된 모든 데이터를 문자열로 반환받을 수 있습니다.

 

(2) HashSet 메소드 활용

Collection 인터페이스 내 메소드들을 HashSet 클래스에서 실제 구현하고 있기 때문에 size(), contains() 등 Collection 인터페이스의 공통된 메소드들을 사용할 수 있습니다. 

System.out.println("길이: "+set.size()); //5
System.out.println("포함여부: "+set.contains("1")); //true
System.out.println("set이 비어있는지 여부: "+set.isEmpty()); //false
System.out.println("5 삭제: "+set.remove("5")); //true
System.out.println(set); //[1, 2, 3, 4]

 

(3) 데이터 순회

전체 데이터를 순회하고 싶을 때는 for-each문 또는 Iterator 인터페이스를 사용할 수 있습니다. Iterator 인터페이스는 순회 방법을 통일시켜주는 반복처리 인터페이스로서, Iterator를 이용하면 공통된 메소드로 순회할 수 있습니다. hasNext() 메소드는 다음 요소가 있는지 여부를 boolean 값으로 반환하고, next() 메소드는 다음 요소를 반환합니다. 

//(1)for-each문
for (String s : set) { 
	System.out.println(s);
}
//toArray() 이용 Object 배열로 변경후 for-each문
Object [] arr = set.toArray();
for (Object o : arr) {
	System.out.println(o);
}
//(2)Iterator
Iterator<String> it = set.iterator(); //set에 들은 데이터를 Iterator 객체에 담아서 리턴
while (it.hasNext()) {
	String s = it.next(); 
	System.out.println(s);
}

 

제네릭을 지정했기 때문에 for-each문에서 데이터를 꺼내올 때도 String 타입, Iterator의 제네릭도 String 타입으로 지정됩니다. next() 메소드로 데이터를 꺼내올 때도 형변환이 필요 없습니다. 

 

(4) Person 타입 HashSet

이번에는 Person 클래스 타입의 HashSet을 생성해 보겠습니다. 

class Person {
	private String name;
	private int age; 
	private String address;
	public Person(String name, int age, String address) {
		super();
		this.name = name;
		this.age = age;
		this.address = address;
	}
	public String getName() {
		return name;
	}
}
public class SetTest3 {
	public static void main(String[] args) {
		Set<Person> set = new HashSet<>();
		Person kkkk = new Person("유관순", 17, "서울");
		set.add(new Person("홍길동", 20, "서울"));
		set.add(new Person("이순신", 44, "전라"));
		set.add(new Person("이순신", 44, "전라")); //new 두번하면 다른 객체 둘다 저장됨 
		set.add(kkkk);
//		set.add(kkkk); //중복불가, 저장안됨 
		for (Person p : set) {
			System.out.print(p.getName()+" ");
		}
		System.out.println();
		Iterator<Person> it = set.iterator();
		while (it.hasNext()) {
			System.out.print(it.next().getName()+" ");
		}
	}
}

Set 계열은 중복 저장이 불가능하다고 하였습니다. 컬렉션에 Person 객체들을 추가하는데, 이순신의 경우 new 키워드를 이용하여 서로 다른 객체를 두 번 생성하였기 때문에 두 번 추가가 성공적으로 되었습니다. 그런데 유관순의 경우 유관순 객체 생성 후 kkkk라는 변수에 참조시키고, kkkk라는 참조변수를 통해 컬렉션에 객체를 추가하고 있기 때문에, 똑같은 객체를 두 번 넣게 되어 두 번째는 저장이 실패하게 됩니다. 따라서 위와 같은 출력 결과를 확인할 수 있습니다. 

 

 

 

▶ LinkedHashSet

 

LinkedHashSet은 데이터가 저장되는 순서대로 순서를 유지합니다. 

Set linkedSet = new LinkedHashSet();
linkedSet.add("1");
linkedSet.add(10);
linkedSet.add("100");
linkedSet.add("Hello");
for (Object x : linkedSet) {
	System.out.print(x+" ");
}

 

 

 

▶ TreeSet

 

TreeSet은 데이터 추가시 자동으로 오름차순 정렬하여 저장됩니다. 

TreeSet<String> s = new TreeSet<>();
s.add("hello");
s.add("aello");
s.add("bello");
s.add("xello");
s.add("pello");
System.out.println(s); //알파벳순 
//다양한 함수들 제공됨 
System.out.println("첫번째요소: "+s.first());
System.out.println("마지막 요소: "+s.last());
System.out.println("지정된값 앞요소(exclusive): "+s.headSet("hello")); //hello앞에걸 다 모아서 출력 
System.out.println("지정된값 뒤요소(inclusive): "+s.tailSet("hello")); //hello뒤에걸 다 모아서 출력 
System.out.println("범위요소: "+s.subSet("bello", "xello")); //bello부터 xello전까지

 

 

댓글