Java의 Hashmap, Hashset, Treemap 및 Treeset의 동일한 요소를 판단하는 몇 가지 방법의 비교
1.1 해시 맵
먼저 Hashmap에 요소가 저장되는 방법을 살펴 보겠습니다. 맵에 저장된 각 요소는 키 값과 같은 키 값 쌍이며 풋 방법을 통해 추가됩니다. 또한 동일한 키는지도에서 관련 값 만 갖습니다. PUT 방법은 다음과 같이 맵에 정의됩니다.
v put (k 키, v 값);
키 값과 같은 키 값 쌍을 저장하는 데 사용됩니다. 리턴 값은 키에 의해지도에 저장된 이전 값입니다. 이전에 존재하지 않으면 Null을 반환합니다. 해시 맵 퍼트 방법이 구현되는 방법입니다.
public v put (k key, v value) {if (key == null) return putfornullkey (value); int hash = 해시 (키); int i = indexfor (Hash, table.length); for (Entry <k, v> e = 테이블 [i]; e! = null; e = e.next) {object k; if (e.hash == hash && ((k = e.key) == key || key.equals (k))) {v OldValue = e.Value; e.Value = 값; e.recordaccess (this); OldValue를 반환하십시오. }} modcount ++; Addentry (해시, 키, 값, i); 널 리턴; }위에서부터 해당 키 값 조합을 추가 할 때 해당 키가 이미 존재하면 해당 값이 직접 변경되고 이전 값이 반환됩니다. 키가 존재하는지 판단하면 키의 해시 코드가 먼저 비교되고 키의 해시 코드는 동등한 것과 비교됩니다. 우리는 여기서 그것을 볼 수 없을 수도 있습니다. 위의 코드에서 Map.entry의 해시 코드와 키 해시 코드를 비교합니다. 실제로, 우리는 맵을 볼 수 있습니다. 엔트리 해시 코드는 실제로 키의 해시 코드입니다. 해당 키가 원래 존재하지 않으면 Addentry가 호출되어 해당 키 값을 맵에 추가합니다. Addentry에 의해 통과 된 해시 매개 변수는 키에 해당하는 해시 코드입니다. 다음으로 Addentry의 메소드 정의를 살펴 보겠습니다.
void addentry (int Hash, k key, v value, int buctIndex) {if ((size> = threshold) && (null! = 테이블 [buctIndex])) {resize (2 * table.length); hash = (null! = 키)? 해시 (키) : 0; BucketIndex = indexfor (Hash, table.length); } createEntry (해시, 키, 값, BucketIndex); } void createEntry (int hash, k key, v value, int buctIndex) {enther <k, v> e = 테이블 [buctIndex]; 표 [bucetIndex] = new Entry <> (해시, 키, 값, e); 크기 ++; }Addentry의 핵심은 CreateEntry를 호출하여 맵을 작성하는 것입니다. 분명히 위의 표는 맵 배열입니다. Map.Entry는 속성 해시를 사용하여 해당 키의 해시 코드를 저장합니다. 위의 Map.entry의 생성자를 살펴 보겠습니다.
입력 (int h, k k, v v, enth <k, v> n) {value = v; 다음 = n; 키 = k; 해시 = h; }분명히 해당 키, 값 및 키에 해당하는 해시 코드를 저장합니다.
Hashmap이 요소를 저장하는 방법을 이해 한 후에는 Hashmap이 요소를 저장하는 방법을 쉽게 알 수 있습니다. Hashmap에는 요소가 동일한 지 여부를 결정하기위한 두 가지 주요 방법이 있습니다. 하나는 키가 동일한 지 여부를 결정하는 것이고 다른 하나는 값이 동일한 지 여부를 결정하는 것입니다. 실제로 Hashmap이 요소를 저장하는 방법을 소개 할 때 Hashmap이 요소 키가 동일한 지 여부를 결정하는 방법을 소개했습니다. 즉, 우선 해시 코드는 동일하며, 둘째, 키는 동일하거나 동일합니다. 맵에서 키가 동일한 지 여부를 결정하는 것은 continkey () 메소드를 통해 수행되며 해시 맵에서의 구현은 다음과 같습니다.
Public Boolean은 KECKEKE (객체 키) {return getEntry (key)! = null; } 최종 항목 <k, v> getEntry (개체 키) {int hash = (key == null)? 0 : 해시 (키); for (Entry <k, v> e = table [indexfor (hash, table.length)]; e! = null; e = e.next) {object k; if (e.hash == hash && ((k = e.key) == key || (key! = null && key.equals (k))) return e; } return null; }키의 해시 코드가 동일한 지 여부를 먼저 결정한 다음 키가 동일인지 동일인지 결정하는 것이 명백합니다.
MAP에 사용 된 값은 ContainSValue 메소드로 판단되며 HashMap에서의 구현은 다음과 같습니다.
public boolean containSvalue (객체 값) {if (value == null) return containsNullValue (); 입력 [] 탭 = 테이블; for (int i = 0; i <tab.length; i ++) for (Entry e = tab [i]; e! = null; e = e.next) if (value.equals (e.value)) true; 거짓을 반환합니다. }분명히, null 형태의 값은 값의 동등한 것으로 판단되며, 널 형태는 동일하며, 즉 저장된 요소의 값이 null입니다.
1.2 해시 세트
Hashmap이 요소를 저장하고 요소가 동일한 지 여부를 결정하는 방법을 알면 Hashset이 요소가 동일한 지 여부를 결정하는 방법을 쉽게 알 수 있습니다.
해시 세트의 요소는 실제로 해시 맵을 통해 저장됩니다. 각 해시 세트 객체는 해당 해시 맵 객체에 대한 참조를 보유합니다. 해시 세트에 요소를 추가하고 삭제할 때 보유한 해시 맵을 통해 수행됩니다. 요소를 저장할 때 해당 요소를 HELD 해시 맵의 키로 저장합니다. 해당 값은 일정한 객체이므로 저장할 때 요소가 동일한 지 결정하는 논리를 사용합니다. 요소가 포함되어 있는지 여부를 결정할 때, 그것은 또한 판단을하기 위해 HASHMAP의 함유 메소드를 호출합니다.
공개 부울은 (Object O) {returnMap.ContainsKey (O); }관심있는 친구는 해시 세트의 소스 코드를 확인할 수 있습니다.
1.3 트리 맵
Treemap에 저장된 요소는 키에 따라 주문하고 정렬됩니다. Treemap에는 저장된 요소를 정렬하는 두 가지 방법이 있습니다. 하나는 보유하는 비교기를 정렬하는 것이고 다른 하나는 비교 가능한 인터페이스를 구현하는 키를 정렬하는 것입니다. 첫 번째 방법이 선호됩니다. HELD 비교기 (기본값이 NULL)가 NULL 인 경우 두 번째 방법이 사용됩니다. Treemap에는 여러 생성자가 있으며,이를 통해 보유한 비교기를 초기화 할 수 있습니다. 먼저 Treemap이 요소를 저장하는 방법을 살펴 보겠습니다. PUT 방법은 다음과 같이 구현됩니다.
public v put (k key, v value) {enther <k, v> t = root; if (t == null) {비교 (키, 키); // type (및 가능한 null) Check root = new Entry <> (키, 값, null); 크기 = 1; 모드 카운트 ++; 널 리턴; } int cmp; 입력 <k, v> 부모; // 분할 비교기 및 비교 경로 비교기 <? 슈퍼 k> cpr = 비교기; if (cpr! = null) {do {parent = t; cmp = cpr.compare (key, t.key); if (cmp <0) t = t.left; elseif (cmp> 0) t = t.right; 그렇지 않으면 t.setValue (value)를 반환합니다. } while (t! = null); } else {if (key == null) 던지는 nullpointerexception (); 비슷한 <? SUPER K> K = (비슷한 <? SUPER K>) 키; {parent = t; cmp = k.compareto (t.key); if (cmp <0) t = t.left; elseif (cmp> 0) t = t.right; 그렇지 않으면 t.setValue (value)를 반환합니다. } while (t! = null); } entry <k, v> e = new Entry <> (키, 값, 부모); if (cmp <0) parent.left = e; else parent.right = e; fixafterinsertion (e); 크기 ++; 모드 카운트 ++; 널 리턴; }위의 구현에서 첫 번째 요소가 직접 저장 될 것임을 알 수 있습니다. 다음 요소는 두 가지 상황으로 나뉩니다. 하나는 비교기가 비어 있지 않은 경우이며, 다른 하나는 비교기가 비어있는 경우입니다. 비교기가 비어 있지 않으면 비교기는 저장된 요소의 위치를 결정합니다. 한 가지 중요한 것은 기존 요소의 키를 현재 저장된 요소의 키와 비교 한 결과가 0 일 때, 현재 저장된 요소의 키가 원래 맵에 이미 존재하며 원래 키에 해당하는 값이 새 값으로 변경 된 다음 이전 값이 직접 반환된다는 점입니다. 보류 비교기가 비어 있으면 요소의 위치는 비교 가능한 인터페이스를 구현하는 키의 비교 방법에 의해 결정됩니다. 비교기 사용과 유사한 한 가지는 원래 키가 새로 저장된 키와 비교 될 때 새로 저장된 키가 이미 원래지도에 존재하며 해당 원래 키의 값이 직접 변경되고 키 값 쌍이 더 이상 저장되지 않는다는 것입니다. 실제로, 요소가 존재하는지 여부를 결정하는 함유 메소드의 주요 구현 논리는 유사하며 특정 구현은 다음과 같습니다.
Public Boolean은 KECKEKE (객체 키) {return getEntry (key)! = null; } 최종 항목 <k, v> getEntry (객체 키) {// 성능을 위해 비교기 기반 버전 (비교기! = null) return getentRyusingComparator (키); if (key == NULL) 던진 NULLPOINTEREXCEPTION (); 비슷한 <? SUPER K> K = (비슷한 <? SUPER K>) 키; 입력 <k, v> p = 루트; while (p! = null) {int cmp = k.compareto (p.key); if (cmp <0) p = p.left; elseif (cmp> 0) p = p.right; 그렇지 않으면 p; } return null; }요소가 존재하는지 여부를 결정하기위한 Treemap의 논리는 비교기 또는 비교 가능한 결과가 0인지 여부를 결정하는 것이기 때문에 Treemap을 사용하여 요소와 유사한 논리를 구현할 때 특히 조심해야합니다.
Treemap의 논리가 포함 된 논리는 해당 값이 동일인지 여부를 결정하는 것입니다. 해시 맵과 유사합니다. 관심있는 친구들은 Treemap의 소스 코드를 확인할 수 있습니다.
1.4 트리 셋
Treeset은 또한 세트의 구현입니다. 저장된 요소는 반복되지 않으며 주문됩니다. 기본적으로 저장된 요소는 비슷한 인터페이스를 구현해야합니다. 기본적으로 요소는 비슷한 객체로 비교되므로. TreeSet은 또한 비교기를 통해 저장된 요소를 비교하는 데 사용될 수 있습니다. 이것은 트리셋을 구성 할 때 비교기 물체 또는 비교기 객체를 고정하는 Treemap을 전달하여 달성 할 수 있습니다. 트리 셋의 구현은 해시 세트의 구현과 유사합니다. 또한지도에 대한 참조를 보유하고 있지만 해시 맵이 아니라 Treemap을 언급합니다. TreeSet에서 요소의 추가 및 삭제는 모두 그들이 보유한 Treemap에 의해 구현됩니다. 따라서 해시 세트와 유사하게 트리 세트의 요소가 동일한지 여부를 결정하는 방법은 Treemap과 일치하며 전통적인 평등 방법보다는 비교기 또는 비교 가능성을 통해 결정됩니다. 관심있는 친구들은 TreeSet의 소스 코드를 확인할 수 있습니다.
읽어 주셔서 감사합니다. 도움이되기를 바랍니다. 이 사이트를 지원 해주셔서 감사합니다!