자바 해시세트 클래스는 실제로 HashMap 인스턴스인 해시 테이블을 기반으로 하는 Set 인터페이스를 구현합니다. 해시 세트의 반복 순서에 대해서는 보장되지 않습니다. 이는 클래스가 시간이 지남에 따라 요소의 일정한 순서를 보장하지 않음을 의미합니다. 이 클래스는 null 요소를 허용합니다. 또한 이 클래스는 해시 함수가 요소를 버킷에 적절하게 분산한다는 가정 하에 추가, 제거, 포함 및 크기와 같은 기본 작업에 대해 일정한 시간 성능을 제공합니다. 이에 대해서는 기사에서 자세히 살펴보겠습니다.
자바 HashSet 기능
HashSet의 몇 가지 중요한 기능은 다음과 같습니다.
- 구현 인터페이스 설정 .
- HashSet의 기본 데이터 구조는 다음과 같습니다. 해시테이블 .
- Set 인터페이스를 구현하므로 중복된 값은 허용되지 않습니다.
- HashSet에 삽입하는 개체가 동일한 순서로 삽입된다는 보장은 없습니다. 개체는 해시 코드를 기반으로 삽입됩니다.
- HashSet에는 NULL 요소가 허용됩니다.
- HashSet도 구현합니다. 직렬화 가능 그리고 복제 가능 인터페이스.
HashSet 선언
public class HashSet extends AbstractSet implements Set, Cloneable, Serializable>
어디 그리고 HashSet에 저장된 요소 유형입니다.
HashSet 자바 예제
자바
// Java program to illustrate the concept> // of Collection objects storage in a HashSet> import> java.io.*;> import> java.util.*;> > class> CollectionObjectStorage {> > > public> static> void> main(String[] args)> > {> > // Instantiate an object of HashSet> > HashSet set => new> HashSet();> > > // create ArrayList list1> > ArrayList list1 => new> ArrayList();> > > // create ArrayList list2> > ArrayList list2 => new> ArrayList();> > > // Add elements using add method> > list1.add(> 1> );> > list1.add(> 2> );> > list2.add(> 1> );> > list2.add(> 2> );> > set.add(list1);> > set.add(list2);> > > // print the set size to understand the> > // internal storage of ArrayList in Set> > System.out.println(set.size());> > }> }> |
하이브 아키텍처
>
>산출:
1>
객체를 저장하기 전에 HashSet은 hashCode() 및 equals() 메소드를 사용하여 기존 항목이 있는지 확인합니다. 위의 예에서 두 목록이 동일한 순서로 동일한 요소를 갖고 있으면 동일한 것으로 간주됩니다. 호출할 때 해시 코드() 두 목록에 대한 방법을 사용하면 둘 다 동일하므로 동일한 해시를 제공합니다.
메모: HashSet은 다음을 수행합니다. 중복된 항목을 저장하지 않음 , 동일한 두 개체를 제공하면 첫 번째 개체만 저장됩니다. 여기서는 list1입니다.
HashSet의 계층 구조는 다음과 같습니다.
HashSet의 내부 작업
Set 인터페이스의 모든 클래스는 Map에 의해 내부적으로 백업됩니다. HashSet은 객체를 내부적으로 저장하기 위해 HashMap을 사용합니다. HashMap에 값을 입력하려면 키-값 쌍이 필요하지만 HashSet에서는 하나의 값만 전달한다는 사실이 궁금할 것입니다.
HashMap의 저장: 실제로 HashSet에 삽입한 값은 맵 객체의 키 역할을 하며 해당 값에 대해 Java는 상수 변수를 사용합니다. 따라서 키-값 쌍에서는 모든 값이 동일합니다.
Java 문서에서 HashSet 구현
private transient HashMap map; // Constructor - 1 // All the constructors are internally creating HashMap Object. public HashSet() { // Creating internally backing HashMap object map = new HashMap(); } // Constructor - 2 public HashSet(int initialCapacity) { // Creating internally backing HashMap object map = new HashMap(initialCapacity); } // Dummy value to associate with an Object in Map private static final Object PRESENT = new Object();>
우리가 살펴보면 추가하다() HashSet 클래스의 메서드:
public boolean add(E e) { return map.put(e, PRESENT) == null; }>
HashSet 클래스의 add() 메소드가 내부적으로 놓다() 키로 지정한 요소와 해당 값으로 상수 PRESENT를 전달하여 HashMap 개체를 지원하는 방법입니다. 제거하다() 방법도 같은 방식으로 작동합니다. 내부적으로 Map 인터페이스의 제거 메소드를 호출합니다.
public boolean remove(Object o) { return map.remove(o) == PRESENT; }>
HashSet은 고유한 객체뿐만 아니라 고유한 객체 컬렉션도 저장합니다. 좋다 배열목록 , 링크드리스트 , 벡터, ..등.
HashSet 클래스의 생성자
HashSet을 생성하려면 HashSet 클래스의 객체를 생성해야 합니다. HashSet 클래스는 HashSet을 생성할 수 있는 다양한 생성자로 구성됩니다. 다음은 이 클래스에서 사용할 수 있는 생성자입니다.
1. 해시셋()
이 생성자는 기본 초기 용량이 16이고 기본 로드 요소가 0.75인 빈 HashSet 개체를 빌드하는 데 사용됩니다. hs라는 이름의 빈 HashSet을 생성하려면 다음과 같이 생성할 수 있습니다.
HashSet hs = new HashSet();>
2. HashSet(intinitialCapacity)
이 생성자는 객체 생성 시에initialCapacity가 지정된 빈 HashSet 객체를 빌드하는 데 사용됩니다. 여기서 기본 loadFactor는 0.75로 유지됩니다.
HashSet hs = new HashSet(int initialCapacity);>
3. HashSet(intinitialCapacity, float loadFactor)
이 생성자는 객체 생성 시에initialCapacity와 loadFactor가 지정된 빈 HashSet 객체를 빌드하는 데 사용됩니다.
HashSet hs = new HashSet(int initialCapacity, float loadFactor);>
4. HashSet(컬렉션)
이 생성자는 주어진 컬렉션의 모든 요소를 포함하는 HashSet 개체를 만드는 데 사용됩니다. 즉, 이 생성자는 Collection 개체에서 HashSet 개체로의 변환이 필요할 때 사용됩니다. hs라는 이름의 HashSet을 생성하려면 다음과 같이 생성할 수 있습니다.
HashSet hs = new HashSet(Collection C);>
다음은 위 주제의 구현입니다.
자바
// Java program to Demonstrate Working> // of HashSet Class> > // Importing required classes> import> java.util.*;> > // Main class> // HashSetDemo> class> GFG {> > > // Main driver method> > public> static> void> main(String[] args)> > {> > > // Creating an empty HashSet> > HashSet h => new> HashSet();> > > // Adding elements into HashSet> > // using add() method> > h.add(> 'India'> );> > h.add(> 'Australia'> );> > h.add(> 'South Africa'> );> > > // Adding duplicate elements> > h.add(> 'India'> );> > > // Displaying the HashSet> > System.out.println(h);> > System.out.println(> 'List contains India or not:'> > + h.contains(> 'India'> ));> > > // Removing items from HashSet> > // using remove() method> > h.remove(> 'Australia'> );> > System.out.println(> 'List after removing Australia:'> > + h);> > > // Display message> > System.out.println(> 'Iterating over list:'> );> > > // Iterating over hashSet items> > Iterator i = h.iterator();> > > // Holds true till there is single element remaining> > while> (i.hasNext())> > > // Iterating over elements> > // using next() method> > System.out.println(i.next());> > }> }> |
>
>산출:
[South Africa, Australia, India] List contains India or not:true List after removing Australia:[South Africa, India] Iterating over list: South Africa India>
HashSet의 메소드
방법 | 설명 |
---|---|
추가(그리고) | 지정된 요소가 없으면 추가하는 데 사용되며, 있으면 false를 반환합니다. |
분명한() | 세트에서 모든 요소를 제거하는 데 사용됩니다. |
포함(객체 o) | 요소가 집합에 있는 경우 true를 반환하는 데 사용됩니다. |
제거(객체 o) | 세트에 요소가 있는 경우 요소를 제거하는 데 사용됩니다. |
반복자() | 집합의 요소에 대한 반복자를 반환하는 데 사용됩니다. |
비었다() | 세트가 비어 있는지 여부를 확인하는 데 사용됩니다. 집합에 대한 조건이 비어 있으면 true를 반환하고 비어 있지 않으면 false를 반환합니다. |
크기() | 세트의 크기를 반환하는 데 사용됩니다. |
클론() | 세트의 얕은 복사본을 만드는 데 사용됩니다. |
HashSet에서 다양한 작업 수행
HashSet에서 자주 사용되는 몇 가지 작업을 수행하는 방법을 살펴보겠습니다.
1. HashSet에 요소 추가하기
HashSet에 요소를 추가하려면 add() 메소드를 사용할 수 있습니다. 그러나 삽입 순서는 HashSet에 유지되지 않습니다. 중복 요소는 허용되지 않으며 모든 중복 요소는 무시된다는 점을 기억해야 합니다.
예
자바
// Java program to Adding Elements to HashSet> > // Importing required classes> import> java.io.*;> import> java.util.*;> > // Main class> // AddingElementsToHashSet> class> GFG {> > > // Method 1> > // Main driver method> > public> static> void> main(String[] args)> > {> > // Creating an empty HashSet of string entities> > HashSet hs => new> HashSet();> > > // Adding elements using add() method> > hs.add(> 'Geek'> );> > hs.add(> 'For'> );> > hs.add(> 'Geeks'> );> > > // Printing all string el=ntries inside the Set> > System.out.println(> 'HashSet elements : '> + hs);> > }> }> |
>
>산출:
HashSet elements : [Geek, For, Geeks]>
2. HashSet에서 요소 제거
Remove() 메서드를 사용하여 HashSet에서 값을 제거할 수 있습니다.
예
리눅스에서 파일 편집하기
자바
// Java program Illustrating Removal Of Elements of HashSet> > // Importing required classes> import> java.io.*;> import> java.util.*;> > // Main class> // RemoveElementsOfHashSet> class> GFG {> > > // Main driver method> > public> static> void> main(String[] args)> > {> > // Creating an> > HashSet hs => new> HashSet();> > > // Adding elements to above Set> > // using add() method> > hs.add(> 'Geek'> );> > hs.add(> 'For'> );> > hs.add(> 'Geeks'> );> > hs.add(> 'A'> );> > hs.add(> 'B'> );> > hs.add(> 'Z'> );> > > // Printing the elements of HashSet elements> > System.out.println(> 'Initial HashSet '> + hs);> > > // Removing the element B> > hs.remove(> 'B'> );> > > // Printing the updated HashSet elements> > System.out.println(> 'After removing element '> + hs);> > > // Returns false if the element is not present> > System.out.println(> 'Element AC exists in the Set : '> > + hs.remove(> 'AC'> ));> > }> }> |
>
>산출:
Initial HashSet [A, B, Geek, For, Geeks, Z] After removing element [A, Geek, For, Geeks, Z] Element AC exists in the Set : false>
삼. HashSet을 통한 반복
iterator() 메서드를 사용하여 HashSet의 요소를 반복합니다. 또한 가장 유명한 것은 for 루프가 향상되었습니다.
예
코드 블록
산출A, B, Geek, For, Geeks, Z, A, B, Geek, For, Geeks, Z,>
HashSet 작업의 시간 복잡성: HashSet의 기본 데이터 구조는 해시테이블입니다. 따라서 HashSet의 추가, 제거 및 조회(메서드 포함) 작업에 대한 시간 복잡도를 상각(평균 또는 일반적인 경우)합니다. 오(1) 시간.
HashSet의 성능
HashSet은 Abstract Set 클래스를 확장하고 구현합니다. 세트 , 복제 가능 및 직렬화 가능 여기서 E는 이 세트에 의해 유지되는 요소의 유형입니다. HashSet의 직접적으로 알려진 하위 클래스는 LinkedHashSet입니다.
이제 일정한 시간 성능을 유지하기 위해 HashSet을 반복하려면 HashSet 인스턴스의 크기(요소 수)와 지원 HashMap 인스턴스의 용량(버킷 수)의 합계에 비례하는 시간이 필요합니다. 따라서 반복 성능이 중요하다면 초기 용량을 너무 높게(또는 부하율을 너무 낮게) 설정하지 않는 것이 매우 중요합니다.
- 초기 용량: 초기 용량은 해시테이블(HashSet은 내부적으로 해시테이블 데이터 구조를 사용)이 생성될 때의 버킷 수를 의미합니다. 현재 크기가 가득 차면 버킷 수가 자동으로 늘어납니다.
- 부하율: 로드 팩터는 용량이 자동으로 증가하기 전에 HashSet이 얼마나 가득 차도록 허용되는지를 측정한 것입니다. 해시 테이블의 항목 수가 부하율과 현재 용량의 곱을 초과하면 해시 테이블이 다시 해시(즉, 내부 데이터 구조가 재구성됨)되어 해시 테이블의 버킷 수가 약 2배가 됩니다.
Number of stored elements in the table Load Factor = ----------------------------------------- Size of the hash table>
예: 내부 용량이 16이고 부하 계수가 0.75인 경우 테이블에 12개의 요소가 있으면 버킷 수가 자동으로 증가합니다.
성능에 미치는 영향:
부하율과 초기 용량은 HashSet 작업의 성능에 영향을 미치는 두 가지 주요 요소입니다. 0.75의 로드 팩터는 시간 및 공간 복잡성과 관련하여 매우 효과적인 성능을 제공합니다. 로드 팩터 값을 그 이상으로 늘리면 메모리 오버헤드가 줄어들지만(내부 재구축 작업이 줄어들기 때문에) 해시테이블의 추가 및 검색 작업에 영향을 미칩니다. 재해싱 작업을 줄이려면 초기 용량을 현명하게 선택해야 합니다. 초기 용량이 최대 항목 수를 로드 비율로 나눈 값보다 크면 재해시 작업이 발생하지 않습니다.
메모: HashSet의 구현은 동기화되지 않습니다. 즉, 여러 스레드가 해시 세트에 동시에 액세스하고 스레드 중 적어도 하나가 세트를 수정하는 경우 외부적으로 동기화되어야 한다는 의미입니다. 이는 일반적으로 세트를 자연스럽게 캡슐화하는 일부 개체를 동기화하여 수행됩니다. 그러한 객체가 없으면 Collections.synchronizedSet 메소드를 사용하여 세트를 래핑해야 합니다. 아래와 같이 실수로 세트에 대한 비동기화 액세스를 방지하려면 생성 시 이 작업을 수행하는 것이 가장 좋습니다.
세트 s = Collections.synchronizedSet(new HashSet(…));
HashSet과 함께 사용되는 메서드
1. java.util.AbstractSet 클래스에서 상속된 메소드
방법 | 설명 |
---|---|
같음() | 객체와 HashSet의 동일성을 확인하고 비교하는 데 사용됩니다. 목록은 순서에 관계없이 두 HashSet에 동일한 요소가 포함된 경우에만 true를 반환합니다. |
해시 코드() | 이 세트의 해시 코드 값을 반환합니다. |
모두 제거(컬렉션) | 이 메소드는 세트에 존재하는 컬렉션의 모든 요소를 제거하는 데 사용됩니다. 호출의 결과로 이 집합이 변경되면 이 메서드는 true를 반환합니다. |
2. java.util.AbstractCollection 클래스에서 상속된 메소드
방법 | 설명 |
---|---|
addAll(컬렉션) | 이 메소드는 언급된 컬렉션의 모든 요소를 기존 세트에 추가하는 데 사용됩니다. 요소는 특정 순서를 따르지 않고 무작위로 추가됩니다. |
모두 포함(컬렉션) | 이 메소드는 세트가 주어진 컬렉션에 존재하는 모든 요소를 포함하는지 여부를 확인하는 데 사용됩니다. 이 메서드는 집합에 모든 요소가 포함되어 있으면 true를 반환하고 요소 중 하나라도 누락되면 false를 반환합니다. |
keepAll(컬렉션) | 이 방법은 주어진 컬렉션에 언급된 세트의 모든 요소를 유지하는 데 사용됩니다. 이 메서드는 호출의 결과로 이 집합이 변경된 경우 true를 반환합니다. |
toArray() | 이 메소드는 Set의 요소와 동일한 요소의 배열을 형성하는 데 사용됩니다. |
toString() | Java HashSet의 toString() 메소드는 HashSet 컬렉션 요소의 문자열 표현을 반환하는 데 사용됩니다. |
3. java.util.Collection 인터페이스에 선언된 메소드
방법 | 설명 |
---|---|
병렬스트림() | 이 컬렉션을 소스로 사용하여 병렬 스트림을 반환합니다. |
RemoveIf?(조건자 필터) | 주어진 조건을 만족하는 이 컬렉션의 모든 요소를 제거합니다. |
개울() | 이 컬렉션을 소스로 사용하여 순차 스트림을 반환합니다. |
toArray?(IntFunction 생성기) | 제공된 생성기 함수를 사용하여 반환된 배열을 할당하여 이 컬렉션의 모든 요소를 포함하는 배열을 반환합니다. |
4. java.lang.Iterable 인터페이스에 선언된 메소드
방법 | 설명 |
---|---|
forEach?(소비자 행동) | 모든 요소가 처리되거나 작업에서 예외가 발생할 때까지 Iterable의 각 요소에 대해 지정된 작업을 수행합니다. |
5. java.util.Set 인터페이스에 선언된 메소드
방법 | 설명 |
---|---|
addAll?(컬렉션 c) | 지정된 컬렉션의 모든 요소가 아직 존재하지 않는 경우 이 집합에 추가합니다(선택적 작업). |
containAll?(컬렉션 c) | 이 집합에 지정된 컬렉션의 모든 요소가 포함되어 있으면 true를 반환합니다. |
같음?(객체 o) | 지정된 개체가 이 집합과 동일한지 비교합니다. |
해시 코드() | 이 세트의 해시 코드 값을 반환합니다. |
RemoveAll?(컬렉션 c) | 지정된 컬렉션에 포함된 모든 요소를 이 세트에서 제거합니다(선택적 작업). |
keepAll?(컬렉션 c) | 지정된 컬렉션에 포함된 이 세트의 요소만 유지합니다(선택적 작업). |
toArray() | 이 세트의 모든 요소를 포함하는 배열을 반환합니다. |
toArray?(T[] a) | 이 세트의 모든 요소를 포함하는 배열을 반환합니다. 반환된 배열의 런타임 유형은 지정된 배열의 런타임 유형입니다. |
Java의 HashSet에 대한 FAQ
Q1. Java에서 HashSet이란 무엇입니까?
답변:
HashSet은 AbstractSet을 확장하고 Set 인터페이스를 구현하는 클래스 유형입니다.
Q2. HashSet을 사용하는 이유는 무엇입니까?
답변:
HashSet은 중복된 데이터를 피하고 빠른 방법으로 값을 찾기 위해 사용됩니다.
Q3. HashSet과 HashMap의 차이점
답변:
기초 | 해시세트 | 해시맵 |
---|---|---|
구현 | HashSet은 Set 인터페이스를 구현합니다. | HashMap은 StoreMap 인터페이스를 구현합니다. |
중복 | HashSet은 중복된 값을 허용하지 않습니다. | HashMap은 키와 값 쌍을 저장하며 중복 키를 허용하지 않습니다. 키가 중복되면 이전 키가 새 값으로 대체됩니다. |
객체 저장 중 객체 수 | HashSet에는 하나의 객체 add(Object o)만 필요합니다. | HashMap은 HashMap 객체에 요소를 추가하기 위해 두 개의 객체 put(K key, V Value)이 필요합니다. |
더미 값 | HashSet은 내부적으로 HashMap을 사용하여 요소를 추가합니다. HashSet에서는 add(Object) 메소드에 전달된 인수가 키 K 역할을 합니다. Java는 add(Object) 메소드에 전달된 각 값에 대해 내부적으로 더미 값을 연결합니다. | HashMap에는 더미 값 개념이 없습니다. |
메커니즘 저장 또는 추가 | HashSet은 내부적으로 HashMap 개체를 사용하여 개체를 저장하거나 추가합니다. | HashMap은 내부적으로 해싱을 사용하여 객체를 저장하거나 추가합니다. |
더 빠르게 | HashSet은 HashMap보다 느립니다. | HashMap은 HashSet보다 빠릅니다. |
삽입 | HashSet은 데이터를 추가하거나 저장하기 위해 add() 메서드를 사용합니다. | HashMap은 데이터를 저장하기 위해 put() 메소드를 사용합니다. |
예 | HashSet은 집합입니다. {1, 2, 3, 4, 5, 6, 7}. | HashMap은 키 -> 값 쌍(키 대 값) 맵입니다. {a -> 1, b -> 2, c -> 2, d -> 1}. |
Q4. Java에서 HashSet과 TreeSet의 차이점
답변:
기초 | 해시세트 | 트리세트 |
---|---|---|
속도 및 내부 구현, 던지기 동작 | 검색, 삽입, 삭제 등의 작업에 사용됩니다. 이러한 작업에는 평균적으로 일정한 시간이 걸립니다. HashSet은 TreeSet보다 빠릅니다. HashSet은 해시 테이블을 사용하여 구현됩니다. | TreeSet은 검색, 삽입, 삭제에 HashSet보다 높은 O(Log n)을 사용합니다. 그러나 TreeSet은 정렬된 데이터를 유지합니다. 또한 high()(가장 낮은 요소 반환), Floor(),ceiling() 등과 같은 작업을 지원합니다. 이러한 작업은 TreeSet에서도 O(Log n)이며 HashSet에서는 지원되지 않습니다. TreeSet은 자체 균형 이진 검색 트리(Red-Black Tree)를 사용하여 구현됩니다. TreeSet은 Java의 TreeMap에 의해 지원됩니다. |
주문 | HashSet의 요소는 순서가 지정되지 않습니다. | TreeSet은 Java의 Comparable 또는 Comparator 메소드에 의해 정의된 정렬된 순서로 객체를 유지 관리합니다. TreeSet 요소는 기본적으로 오름차순으로 정렬됩니다. first(), last(), headSet(), tailSet() 등과 같이 순서가 지정된 집합을 처리하는 여러 가지 방법을 제공합니다. |
널 객체 | HashSet은 null 객체를 허용합니다. | TreeSet은 null Object를 허용하지 않고 NullPointerException을 발생시킵니다. 이유는 TreeSet이 CompareTo() 메소드를 사용하여 키를 비교하고, CompareTo()가 java.lang.NullPointerException을 발생시키기 때문입니다. |
비교 | HashSet은 equals() 메서드를 사용하여 Set의 두 객체를 비교하고 중복 항목을 감지합니다. | TreeSet은 동일한 목적으로 CompareTo() 메서드를 사용합니다. equals()와 CompareTo()가 일치하지 않는 경우, 즉 두 개의 동일한 객체에 대해 같음은 true를 반환해야 하고 CompareTo()는 0을 반환해야 하면 Set 인터페이스의 계약을 위반하고 TreeSet과 같은 Set 구현에서 중복을 허용합니다. |