Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- SQL
- oracle
- Exception
- Javascript
- Linux
- git
- JPA
- 트랜잭션
- docker
- 차이점
- group by
- MongoDB
- 호이스팅
- analytics4
- 자바
- mssql
- 추상클래스
- mysql
- 티스토리챌린지
- 리눅스
- spring
- PostgreSQL
- 오블완
- DBMS
- rsync
- Python
- MariaDB
- IntelliJ
- java
- 명령어
Archives
- Today
- Total
hanker
Java - Set 사용 법 (HashSet, TreeSet, LinkedHashSet) 본문
반응형
Java에서 Set이란 단순하게 얘기하면 중복을 제거해주는 컬렉션이다.
이번 글에서는 단순하게 중복을 제거하는 컬렉션 이상의 내용을 알아보자.
1. Set의 기본 사용법
1-1. Set이란?
Set은 중복된 값을 허용하지 않으며 순서가 보장되지 않는다.
1-2. HashSet, TreeSet, LinkedHashSet 사용 예제
public class Main {
public static void main(String[] args) {
// HashSet: 빠른 검색(O(1)), 순서 보장X
Set<String> hashSet = new HashSet<>();
hashSet.add("Python");
hashSet.add("Java");
hashSet.add("C++");
hashSet.add("Java"); // 중복된 값은 추가되지 않음
System.out.println("HashSet: " + hashSet);
// TreeSet: 요소들이 정렬된 상태로 저장됨 (오름차순)
Set<String> treeSet = new TreeSet<>();
treeSet.add("Python");
treeSet.add("Java");
treeSet.add("C++");
treeSet.add("Java"); // 중복된 값은 무시됨
System.out.println("TreeSet: " + treeSet);
// LinkedHashSet: 삽입 순서를 유지함
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Python");
linkedHashSet.add("Java");
linkedHashSet.add("C++");
linkedHashSet.add("Java"); // 중복된 값은 무시됨
System.out.println("LinkedHashSet: " + linkedHashSet);
}
}
- HashSet : 빠르게 검색이 가능하지만, 순서가 보장이 안된다.
- TreeSet : 요소들이 오름차순으로 정렬된 상태로 저장된다.
- LinkedHashSet : 요소들의 삽입 순서대로 유지된다.
2. 사용자 정의 객체와 중복 처리 (equals & hashCode)
Set에 사용자 정의 객체를 저장할 때는 동일성을 판단하기 위해 equals() 와 hashCode() 메서드를 올바르게 오버라이드해야 한다.
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// equals와 hashCode를 오버라이드하여 이름과 나이가 같으면 같은 객체로 판단
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public class Main {
public static void main(String[] args) {
Set<Person> people = new HashSet<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Alice", 30)); // 중복된 객체
System.out.println("사람 목록: " + people);
// equals, hashCode를 올바르게 구현했으므로 중복이 제거되어 2개만 출력된다.
}
}
3. 집합 연산 (교집합, 합집합, 차집합)
Set의 removeAll(), addAll(), removeAll() 메서드를 이용하여 교집합, 합집합, 차집합 등을 구할 수 있다.
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Integer> setA = new HashSet<>();
Set<Integer> setB = new HashSet<>();
// setA에 1, 2, 3, 4, 5 추가
for (int i = 1; i <= 5; i++) {
setA.add(i);
}
// setB에 4, 5, 6, 7 추가
for (int i = 4; i <= 7; i++) {
setB.add(i);
}
// 합집합 (Union)
Set<Integer> union = new HashSet<>(setA);
union.addAll(setB);
System.out.println("합집합: " + union); // [1, 2, 3, 4, 5, 6, 7]
// 교집합 (Intersection)
Set<Integer> intersection = new HashSet<>(setA);
intersection.retainAll(setB);
System.out.println("교집합: " + intersection); // [4, 5]
// 차집합 (A - B)
Set<Integer> difference = new HashSet<>(setA);
difference.removeAll(setB);
System.out.println("차집합 (setA - setB): " + difference); // [1, 2, 3]
}
}
4. Iterator를 사용한 Set 순회
Set은 인덱스 기반 접근이 불가능하므로, Iterator를 사용하거나 향상된 for문을 통해 순회한다.
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<String> languages = new HashSet<>();
languages.add("Java");
languages.add("Python");
languages.add("C++");
// Iterator 사용
Iterator<String> iter = languages.iterator();
while (iter.hasNext()) {
String lang = iter.next();
System.out.println("Iterator: " + lang);
}
// 향상된 for문 사용
for (String lang : languages) {
System.out.println("향상된 for문: " + lang);
}
}
}
5. Stream API와 Set
Java 8 이상에서는 Stream API를 활용하여 Set의 요소들을 필터링, 변환, 집계할 수 있다.
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Set<String> fruits = new HashSet<>();
fruits.add("apple");
fruits.add("banana");
fruits.add("cherry");
fruits.add("apple"); // 중복은 무시됨
// 요소들을 대문자로 변환하여 List로 수집
var upperFruits = fruits.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("대문자 변환 결과: " + upperFruits);
// "a"를 포함한 요소만 필터링
var filtered = fruits.stream()
.filter(fruit -> fruit.contains("a"))
.collect(Collectors.toSet());
System.out.println("\"a\"를 포함한 과일: " + filtered);
}
}
정리
Java Set의 구현체별 차이, 사용자 정의 객체, 집합 연산, Iterator와 Stream API의 활용 등 다양한 활용 법에 대해서 알아봤다.
순서가 중요하지 않고 빠른 성능이 필요할 때는 HashSet, 정렬이 필요할 때에는 TreeSet을 사용하면 된다.
끝.
반응형
'JAVA' 카테고리의 다른 글
Java - List 인터페이스 (ArrayList, LinkedList, Vector 등) (1) | 2025.02.12 |
---|---|
Java - 예외 처리의 활용 및 효율적인 관리 방법 (Custom Exception, Exception Propagation) (0) | 2025.02.10 |
Java - 상속과 다형성의 활용 (0) | 2025.02.05 |
JAVA - 멀티스레딩 가이드 (구현부터 동기화까지) (0) | 2025.01.07 |
Java - CheckedException과 UncheckedException이 뭐지? (0) | 2024.12.06 |