JAVA
컬렉션 프레임워크 - Set 계열 인터페이스
jiyoon12
2025. 5. 7. 11:02
1. 주요 특징
- 중복 허용 불가 : Set에 같은 요소를 추가하려고 하면, 추가가 되지 않는다. 즉, 모든 요소가 고유해야 하며, 이미 존재하는 요소를 추가할 경우 무시한다.
- 순서 보장하지 않음 : Set은 요소들의 순서를 유지하지 않는다. 요소들이 내부적으로 어떻게 저장되고 관리되는지는 Set을 구현하는 클래스에 따라 다르다. 따라서 요소들이 추가된 순서와 Set에서 요소를 순회할 때의 순서가 다를 수 있다.
- 값의 유일성 : Set은 각 요소의 유일성을 보장한다. 이는 주로 요소의 equals()와 hashCode() 메서드를 사용하여 결정된다. 두 객체가 같다고 판단되면, 둘 중 하나만 Set에 저장된다.
2. 사용 예시
- 아이디 목록 관리: 사용자 아이디는 유일해야 하므로 **Set**을 사용하여 중복 없이 관리할 수 있습니다.
- 주민등록번호: 각 사람의 주민등록번호는 고유한 값이므로, 이를 **Set**에 저장하여 중복 등록을 방지할 수 있습니다.
- 직원 번호: 회사에서 각 직원에게 부여한 고유한 사번을 **Set**을 이용해 관리할 수 있습니다.
3. 주요 메서드
- Set 인터페이스는 Java Collection Framework 내에서 중복을 허용하지 않는 유니크한 아이템들을 저장하는 데 사용된다.
- add(E e) : 지정된 요소를 세트에 추가한다. 요소가 세트에 이미 존재하는 경우는 추가되지 않는다.
- boolean add(E e);
- 반환값 : 요소가 세트에 성공적으로 추가되면 true, 이미 존재하는 경우는 false를 반환한다.
- remove(Object o) : 지정된 요소를 세트에서 제거한다.
- boolean remove(Object o);
- 반환값 : 요소가 세트에서 성공적으로 제거되면 true, 그렇지 않으면 false를 반환한다.
- contains(Object o) : 세트가 지정된 요소를 포함하고 있는지 여부를 확인한다.
- boolean contains(Object o);
- 반환값 : 요소가 세트에 존재하면 true, 그렇지 않으면 false를 반환한다.
- size() : 세트에 저장된 요소의 수를 반환한다.
- int size();
- 반환값 : 세트에 있는 요소의 총 수를 반환한다.
- isEmpty() : 세트가 비어 있는지 여부를 확인한다.
- boolean isEmpty();
- 반환값 : 세트가 비어 있으면 true, 하나 이상의 요소가 있으면 false를 반환한다.
- clear() : 세트에서 모든 요소를 제거한다.
- void clear();
- 이 메서드는 세트를 비워서 요소가 없는 상태로 만든다.
- iterator() : 세트의 요소에 접근할 수 있는 반복자(iterator)를 반환한다.
- Iterator<E> iterator();
- 이 반복자를 사용하여 세트의 요소를 순차적으로 접근할 수 있다.
package collections;
import java.util.*;
public class MySetTest {
public static void main(String[] args) {
// 계층 구조 확인 (업캐스팅된 상태)
Set<Integer> mTestSet = new HashSet<>();
// 사용방법
// HashSet : 중복된 요소를 허용하지 않고, 순서가 없는 자료 구조
HashSet<Integer> numberSet = new HashSet<>();
// 요소 추가하기
numberSet.add(500);
numberSet.add(11); // 중복 값, 추가되지 않음
numberSet.add(200);
numberSet.add(33);
numberSet.add(355); // 중복 값, 추가되지 않음
System.out.println("numberSet의 크기 : " + numberSet.size());
// 요소 제거
numberSet.remove(1); // remove 할 때 없는 요소를 선택하더라도 오류 발생하지 않음
System.out.println("numberSet의 크기 : " + numberSet.size());
// 자료구조는 반복문과 함께 많이 사용 된다.
// for (int i = 0; i < 10; i++) { } - 인덱스 for 구문은 사용 불가
// 향상된 for 구문으로 set 계열의 데이터를 순회 시킬 수 있다.
for (Integer num : numberSet) {
System.out.println("num 값 확인 : " + num);
}
// Set 계열을 Iterator 타입으로 변환해서 순회 시킬 수 있었다. 지금도 가능
System.out.println("-----------------------------");
Iterator<Integer> iter = numberSet.iterator(); // 형 변환 처리 Set --> Iterator 형 변환
while (iter.hasNext()) {
System.out.println("값 : " + iter.next()); // 요소를 반환 처리 한다.
}
System.out.println("------------------------");
// Set 계열 자료 구조 선언 (정수값만 담을 수 있고 중복 허용 불가)
HashSet<Integer> lottoNumbers = new HashSet<>();
while (lottoNumbers.size() < 6) {
lottoNumbers.add(getRandomNumber());
}
System.out.println("무작위로 선택된 로또 번호 6개 : " + lottoNumbers.toString());
// HashSet 데이터 타입을 ArrayList 객체 생성시에 즉, 생성자에 인자값을 넣을 수 있도록 설계됨
ArrayList<Integer> sortedList = new ArrayList<>(lottoNumbers);
// 정렬하기 기능 사용해보기
Collections.sort(sortedList);
System.out.println("정렬된 로또 번호 확인 : " + sortedList);
} // end of main
// 무작위 1 부터 45 까지 랜덤 번호 생성 함수
public static int getRandomNumber() {
Random random = new Random();
return random.nextInt(45) + 1;
}
} // end of class
- 실습 과제
- 고유 사용자 ID 관리 시스템
- 상황 설명 : 웹사이트에 접속하는 사용자의 ID를 관리하는 시스템을 개발합니다. 사용자 ID는 고유해야 하며 중복을 허용하지 않습니다. 시스템은 사용자가 로그인할 때마다 ID를 체크하고, 새로운 사용자 ID를 등록할 때 중복을 방지합니다.
package collections;
import java.util.HashSet;
import java.util.Random;
import java.util.Scanner;
public class UniqueUserIDSystem {
// 상황 -> 사용자가 키보드로 입력한 ID 데이터를 많이 저장해야 한다.
// 고유한 값이어야 한다. 메모리상으로 관리할 예정
private HashSet<String> registeredIDs;
public UniqueUserIDSystem() {
registeredIDs = new HashSet<>();
// printAllIDs 메서드를 테스트 하기 위해서 샘플 데이터 입력해 보기
// 샘플 데이터 입력 - 추후 삭제 예정
registeredIDs.add("홍길동");
registeredIDs.add("이순신");
registeredIDs.add("야스오");
}
// 사용자 ID를 등록하는 메서드
public boolean addUserID(String userId) {
return registeredIDs.add(userId);
}
// 사용자 ID를 출력하는 메서드를 직접 만들어 보자. - 전체 출력
// 메서드 이름을 동사로 시작하는 것이 권장사항이다.
public void getOutPut() {
for(String id : registeredIDs){
System.out.println("id : " + id);
}
}
public void printAllIDs() {
// registeredIDs 순회해서 콘솔 창에 출력 하고자 한다.
// 초기화 for 구문, Iterator 로 형변환해서 순회 시킬 수 있다.
// HashSet 안에 요소가 아무것도 없다면
if(registeredIDs.isEmpty()){
System.out.println("등록된 사용자 ID가 없습니다");
return; // 실행의 제어권 반납
}
for (String id : registeredIDs){
System.out.println("id : " + id);
}
System.out.println("총 등록된 ID 개수 : " + registeredIDs.size());
}
// 시스템을 실행할 메서드
public void start() {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("사용하고 싶은 ID를 입력하세요 종료하려면 'exit' 입력");
String input = scanner.nextLine().trim(); // .trim() 공백 제거
// 사용자가 키보드에서 값을 넣지 않고 바로 엔터를 누르는 경우
// 빈 입력 처리
if (input.isEmpty()) {
System.out.println("ID를 입력해주세요");
continue;
}
if ("exit".equals(input)) {
System.out.println("시스템을 종료 합니다.");
break;
}
boolean isRegistered = addUserID(input);
if (isRegistered) {
System.out.println("새로운 사용자 ID가 등록되었습니다.");
} else {
System.out.println("이미 등록된 사용자 ID 입니다.");
}
} // end of while
scanner.close(); // 자원 해제
} // end of start()
// 메인 함수
public static void main(String[] args) {
UniqueUserIDSystem idSystem = new UniqueUserIDSystem();
idSystem.start();
idSystem.printAllIDs();
idSystem.getOutPut();
}
} // end of class