해당 게시글은 [Java] 어서와! 자료구조 알고리즘은 처음이지?https://programmers.co.kr/learn/courses/13577를 간략히 요약한 게시글이며 모든 출처는 해당강의에 있습니다.
배열, 리스트, 맵 등등은 추가하거나 업데이트하기 전에 개발자가 임의로 확인을 먼저 하는 형식으로 이루어져 있지만, 컬렉션에 넣을때 컬렉션 자체 적으로 확인 하기 위해서 마련된 별도의 컬렉션이 존재합니다.
이전 까지 contains()
, containsKey()
, containsValue()
등등 메서드를 호출하여 컬렉션에 값이 이미 존재하는지 확인하는 별도의 로직을 구현해야 했었습니다. 하지만, 집합(Set)
을 이용하면 데이터를 입력 하더라도 컬렉션 자체적으로 버려버림으로써 추가되지 않습니다.
컬렉션은 배열, 리스트와 마찬가지로 선형 데이터 구조
를 가지고 있습니다. 값을 넣을 때 존재 하는지 여부를 확인 하기 위해선 탐색 알고리즘
도 필요할 것입니다.
중복을 허용하지 않는 집합을 만들 때 기존의 방식인 리스트로 데이터를 추가해 보겠습니다.
List<Integer> list = new LinkedList<>();
if(!list.contains(1)) list.add(1);
if(!list.contains(2)) list.add(2);
if(!list.continas(3)) list.add(3);
if(!list.contains(1)) list.add(1);
if(!list.contains(2)) list.add(2);
if(!list.continas(3)) list.add(3);
System.out.println(list);
//Console
[1,2,3]
리스트.contains()
로 리스트에 이미 값이 존재하고 있는지 개발자가 값을 대입하기 전 확인해야 했었습니다. 1,2,3을 각각 2번씩 대입하였으나 값이 이미 존재하는 경우엔 입력 되지 않습니다.
Set을 이용하여 데이터를 추가 하겠습니다.
HashSet<Integer> list = new HashSet<>();
list.add(1);
list.add(2);
list.add(3);
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);
//Console
[1,2,3]
단순히 add
만으로도 중복을 알아서 걸러 줍니다.
집합도 컬렉션인 만큼 다양한 인터페이스와 클래스들이 존재합니다. 그 중에서 많이 사용되는 것들은 Set
, HashSet
, LinkedHashSet
, TreeSet
등이 있습니다.
HashSet<MyData> list = new HashSet<>(); //set은 순서를 보장하지 않는다.
Set<MyData> list = new HashSet<>();
Set<MyData> list = new LinkedHashSet<>(); //LinkedHashSet은 순서를 보장합니다.
Set<MyData> list = new TreeSet<>();
집합.add(값)
: 집합에 값이 존재하지 않을 시, 값을 추가합니다.(존재하면 버림)
집합.remove(값)
: 집합에 값이 존재하면 해당 값을 집합에서 삭제합니다.
집합.size()
: 현재 집합에 존재하는 요소들의 갯수를 반환합니다.
집합.contains(값)
: 집합에 값이 존재하면 true, 없으면 false를 반환합니다.
집합.isEmpty()
: 집합이 비어 있다면 true, 요소가 하나라도 있으면 false를 반환합니다.
집합.iterator()
: 집합을 순회할 수 있는 iterator를 반환합니다.
집합A.addAll(집합B)
: 집합A에 집합B의 모든 요소를 추가합니다.(A+B)
집합A.removeAll(집합B)
: 집합A에 존재하는 요소들중 집합B에도 존재하는 요소들을 삭제합니다.(A-B)
집합A.retainAll(집합B)
: 집합A와 집합B에 존재하는 요소들만 남깁니다.(A*B)
요소로 사용할 MyData 클래스 정의
class MyData{
int v;
public MyData(int v){
this.v = v;
}
public String toString(){
return "" + v;
}
@Override
public boolean equals(Object obj) { //객체간 비교
if(this == obj) return true; //같은 객체
if(obj == null || getClass() != obj.getClass()) return false; //다른 클래스
MyData myData = (MyData) obj; //타입 캐스팅
return v == myData.v; //값 비교
}
@Override
public int hashCode() {
return Objects.hash(v); //해시 반환
}
}
집합 A와 집합 B를 구성합니다.
Set<MyData> setA = new LinkedHashSet<>();
Set<MyData> setB = new LinkedHashSet<>();
//A
setA.add(new MyData(1));
setA.add(new MyData(2));
setA.add(new MyData(3));
//B
setB.add(new MyData(2));
setB.add(new MyData(3));
setB.add(new MyData(4));
합집합, 차집합, 교집합을 구합니다.
//A+B
setA.addAll(setB); //[1,2,3,4]
//A-B
setA.removeAll(setB); //[1]
//A*B
setA.retainAll(setB); //[2,3]
package Set집합;
import java.util.*;
class MyData{
int v;
public MyData(int v){
this.v = v;
}
public String toString(){
return "" + v;
}
@Override
public boolean equals(Object obj) { //객체간 비교
if(this == obj) return true; //같은 객체
if(obj == null || getClass() != obj.getClass()) return false; //다른 클래스
MyData myData = (MyData) obj; //타입 캐스팅
return v == myData.v; //값 비교
}
@Override
public int hashCode() {
return Objects.hash(v); //해시 반환
}
}
public class Set실습 {
public static void main(String[] args){
// List<Integer> list = new LinkedList<>();
//
// if(!list.contains(1)) list.add(1);
// if(!list.contains(2)) list.add(2);
// if(!list.contains(3)) list.add(3);
//
// if(!list.contains(1)) list.add(1);
// if(!list.contains(2)) list.add(2);
// if(!list.contains(3)) list.add(3);
// HashSet<Integer> list = new HashSet<>();
// list.add(1);
// list.add(2);
// list.add(3);
//
// list.add(1);
// list.add(2);
// list.add(3);
// HashSet<MyData> list = new HashSet<>(); //set은 순서를 보장하지 않는다.
// Set<MyData> list = new HashSet<>();
// Set<MyData> list = new LinkedHashSet<>();
// list.add(new MyData(1));
// list.add(new MyData(2));
// list.add(new MyData(3));
//
// list.add(new MyData(1));
// list.add(new MyData(2));
// list.add(new MyData(3));
Set<MyData> setA = new LinkedHashSet<>();
Set<MyData> setB = new LinkedHashSet<>();
//A
setA.add(new MyData(1));
setA.add(new MyData(2));
setA.add(new MyData(3));
//B
setB.add(new MyData(2));
setB.add(new MyData(3));
setB.add(new MyData(4));
//
// //A + B
// setA.addAll(setB);
// //A - B
// setA.removeAll(setB);
//A * B
setA.retainAll(setB);
System.out.println(setA);
}
}