Javaのコレクション

コレクション反復子

現在、Javaには3つのイテレータがあります。IteratorIterable ListIterator。

  1. まず、イテレーターインターフェースを確認します。

public interface Iterator { boolean hasNext(); E next(); void remove(); } 提供されるAPIインターフェースの意味は次のとおりです:hasNext():コレクションに別のオブジェクトがあるかどうかを判別します。next():コレクション内の次のオブジェクトを返し、アクセスポインターを1ビット移動します。remove():コレクションのnext()メソッドを呼び出して返されたオブジェクトを削除します。JDKの初期バージョンでは、コレクションを走査する方法は1つしかなく、それはイテレーターを介して操作することでした。具体的な例は次のとおりです。








复制代码
リストリスト=新しいArrayList <>();
list.add(10);
list.add(20);
list.add(30);
イテレータiter = list.iterator();
while(iter.hasNext()){ Integer next = iter.next(); System.out.println(next); if(next == 20){ iter.remove(); } } 复制代码2。Iterable接口







1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface Iterable { Iterator iterator(); // JDK 1.8以降デフォルトvoid forEach(Consumer <?super T> action){ Objects.requireNonNull(action); for( T t:this){ action.accept(t); } } // JDK 1.8以降のデフォルトSpliterator spliterator(){ return Spliterators.spliteratorUnknownSize(iterator()、0); } }  Iterator()メソッドがIterableインターフェースで提供されていますイテレータを返すため、Iterableインターフェースを実装するコレクションは、引き続きイテレータを使用して、コレクション内のオブジェクトを走査および操作できます。JDK 1.8では、新しいメソッドforEach()がIterableインターフェースに追加されました。これにより、拡張forループがオブジェクトをトラバースできるようになります。













为什么要设计两个接口Iterable和Iterator?Iterator接口的保留可以让子类去实现自己的迭代器,而Iterable接口更加关注于for-each的增强语法。
  1. ListIterator

ListIteratorはIteratorインターフェースを継承し、Listコレクションにのみ存在します。メソッドを呼び出すことにより、開始インデックスがindexであるイテレータを返すことができます。ListIteratorにはいくつかの重要なメソッドがあり、そのほとんどはIteratorで定義されているのと同じ意味を持ち、さらに、返されたイテレータに従って双方向トラバーサルを実現できます。

1
2
3
4
5
6
7
8
9
10
11
12
public interface ListIterator extends Iterator { boolean hasNext(); E next(); boolean hasPrevious(); E previous(); int nextIndex(); int previousIndex(); void remove (); //現在の添え字の要素、つまり最後にアクセスした要素を置き換えるvoid set(E e); void add(E e); Three、MapおよびCollectionインターフェース











MapインターフェースとCollectionインターフェースは、Javaコレクションフレームワークの2つの重要な学校です。Collectionはコレクション要素自体を格納し、Mapは<key、value>のキーと値のペアを格納しますが、一部のCollectionサブクラスはMapを使用して実現します。たとえば、HashSetの最下層はHashMapを使用し、TreeSetの最下層はTreeMapを使用し、LinkedHashSetの最下層はLinkedHashMapを使用します。

Mapインターフェースのデータ構造は、<key、value>の形式です。キーマップ値。キーは値に対応します。キーを繰り返すことはできず、値を繰り返すことができます。Mapインターフェースは、さまざまなカテゴリーに細分されています。

SortedMap接口:该类映射可以对<key, value>按照自己的规则进行排序,具体实现有 TreeMap
AbsractMap抽象类:它为子类提供好一些通用的API实现,所有的具体Map如HashMap都会继承它

Collectionインターフェースは、すべてのコレクションに共通のメソッドを提供します(Mapはここには含まれていません):
addメソッド:add(E e)/ addAll(Collection <?extends E> var1)/ addAll(int index、Collection <?extends E> var1)
Findメソッド:contains(Object var1)/ containsAll(Collection <?> var1)/
コレクション自体の情報をクエリします:size()/ isEmpty()
Deleteメソッド:remove(O o)/ removeAll(Collection <?> var1)/ Find交差を検索します:RetainAll(コレクションc)

... ...

コレクションインターフェイスは、コレクションをさまざまなカテゴリに分割します。

Set接口:一个不允许存储重复元素的无序集合,具体实现有HashSet / TreeSet···
List接口:一个可存储重复元素的有序集合,具体实现有ArrayList / LinkedList···
Queue接口:一个可存储重复元素的队列,具体实现有PriorityQueue / ArrayDeque···
  1. Mapインターフェースの詳細説明
    Mapシステムは、主に2種類のコレクションに分類されます:AbstractMapとSortedMap。AbstractMap
    は、Mapインターフェースの拡張です。これは、通常のMapコレクションの共通メソッドを定義します。これにより、サブクラスが同じコードを大量に作成することを回避できます。AbstractMapを継承した後、サブクラスを繰り返すことができます。そのメソッドを記述し、追加のロジックを実装して、より多くの外部関数を提供します。
    SortedMapインターフェースは、Mapのソート動作を定義します。サブクラスがそれを実装する場合、ソート機能を外部に提供するためにすべてのメソッドを書き直す必要があります。

1.1 HashMap
HashMapは、要素を格納するためのハッシュテーブルの最も一般的な使用法のコレクションです。要素がHashMapに追加されると、キーのハッシュ値が配列のインデックス添え字に変換され、格納場所が決定されます。要素を検索する場合、要素はキーのハッシュに基づいています。アドレスは、検索位置を決定するために、配列の添字添え字に変換されます。
HashMapの最下層は、3つのデータ構造で実装されています:配列+リンクリスト+赤黒木。これはスレッドセーフではないコレクションです。

要素を追加するときにハッシュの競合がある場合、HashMapは同じアドレスの要素をリンクリストにリンクします。リンクリストの長さが8を超え、配列の長さが64を超える場合、赤黒のツリーデータ構造に変換されます。

HashMapについての簡単な要約:
1.これは、コレクションで最も一般的に使用されるMapコレクションタイプです。最下層は、配列+リンクリスト+赤黒木で構成されます
。2. HashMapはスレッドセーフではありません。3.
要素を挿入するとき、要素のハッシュ値を計算します、ハッシュマッピング関数を介して配列添え字に変換されます。要素を検索するとき、配列添え字配置要素の位置はハッシュマッピング関数を介して取得されます。

1.2 LinkedHashMap
LinkedHashMapは、HashMapとLinkedListの組み合わせと見なすことができます。これは、HashMapに基づいて二重リンクリストを追加し、各要素の挿入順序をデフォルトで格納しますが、この二重リンクリストにより、LinkedHashMapはLRUキャッシュ消去戦略を実装できます。要素のアクセス順序に従ってソートされるようにこの二重にリンクされたリストを設定できるため

1
2
3
4
//ヘッドノードの
一時的なLinkedHashMap.Entry <K、V> head;
//テールノードの
一時的なLinkedHashMap.Entry <K、V> tail;
LinkedHashMapは、メソッドを提供するため、LRUキャッシュの削除戦略を実装するために使用できます:

1
2
3
protected boolean removeEldestEntry(java.util.Map.Entry <K、V> eldest){ return false; } このメソッドは、リンクリストの先頭に最も近いノードを削除でき、get(key)メソッドのソースコードは次のとおりです。 、その役割はノードの位置を移動することです:


1
2
3
4
5
6
7
8
public V get(Object key){ Node <K、V> e; if((e = getNode(hash(key)、key))== null)return null; if(accessOrder)afterNodeAccess(e); return e.value; } get(key)が呼び出され、accessOrder = trueである限り、ノードはリンクリストの最後に更新されます。特定のロジックはafterNodeAccess()にあります。ソースコードは次のとおりです。







コードをコピーします
void afterNodeAccess(Node <K、V> e){//ノードを最後の
  LinkedHashMap.Entry <K、V>に移動しますlast;
  if(accessOrder &&(last = tail)!= e){     LinkedHashMap.Entry <K、 V> p =(LinkedHashMap.Entry <K、V>)e、b = p.before、a = p.after;     p.after = null;     if(b == null)head = a;      そうでなければb.after = a;     if(a!= null)a.before = b;     else last = b;     if(last == null)head = p;     else {       p.before = last;       last.after = p;     }     tail = p;     ++ modCount;   } } コードのコピーaccessOrder = trueを指定すると、リンクリストをアクセス順に配置するように設定でき、提供されたコンストラクターを介してaccessOrderを設定できます。
















public LinkedHashMap(int initialCapacity、float loadFactor、boolean accessOrder){ super(initialCapacity loadFactor ); this.accessOrder = accessOrder; } 内部的に定義されたロジックであるremoveEldestEntry()メソッドを書き換えて、通常、容量が上限に達しているかどうかを判別し、達している場合は消去を実行します。



LinkedHashMapに関する2つのポイントを要約し
ます。1.最下層は二重にリンクされたリストを維持し、HashMapを継承するため、スレッドセーフではありません
。その時に満たすべき条件。

1.3 TreeMap
TreeMapはSortedMapのサブクラスであるため、並べ替え機能を備えています。赤黒木データに基づいて実装されます。各キーと値のペア<key、value>はノードであり、デフォルトでキーによって自然に並べ替えられます。 1つは、カスタムコンパレータで渡すことにより、カスタムルールでソートできることです。

//キーの自然な並べ替えによると、整数の自然な並べ替えは昇順
TreeMap <Integer、Object> naturalSort = new TreeMap <>();
//カスタムの並べ替え、キーの降順で並べ替え
TreeMap <Integer、Object> customSort = new TreeMap <>( (o1、o2)-> Integer.compare(o2、o1));

図の赤黒ツリーの各ノードはエントリです。キーと値はここではマークされていません。これらの要素はキーに従ってソートされており、データ構造全体が整然とした状態にあります!
自然ソートとカスタムソートについて:
自然ソート:キーはComparableインターフェースを実装する必要があります。
IntegerクラスはComparableインターフェースを実装しているため、自然なソート規則に従って、キーは小さいものから大きいものへとソートされます。

TreeMap <Integer、String> treeMap = new TreeMap <>();
treeMap.put(2、 "贰");
treeMap.put(1、 "壹");
System.out.print(treeMap);
// {1 = 1、2 = 2}
カスタマイズされたソート:TreeMapを初期化するときに、新しいコンパレータを渡します。キーは、Comparableインターフェースを実装する必要はありません。

コードをコピーする
TreeMap <Integer、String> treeMap = new TreeMap <>((o1、o2)-> Integer.compare(o2、o1));
treeMap.put(1、 "壹");
treeMap.put(2、 " ); ");
treeMap.put(4、"
"); treeMap.put(3、"三 ");
System.out.println(treeMap);
// {4 = 4、3 = 、2 = 2、 1 =一}
コードのコピー
TreeMapに関する3つのポイントが主に紹介されています:
1.その最下層は赤黒木によって実装され、操作時間の複雑さはO(logN);
2. TreeMapはキーを自然にまたはカスタムソートによってソートできます。 、カスタムソートにはコンパレータを渡す必要がありますが、自然なソートにはComparableインターフェースを実装するためのキーが必要です;
3. TreeMapはスレッドセーフではありません。

1.4 WeakHashMap WeakHashMap
の下部に格納されている要素のデータ構造は、配列+リンクリストであり、赤黒木はありません。日常の開発ではめったに使用されません。Mapに基づいて実装されます。Entryのキーはすべてのガベージコレクションでクリアされます。これは、短時間または1回アクセスされ、WeakHashMapにキャッシュされ、できるだけ早くリサイクルされる要素に適しています。

public class WeakHashMap <K、V> extends AbstractMap <K、V> implements Map <K、V> { }   EntryがGCの場合、WeakHashMapは要素がリサイクルされたことをどのように認識しますか?

    在 WeakHashMap 内部维护了一个引用队列queue:

private final ReferenceQueue queue = new ReferenceQueue <>();
キューには、GCによってドロップされたすべてのキーが含まれます。JVMがGCをオンにすると、WeakHashMapのキーがリサイクルされると、キーはexpungeStaleEntries()のキューに配置されますキューをトラバースし、キュー内のすべてのキーを取り出し、WeakHashMapでそれらを削除して同期を達成します。

図の点線でマークされた要素は、次にWeakHashMapにアクセスしたときに削除されます。WeakHashMapは内部で一連の調整を行うため、キューの役割は、GCで削除された要素をマークすることです。
WeakHashMapについて注意すべき点が3つあり
ます。1。そのキーは弱いキーの一種です。WeakHashMapに入れられると、いつでもリサイクルされるため、特定のアクセス要素が存在する必要があるという保証はありません
。2。通常のマップに依存して実装されます。非スレッドセーフなコレクション;
3.通常、WeakHashMapはキャッシュとして使用され、一度だけアクセスする必要がある、または短時間だけ保存する必要があるキーと値のペアを保存するのに適しています。

1.5 HashTable
Hashtable 基本的なストレージ構造は、スレッドセーフなコレクションである配列+リンクリストです。リンクリストが長すぎると、クエリの効率が低くなり、Hashtableが長時間ロックされるため、並行環境ではパフォーマンスが非常に低下します。基本的には削除され、めったに使用されません。スレッドセーフ、そのすべてのメソッドにsynchronizedキーワードが追加されました。HashTableのデフォルトの長さは11で、負荷係数は0.75Fです。つまり、要素の数が配列の長さの75%に達すると、拡張が実行され、各拡張は元の配列の長さの2倍になります。


  1. コレクションコレクションシステムの詳細な説明コレクションコレクションシステムの最上位のインターフェイスはコレクションであり、コレクションの下で一連のメソッドを指定します。
    コレクションは、リスト、セット、キュー
    セットの3つのタイプのコレクションに分けることができます。重複する要素は保存できません。また、ハッシュ関数を使用して、コレクションの内部配置要素に操作をマッピングする必要があります。デフォルトでは、コレクションの内部要素は順不同です。
    リストインターフェイス:繰り返し要素を格納でき、コレクション内の要素は、要素が挿入された順序に従って配置され、要素はインデックスによってアクセスできます。
    キューインターフェイス:キューはストレージ構造として使用され、コレクション内の要素は規則正しく配置されます。操作できるのはヘッドノード要素のみで、キューの途中の要素にはアクセスできません。
    上記の3つのインターフェースは最も一般的で抽象的な実装であり、各コレクションインターフェース内でより具体的なパフォーマンスが得られ、さまざまな追加機能が派生するため、開発者は各コレクションの利点を比較し、最適なものに基づいてそれらを使用できます。

2.1 Setインターフェース
SetインターフェースはCollectionインターフェースを継承し、繰り返される要素を含まないコレクションです。正確には、Set内の2つの要素はo1.equals(o2)として表示されず、Setは最大で1つのNULL値要素しか格納できません。

Setコレクションシステムでは、2つの点に焦点を当てる必要があり
ます。変数要素を格納するときは、要素の状態が変化するたびに、2つの等しい要素、つまりo1.equals( o2)= trueなので、通常はSetに格納されている要素を変更しないでください。変更すると、equals()の関数が破棄されます。
セットの最大の役割はヘビーを判断することであり、プロジェクトの最大の役割はヘビーを判断することです!

HashSetの
最下層HashSetはHashMapで実装されており、基本的に新しいHashMapである複数の構築メソッドを観察できます。

コードをコピーします
public class HashSet the Set the extends the AbstractSet the implements、Cloneable、the Serializable { public HashSet(){ this.map new new = the HashMap(); } public HashSet(int initialCapacity 、a float loadFactor ){ this.map new new = the HashMap(initialCapacity、loadFactor) ; } public HashSet(int initialCapacity ){ this.map = new HashMap(initialCapacity); } } コードのコピーadd()メソッドとremove()メソッドがHashSetの操作をHashMapに移植する方法を観察できます。











コードをコピーします
Private the PRESENT static Final Object = new new Object();
public Boolean the Add(E E){ return this.map.put(E、PRESENT)== null; } public Boolean Remove(Object O){ return this.map。 remove(o)== PRESENT; } コードHashMapの値をコピーします。HashSetを使用する開発者は、挿入する必要があるキーに注意を払うだけで、HashMapの値をシールドできます。






HashSetはHashMapに基づいて実装されているため、多くの場所をHashMapにリンクできます。
基礎となるデータ構造:HashSetは、配列+リンクリスト+赤黒木も使用して
スレッドセーフを実現します。HashMapの実装により、HashMap自体はスレッドセーフではなく、HashSetにはありません追加の同期戦略を追加して、HashSetが
オブジェクトの状態をHashSet 保存するのもスレッドセーフではないようにします。状態が変更された後、2つの要素o1.equals(o2)がセットに表示され、equals( )セマンティクス。

LinkedHashSet
LinkedHashSetには、次のようなかわいそうな小さなコードがあります。

复制代码
パブリッククラスLinkedHashSetのは
HashSetの延び
用具セット、Cloneableを、java.io.Serializableのを{

private static final long serialVersionUID = -2851667679971038690L;
public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
    super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
    super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);
    addAll(c);
}
@Override
public Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}

}
アマゾン評価www.yisuping.com

おすすめ

転載: blog.csdn.net/weixin_45032957/article/details/108576533