JDK1.8.0_144 다운로드 주소 : //www.vevb.com/softs/551512.html
AbstractMap Abstract 클래스는 몇 가지 간단하고 일반적인 방법을 구현하며, 이는 그 자체로 어렵지 않습니다. 그러나이 추상 클래스에는주의를 기울여야 할 두 가지 방법이 있습니다. 키 세트 및 값 메소드 소스 코드의 구현은 교과서 스타일 모델이라고 할 수 있습니다.
초록 클래스는 일반적으로 각 하위 클래스에 대한 공통 방법을 구현하기위한 골격으로 구현됩니다. 이전 기사에서는 MAP 인터페이스를 설명 했으며이 기사는 AbstractMap Abstract 클래스를 분석하고 연구합니다.
Java에는 맵 유형 데이터 구조가 많이 있습니다. AbstractMap은 해골 구현으로서 MAP 인터페이스의 일부 방법을 구현합니다. 즉, 서브 클래스에 대한 공개 메소드를 제공하며 구현이없는 다양한 맵이 다를 수 있습니다.
추상 클래스는 새로운 키워드를 통해 초록 클래스 인스턴스를 직접 생성 할 수 없지만 생성자가있을 수 있습니다. AbstractMap은 보호 된 수정 된 매개 변수가없는 생성자를 제공합니다. 즉, 하위 클래스 만 액세스 할 수 있으며 (물론 추상 클래스 자체이며, 다른 클래스는 직접적으로 인스턴스화 할 수 없음), 즉 서브 클래스만이 매개 변수가없는 생성자를 호출 할 수 있습니다.
항목 인터페이스는 맵 인터페이스에서 내부적으로 정의됩니다. 이 인터페이스는 키 값 키 값 쌍을 유지하기 위해 맵 맵의 내부 구현이며 키 값은이 맵에 저장됩니다. AbstractMap 은이 내부 인터페이스를 구현하고 총 2 개가 있습니다. 하나는 변이 가능한 단순한 것입니다.
공개 정적 클래스 Simpleentry <k, v> 항목 <k, v>, java.io.serializable
map.entry <k, v> 인터페이스가 구현되고 직렬화 될 수 있습니다 (직렬화 될 수 있음).
이 방법은 비교적 간단하며, 모두 값을 취하고 값을 저장하는 작업입니다. 키 값의 정의는 최종 수정이며, 이는 불변의 참조입니다. 또한 SetValue 방법은 약간 특별합니다. 저장된 값은 저장된 값이 아니라 이전 값이 반환되었습니다. 당신이 배워야 할 것은 다시 작성하는 평등 및 해시 코드 방법입니다.
public boolean equals (object o) {if (! (o instanceof map.entry)) // 매개 변수가 map.entry 유형인지 여부를 결정하려면, 동등한 경우, 가장 먼저해야 할 일은 동일한 유형이 동일하게 반환하는 것입니다. map.entry <?,?> e = (map.entry <?,?>) o; // 객체 유형을 MAP.entry 유형으로 강요하면 매개 변수가 "?" 런타임에 일반 유형이 지워지기 때문에 "k, v"대신. 컴파일러는 k와 v가 무엇인지, return eq (key, e.getKey ()) && eq (value, e.getValue ()); // 키와 값은 각각 판단을 위해 EQ 메소드를 호출하고, 둘 다 반환 할 때 동일합니다. } 개인 정적 부울 EQ (Object O1, Object O2) {return o1 == null? O2 == NULL : O1.Equals (O2); //이 3 개 항목 연산자도 매우 간단하지만 O1과 O2는 여기서 객체 유형이지만 객체 유형의 동등한 메소드는 "=="로 참조되므로 여기서는 문제가 있다고 생각하지 않으므로 O1 유형은 문자열이 될 수 있지만 문자열#동일 메소드는 여전히 동등한 메소드를 호출 할 때 여전히 호출 될 수 있기 때문입니다. }Equals 메소드를 올바르게 다시 작성하고 올바르게 사용하려면 일반적으로 해시 코드 메소드를 다시 작성해야합니다.
public int hashcode () {return (key == null? 0 : key.hashcode ()) ^ (value == null? 0 : value.hashcode ()); // 키와 값의 값이 NULL이 아닌 경우 해시 코드가 Xored됩니다. }공개 정적 클래스 SimpleMutableEntry <k, v>는 입력 <k, v>, java.io.serializable simplemutableentry를 구현합니다
불변성으로 정의 된 항목은 setValue 메소드를 제공하지 않기 때문에 실제로 불변이 아니며 여러 스레드에 동시에 액세스 할 때 SetValue 메소드를 통해 자연스럽게 수정할 수 없습니다. Simpleentry와 비교하여 키 및 값 멤버 변수는 최종 유형으로 정의됩니다. setValue 메소드를 호출하면 unsupportedOperationException 예외가 발생합니다.
그와 해시 코드 방법은 Simpleentry와 일치합니다.
그런 다음 AbstractMap Abstract 클래스에서 맵 인터페이스의 어떤 메소드를 구현하는지 확인하십시오.
public int size ()
EntrySet 메소드는 맵에 정의되어 있으며, 이는 맵의 집합 모음을 반환합니다. 세트 컬렉션의 크기 메소드는 맵의 크기 인 직접 호출됩니다.
공개 부울 isempty ()
위의 크기 방법을 0과 같으면 비어 있습니다.
공개 부울은 키 (객체 키)
이 방법의 구현은 비교적 간단합니다. EntrySet 메서드를 호출하여 세트 컬렉션의 반복자를 얻고 매개 변수 키로 횡단합니다. 맵은 NULL의 키 값으로 저장할 수 있습니다. key = null은 특수 스토리지 (해시 코드 값을 계산할 수 없음)와 함께 맵에 저장되므로 매개 변수 키가 비어 있는지 여부를 결정하는 방법도 수행했습니다.
공개 부울이 포함되어 있습니다 (객체 값)
이 방법 구현은 ContainsKey와 일치합니다.
public v get (객체 키)
이 방법 구현은 위의 두 가지와 유사하며, 차이점은 위의 것이 부울과 동일 하며이 방법은 값을 반환한다는 것입니다.
public v put (k key, v value)
키-값 쌍을 맵에 저장하는 방법은 자세히 구현되지 않으며, 지원되지 않은 지출 소지가 직접 던져집니다.
public v remak (객체 키)
매개 변수 키를 통해 맵에 지정된 키 값 키 값 쌍을 삭제하십시오. 이 방법은 또한 매우 간단합니다. 또한 반복자를 통한 세트 컬렉션을 가로 지르고 반복자를 통과하고 해당 키 값을 찾은 다음 반복자#제거 메소드를 호출하여 맵을 삭제합니다.
public void putall (map <? extends k,? extends v> m)
이 방법은 또한 들어오는 맵을 가로 지르고 풋 방법을 호출하여 저장하는 것이 매우 간단합니다.
public void clear ()
EntrySet 메서드를 호출하여 세트 수집을받은 다음 Set#CLEAR () 메서드를 호출하여 지우십시오.
공개 세트 <k> Keyset ()
맵 키 값의 세트 모음을 반환합니다. AbstractMap은 멤버 변수 "Transient Set <k> Keyset"을 정의합니다. JDK7에서 키 세트 변수는 휘발성에 의해 수정되지만 JDK8에서는 휘발성에 의해 수정되지 않습니다. Keyset 변수에 대한 주석에서 이러한 필드에 액세스하는 방법이 자체적으로 동기화되지 않으며 휘발성은 스레드 안전을 보장 할 수 없다고 설명합니다. 키 세트 방법의 구현은 흥미 롭습니다.
우선,이 방법에 대해 생각하면 키 값 세트 세트를 반환하는 것입니다. 당연히 간단한 구현 방법을 생각하고 항목 배열을 가로 지르고 키 값을 꺼내 다음 코드와 유사하게 세트 세트에 넣을 수 있습니다.
public set <k> keyset () {set <k> ks = null; for (map.Entry <k, v> entry : entryset ()) {ks.Add (entry.getKey ()); } return ks;}즉, 키 세트 방법이 호출 될 때마다 입력 배열을 가로 지르고 데이터 볼륨이 클 때 효율이 크게 줄어 듭니다. JDK 소스 코드는 매우 잘 작성되었으며 Traversal의 방법을 채택하지 않습니다. 진입하지 않으면 맵이 현재 키 값 키 값 쌍을 추가했음을 어떻게 알 수 있습니까?
답은 Keyset Method 내부의 새로운 사용자 정의 세트 컬렉션을 다시 구현하는 것이며,이 사용자 정의 세트 컬렉션에서 반복자 메소드가 다시 작성됩니다. 여기 열쇠가 있습니다. 반복 메소드는 반복자 인터페이스를 반환하고 여기에서 다시 구현됩니다. EntrySet 메서드를 호출 한 다음 반복자 메소드를 호출합니다. 다음은 코드와 함께 분석됩니다.
public set <k> keyset () {set <k> ks = 키 세트; // 정의 된 과도 세트 <k> Keyset if (ks == null) {// 첫 번째 호출은 확실히 NULL입니다. 다음 코드를 통해 세트 예제를 작성하십시오. ks = new AbstractSet <k> () {// 사용자 정의 세트 공개 반복기 <k> iterator () {// <k>의 반복자 메소드를 다시 작성하십시오. 반복자 <Entry <k, v >> i = entryset (). iterator (); // 세트 수집 반복자 반복자 공개 boolean hasnext () {return i.hasnext (); // 키 값의 판단은 항목의 판단입니다} public k next () {return i.next (). getKey (); // 다음 키 값은 항목#getKey} 공개 void void remove () {i.remove (); // 키 값을 삭제하고 ender}}}; } public int size () {// 다시 작성된 세트#size method를 반환합니다. // 키의 값은 전체 맵이 얼마나 큰지 이므로이 클래스의 크기 메소드를 호출하십시오. 이것은 내부 클래스입니다. 이 키워드를 사용 하여이 클래스를 직접 대표하십시오. AbstractMap의 크기 메소드가 호출되었음을 나타냅니다. 이것 없이는 정적 정적 메소드라는 것을 의미합니다.} public boolean isempty () {// 다시 작성된 세트#isempty methods reporactMap을 반환합니다. this.isempty (); // 핵심 값이 있는지 여부는 맵이 비어 있는지 여부를 의미 하므로이 클래스의 isempty 메소드를 호출하는 것입니다} public void clear () {// 다시 작성된 세트#clear method actractMap.this.clear (); // 키 값을 지우십시오. 단지지도를 지우는 것이므로이 클래스의 명확한 메소드를 호출하는 것입니다} public boolean 포함 (개체 k) {// rewrite set#포함 메소드 return actractMap.this.containskey (k); // 세트가 데이터 k를 포함하는지 판단합니다. 이는 맵에 키 값이 포함되어 있는지 여부를 의미 하므로이 클래스의 incloinskey 메소드를 호출하십시오}}; 키 세트 = KS; //이 사용자 정의 세트 수집을 변수 키 세트에 할당합니다. 키 세트가 무효가 아니기 때문에 향후 키 세트 메소드를 다시 호출 할 때 직접 반환하면됩니다. } rack ks;나는 이것이 매우 영리한 구현이라고 생각합니다. 이 방법은 키 값을 중심으로 진행되지만 실제로 항목을 가로 지르지 않고 항목과 함께 구현할 수 있습니다. 동시에, 템플릿 메소드 모드의 모범 사례 인 EntrySet# iterator 메소드를 호출하는 것이 위에서 언급되어 있습니다. EntrySet은 AbstractMap에서 구현되지 않지만 완료하기 위해 서브 클래스에 맡겨 지지만 Keyset 메소드는 템플릿 메소드 패턴 인 "알고리즘 골격"으로 구현할 수 있습니다.
공개 컬렉션 <v> value ()
값 메소드의 경우 Keyset을 완전히 참조 할 수 있습니다. 두 사람은 같은 효과를 가지고 있으므로 공간을 절약하기 위해 여기서 반복하지 않을 것입니다.
공개 초록 세트 <Entry <k, v >> entryset ()
추상적 인 방법은 서브 클래스로 넘겨져 완료 하여이 방법이 특히 "일반"이 아님을 나타냅니다.
공개 부울 평등 (Object O)
맵은 맵의 각 키 값 쌍의 키와 값이 하나씩 대응하는 경우에만 적용됩니다. 이 방법에서 먼저 간단한 조건을 판단하십시오. 참조가 동일하면 직접 true를 반환하십시오. 매개 변수 O가 맵 유형이 아닌 경우 직접 false를 반환하십시오. 두 맵의 숫자가 다른 경우 직접 false를 반환하십시오. 그래야만 항목 배열을 반복하고 항목의 키와 값이 하나씩 해당하는지 여부를 비교합니다. 이 방법은 간단하지만 이것은 우리에게 영감을줍니다. 조건부 판단에서, 우리는 먼저 간단한 기본 판단을 판단한 다음 복잡한 것들을 판단해야합니다.
public int hashcode ()
객체 클래스의 평등 메소드를 다시 작성하고 해시 코드를 다시 작성해야합니다. AbstractMap의 해시 코드 구현은 모든 맵의 해시 코드 값을 끝까지 추가하는 것입니다.
공개 문자열 tostring ()
이 방법에 대해 할 말이 없습니다. 모든 키 가치 쌍을 꺼내어 StringBuilder를 사용하여 스플릿 한 것입니다.
보호 된 객체 클론 ()은 ClonenotsupportedException을 던졌습니다
변수 키 세트와 값의 얕은 사본이므로 얕은 사본을 구현하여 두 개의 얕은 사본으로 인한 문제를 방지합니다.