[Java] Collection Framework - Set
- 컴퓨터 시스템에서 데이터를 효율적으로 저장 및 관리하는 방법(자료구조론)
=> 자바에서 자료구조를 구현하여 제공하는 클래스들의 모음이다.
=> 기타 대부분의 언어들은 자료구조를 개발자가 직접 구현해야 하지만
자바는 클래스 내의 메서드를 통해 자료구조를 활용할 수 있도록 지원해준다.
- java.util 패키지에 클래스 및 인터페이스로 지공된다.
🔍 컬렌션 3대 인터페이스
Set, List, Map
=> 각 인터페이스를 구현한 구현체 클래스들이 제공된다.
=> 이 중, Set과 List 계열은 Collection 인터페이스를 공통으로 상속받았기 때문에 대부분의 메서드가 동일하다.
1. Set 계열
- 저장 순서가 유지되지 않는다 => 즉, 인덱스 사용이 불가능 하다
- 데이터 중복을 허용하지 않는다. 중복데이터는 애초에 저장되지 않는다.
그래서 아주 효율적인 중복제거 수단으로 사용된다.
- Set 계열의 구현체 클래스 : HashSet, TreeSet 등
✍ HashSet 객체 생성하기
public static void main(String[] args) {
Set set = new HashSet(); // HashSet 객체 생성
System.out.println("Set 객체가 비어있는가? : " + set.isEmpty());
System.out.println("Set 객체에 저장된 요소 갯수 : " + set.size());
System.out.println("Set 객체의 모든 요소 : " + set.toString());
System.out.println("Set 객체의 모든 요소 : " + set); // toString() 생략 가능
}
원래는 HashSet set = new HashSet();의 형태지만
위의 코드는 HashSet을 Set으로 업태스팅하여 작성하였다.
대부분의 메서드를 부모 인터페이스인 Set 인터페이스가 보유중이므로
업캐스팅 상태에서도 대부분의 기능을 사용하는 데 문제가 없기 때문이다.
isEmpty() 메서드는 객체의 데이터 유무를 판단하여 리턴해주고
set.size() 메서드는 배열의 length와 유사하다. 컬렉션의 크기를 리턴해준다
객체의 모든 요소를 출력하기 위해서는 참조변수 그 자체를 그냥 출력하거나 toString()을 붙여주면 된다.
✍ Set 객체에 데이터 추가하기
set.add(1);
set.add(100);
set.add("abcde");
set.add(3.14);
set.add('A');
System.out.println("Set 객체의 모든 요소 : " + set);
=> set.add() 를 통해 데이터를 추가 할 수 있다. 단, 저장 순서가 유지 되지 않기 때문에 순서는 달라진다
데이터 타입 종류와 상관없이 모든 데이터들을 입력할 수 있다.
💻
✍ Set 객체에 저장된 요소 확인하기
System.out.println(set.contains(1));
contains() 메서드를 통해 set에 저장된 요소의 존재 유뮤를 리턴받을 수 있다.
💻
1은 저장되어 있기 때문에 true가 리턴된다.
✍ 객체에 저장된 요소 삭제하기
set.remove(1);
System.out.println(set);
remove() 메서드를 통해 요소를 삭제할 수 있다. 삭제한 후 모든 요소를 출력해보면
💻
1이 삭제된 걸 확인할 수 있다.
✍ addAll()
새로운 set 인스턴스를 생성한 후 기존에 저장되어 있던 데이터를 전부 추가할 수 있다.
public static void main(String[] args) {
Set set = new HashSet(); // HashSet 객체 생성
set.add(1);
set.add(100);
set.add("abcde");
set.add(3.14);
set.add('A');
Set set2 = new HashSet(); // set2 인스턴스 생성
set2.addAll(set); // set의 모든 요소를 set2에 추가
System.out.println(set2); // set2의 모든 요소 출력
}
=> set2 인스턴스를 생성한 후
이미 set.add()를 통해 추가되어 있던 set의 모든 요소를 그대로 set2에 저장할 수 있다.
addAll()이후 set2의 모든 요소를 출력해보면
💻
set의 모든 요소가 set2에 저장된 걸 확인 할 수 있다.
✍ 저장된 요소 모두 제거하기
set2.clear();
System.out.println(set2);
clear() 메서드를 통해 저장된 요소를 모두 제거할 수 있다.
💻
=> 요소가 모두 제거된 걸 확인할 수 있다
주의!!!!!!!!!!!!!!!!!!!!!!!!
HastSet등 컬렉션 객체 생성 시 파라미터로 다른 컬렉션 객체를 전달하면
해당 컬렉션 객체의 요소를 갖는 새로운 컬렉션 객체가 생성된다.
Set set3 = new HashSet(set); // set3 객체 생성
System.out.println("set3의 모든 요소 : " + set3);
System.out.println("set의 모든 요소 : " + set);
여기서 주의할 점은 !
데이터가 저장된 주소를 공유하는 것이 아닌 실제 요소를 복사하여 전달하므로
저장된 요소는 갖지만 주소를 다르게 생성된다.
Set set3 = new HashSet(set);
System.out.println("set3의 모든 요소 : " + set3);
System.out.println("set의 모든 요소 : " + set);
System.out.println("set과 set3객체는 동일한 객체인가? : " + (set==set3));
System.out.println(set.equals(set3));
💻
set3 인스턴스를 생성할 때 파라미터로 set을 전달하여 set의 요소가 모두 복사되었다.
요소는 동일하지만 다른 주소값을 가진 객체이다.
🔍 TreeSet 객체 활용하기
TreeSet 객체를 활용하면 같은 타입 데이터가 저장된 Set 객체 정렬이 가능하다.
주의! 반드시 같은 타입 데이터만 저장해야한다!
=> 이진 탐색 트리 (Binary Search Tree)를 개량한 레드-블랙(Red-Black Tree) 구조 사용
수치데이터는 수치의 크기순으로 오름차순 정렬되며 ( 0 -> 9 )
문자데이터는 문자 코드값의 크기 순으로 오름차순 정렬되므로
수치 데이터와 문제 데이터의 정렬 결과는 다를 수 있다 !
Set set4 = new HashSet(); // set4 객체 생성
// 요소 추가
set4.add(100);
set4.add(99);
set4.add(500);
set4.add(2);
set4.add(35);
set4.add(999);
System.out.println(set4); // 요소 출력
Set<Integer> set5 = new TreeSet(set4); // set4 요소를 set5에 추가 => TreeSet 자동 정렬
System.out.println(set5); // 요소 출력
set4에 저장한 요소들을 set5 TreeSet으로 정렬 한다
💻
set4와 set5의 차이를 확인할 수 있다. set5는 TreeSet 객체를 활용하였으므로 요소들이 정렬되어 출력되었다.
✍ Set 계열의 모든 요소를 반복문을 통해 출력하기
for(int i : set5) {
System.out.println(i);
}
향상된 for문으로 set 객체의 요소를 출력할 수 있다.
💻