Set을 지난번에 공부한 List와 비교해보자면
1. Set은 중복 값을 삽입할 수 없다.
2. Set은 특정한 순서를 가지고 있지 않다.
이제 예제를 통해 한번 알아보자.
String 타입만 받는 HashSet을 선언한 뒤 set 안에 add 메소드를 사용해서 "a", "b", "b", "d" 총 4개의 값을 set 안에 넣었는데
set은 중복값을 허용하지 않기 때문에 b를 1번 넣건 200번 넣건 동일한 값은 하나만 들어가게 된다.
또한 삽입 시 순서가 없기 때문에 배열(Array)이나 List 처럼 get(인덱스)로 값을 가져올 수 없고 .Iterator를 통해 가져와야 하는데
set.iterator()로 set 값을 iterator에 담은 후 .next를 통해 하나씩 뽑아내는 식이다.
여기서 순서가 없다고 했는데 100% 보장하지 않을 뿐 대부분의 경우에는 넣은 값의 hashCode값에 따라 순서가 정해져 나오게 된다
자바에서 set에 대해 배울 때 set은 정렬 순서가 없으며 무작위로 호출되기 때문에
순서를 가지게 하고 싶으면 LinkedHashSet을 사용하라고 알고있는 경우가 많다.
실제 set에 값을 넣고 iterator로 값을 꺼내보면 무작위로 넣었는데도 출력시 값이 정렬이 되어서 뽑히고
여러번 다시 출력하더라도 결과는 동일하다. 의문이 생길텐데,
실제 set에 값을 넣을 때 hashCode 값을 가지고 넣기 때문에 무작위로 넣는 것 처럼 보여도 실제로 뽑아보면 hash 코드 값 순으로 넣었기 때문에 무작위가 아닌 것이다.
여기서 hashCode가 무조건 맞는 것이 아닌게
Returns an iterator over the elements in this set. The elements are returned in no particular order.
이렇게 특별한 순서가 있는 것은 아니다! 라고 설명에 써 놓았기 때문에 실제 여러 값을 넣어보며 테스트 할 시에는 hashCode와 다르게 들어오는 경우도 많다. 높은 확률로 hashCode 순서대로 넣고 뽑아낸다는 것이다.
Set 선언방법과 주요 메소드는 다음과 같다.
Set 선언하기 (LinkedHashSet, TreeSet으로도 가능)
HashSet<데이터타입> set명 = new HashSet<데이터타입>();
Set에 값 추가하기
set명.add("값");
Set 크기 확인하기
set명.size();
Set 내용 출력할 수 있게 Iterator 안에 담기
Iterator<데이터타입> iterator명 = set명.Iterator();
Iterator 안에 담은 set 출력하기
Iterator명.next();
or
while(iterator명.hasNext()) {
iterator명.next(); // 값 없을때까지 계속 출력
}
주로 사용되는 Set은 HashSet 말고도
LinkedHashSet, TreeSet이 있는데 특징은 다음과 같다
LinkedSet
- 다른 Set들과 동일하게 중복은 허용하지 않으나 .add() 한 순서대로 값이 저장된다
TreeSet
- 오름차순으로 값을 정렬해 가지고 있으며 다른 set보다 대량의 데이터를 검색할 시 훨씬 빠르다
마지막으로 예제에 사용한 코드는 아래와 같다
import java.util.HashSet;
import java.util.Iterator;
public class SetTest {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>(); // set 선언
set.add("a");
set.add("b");
set.add("b"); // set에 중복값 저장 불가
set.add("c"); // set에 값 담기
System.out.println("set 크기 확인 : " + set.size());
Iterator<String> iter = set.iterator(); // set을 Iterator 안에 담기
while(iter.hasNext()) { // iterator에 다음 값이 있다면
System.out.println("iterator : " + iter.next()); // iter에서 값 꺼내기
}
}
}
HashSet에대해 자세히 알아보자
Set 인터페이스에서 지원하는 구현 클래스
순서대로 입력되지 않고, 일정하게 유지되지 않는게 특징
HashSet은 null 요소도 허용
이 클래스의 가장 큰 특징은 중복을 허용하지 않음
중복을 걸러내는 과정
HashSet은 객체를 저장하기 전에 먼저 객체의 hashCode()메소드를 호출해서 해시 코드를 얻어낸 다음 저장되어 있는 객체들의 해시 코드와 비교한 뒤 같은 해시 코드가 있다면 다시 equals() 메소드로 두 객체를 비교해서 true가 나오면 동일한 객체로 판단하고 중복 저장을 하지 않는다.
문자열을 HashSet에 저장할 경우, 같은 문자열을 갖는 String객체는 동일한 객체로 간주되고 다른 문자열을 갖는 String객체는 다른 객체로 간주되는데, 그 이유는 String클래스가 hashCode()와 equals() 메소드를 재정의해서 같은 문자열일 경우 hashCode()의 리턴 값을 같게, equals()의 리턴 값은 true가 나오도록 했기 때문이다.
HashSet 변수 선언
HashSet의 변수를 선언하는 방법:
HashSet<데이터타입> 변수명 = new HashSet<데이터타입>(); 으로 선언
HashSet<Integer> : Integer형의 HashMap 데이터가 들어감
HashSet<String> : String형의 HashMap 데이터가 들어감
HashSet<Integer> set = new HashSet<Integer>();
HashSet<String> set2 = new HashSet<String>();
HashSet 값 추가
HashSet의 값을 추가하는 방법이다.
HashSet의 add(value) 메소드를 사용하여 값을 추가한다.
추가되는 값은 HashSet<데이터타입>의 맞는 데이터만 추가해준다.
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
}
}
HashSet 값 삭제
HashSet의 값을 삭제하는 방법이다.
HashSet의 remove(value) 메소드를 사용하면 원하는 value 값만 삭제된다.
전부 삭제하고 싶은 경우 HashSet의 clear() 메소드를 사용해준다.
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.remove(1);
set.clear();
// String
HashSet<String> set2 = new HashSet<String>();
set2.remove("a");
set2.clear();
}
}
HashSet의 크기 구하기
HashSet의 size() 메소드를 사용해 현재 HashSet의 크기를 구할 수 있습니다
아래와 같이 중복값이 들어오면 자동으로 제거됩니다
Size() 메소드 사용시 둘 다 결과가 3으로 출력이 됩니다
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
System.out.println("set의 크기 : " + set.size());
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
System.out.println("set2의 크기 : " + set2.size());
}
}
결과 화면
HashSet 데이터 출력하기
HashSet 데이터를 단순히 println으로 출력을 하는 경우 [1, 2, 3], [a, b, c] 형태로 출력을 하게 된다.
하나의 객체를 가져오고 싶을 경우 Iterator를 사용해서 가져올 수 있다.
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
System.out.println("set의 값 : " + set);
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
System.out.println("set2의 값 : " + set2);
// Integer 출력
Iterator iter = set.iterator();
while(iter.hasNext()) {
System.out.print(iter.next() + " ");
}
System.out.println("");
// String 출력
Iterator iter2 = set2.iterator();
while(iter2.hasNext()) {
System.out.print(iter2.next() + " ");
}
}
}
결과 화면
HashSet 검색하기
Hashet 내부의 원하는 값을 검색하는 경우 contains(value) 메소드를 사용한다.
값이 존재한다면 true, 값이 없다면 false를 return한다.
public class HashSetTest {
public static void main(String[] args) {
// Integer
HashSet<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
System.out.println("1은 있는가? : " + set.contains(1));
// String
HashSet<String> set2 = new HashSet<String>();
set2.add("a");
set2.add("b");
set2.add("c");
set2.add("a");
System.out.println("a는 있는가? : " + set2.contains("a"));
}
}
결과 화면
'공부 STUDY > JAVA' 카테고리의 다른 글
[JAVA] IO 자바 입출력 (1) | 2023.01.16 |
---|---|
[JAVA] 자료구조 - Map (0) | 2023.01.15 |
[JAVA] 자료구조 - List | ArrayList, LinkedList 차이는 무엇일까? (0) | 2023.01.15 |
[JAVA] 제네릭 Generic (0) | 2023.01.15 |
[JAVA] java.util패키지 | 컬렉션 프레임워크(Collection Framework) (0) | 2023.01.15 |