実際のプロジェクト開発には多くのオブジェクトがあります。 Javaは、このような問題を解決するための収集フレームワークを提供しますクラスはjava.utilパッケージにあり、リスト1はコレクションクラス間の関係について説明します。
リスト1。コレクションクラス間の関係
コレクション
├リスト
│├LinkedList
│laarraylist
│装置
│kstack
└セット
地図
バッシュテーブル
ファシュマップ
sweakhashmap
コレクションインターフェイス
コレクションインターフェイス
コレクションは、最も基本的なコレクションインターフェイスです。つまり、コレクションの要素を表します。同じ要素を許可し、ソート要素をサポートしているコレクションもあれば、機能していないコレクションもあります。 JDKは、コレクションから直接継承されたクラスを提供しません。コレクションインターフェイスを実装するすべてのクラスは、2つの標準的なコンストラクターを提供する必要があります。後者のコンストラクターを使用すると、ユーザーはコレクションをコピーできます。
コレクション内の各要素を反復する方法は?
実際のタイプのコレクションに関係なく、このメソッドは反復的な子供を返し、反復子を使用してコレクションの各要素に1つずつアクセスします。典型的な使用法は次のとおりです。
iterator it = collection.iterator();
コレクションインターフェイスの2つのインターフェイスはリストとセットです。
コレクションインターフェイスによって提供される主な方法:
1。ブールアンド(オブジェクトo)コレクションにオブジェクトを追加します。
2。Booleanremoty(オブジェクトo)指定されたオブジェクトを削除します。
3。intsize()現在のコレクションの要素の数を返します。
4。Booleanが含まれます(オブジェクトo)セットに指定されたオブジェクトがあるかどうかを見つけます。
5。Booleanisempty()セットが空であるかどうかを判断します。
6。ITERATORITERATOR()ITERATORを返します。
7。ブールcontasall(コレクションc)セットにセットCに要素があるかどうかを見つけます。
8。BooleanAddall(コレクションC)は、コレクションCのすべての要素をコレクションに追加します。
9。voidclear()セット内のすべての要素を削除します。
10。void removeall(コレクションC)セットCコレクションの要素をコレクションから削除します。
11。voidresterall(collection c)コレクションCに含まれていない要素をコレクションから削除します。
リストインターフェイスをリストします
リストは、このインターフェイスで各要素挿入の位置を正確に制御できる整然としたコレクションです。ユーザーは、インデックス(リスト内の要素の位置、配列入札と同様)を使用して、Javaアレイに似たリスト内の要素にアクセスできます。以下に説明するセットとは異なり、リストでは同じ要素が許可されています。
コレクションインターフェイスに必要なIterator()メソッドに加えて、ListはListTratorインターフェイスを返すListIterator()メソッドも提供します。標準のイテレーターインターフェイスと比較して、ListCotratorにはadd()などのいくつかの方法があり、追加、削除、設定要素、前方トラバーサルなどの関数を許可します。リストインターフェイスを実装するために一般的に使用されるクラスには、LinkedList、ArrayList、Vector、Stackが含まれます。
リストインターフェイスによって提供される主な方法:
1。void add(int index、object element)指定された場所にオブジェクトを追加します。
2。BooleanAddall(intインターン、コレクションC)は、セットCの要素を指定された位置に追加します。
3。オブジェクトGET(int index)リスト内の指定された位置で指定された要素を返します。
4。INDEXOF(オブジェクトO)最初の要素oの位置を返します。
5。オブジェクトremoveInt(int index)指定された位置の要素を削除します。
6。オブジェクトセット(int indexex、オブジェクト要素)要素要素の位置インデックスの要素を置き換えて、交換可能な要素を返します。
マップインターフェイス
MAPはCollegインターフェイスを継承しませんでした。マップは、キーから値へのマッピングを提供することはできません。各キーは1つの値のみをマップできます。マップインターフェイスは、3つのビューセットを提供します。マップコンテンツは、キーセット、値のグループ、またはキー価値マッピングのセットと見なすことができます。
MAPで提供される主な方法:
1。ブール等等(オブジェクトO)比較オブジェクト。
2。Booleanremove(オブジェクトo)オブジェクトを削除します。
3。Put(オブジェクトキー、オブジェクト値)キーと値を追加します。
ランダムアクセスインターフェイス
ランダムアクセスインターフェイスは、ランダムアクセスインターフェイスを呼び出すことで高速でランダムアクセスをサポートするオブジェクトと見なすことができません。このインターフェイスの主な目的は、高速でランダムなアクセスをサポートできるリストの実装を識別することです。配列ベースのリストの実装は、raodomaccessインターフェイスを実装しますが、リンクされたリストベースの実装ではそうではありません。アレイのみが迅速なランダムアクセスを実行できるため、リンクされたリストへのランダムアクセスは、リンクリストによって移動する必要があります。したがって、このインターフェースの利点は、アプリケーションでは、処理されているリストオブジェクトが高速かつランダムアクセスを実行して、プログラムのパフォーマンスを改善するために異なるリストに対して異なる操作を実行できるかどうかを知ることができることです。
導入
LinkedListクラス
LinkedListはリストインターフェイスを実装し、null要素を許可します。さらに、LinkedListは、LinkedListの最初またはテールでデータを操作するための追加のGET、削除、挿入、およびその他のメソッドを提供します。これらの操作により、LinkedListはスタック、キュー(キュー)、または2回のキューとして使用できます。 LinkedListには同期方法がありません。つまり、複数のスレッドが同時にリストにアクセスする場合は、独自のアクセス同期を実現する必要があります。 1つの解決策は、リストを作成するときに同期リストを作成することです。
リストリスト= collections.synchronizedList(new LinkedList(…));
ArrayListクラス
ArrayListは、可変サイズ配列を実装します。 nullを含むすべての要素が可能になります。サイズ、ISEMPTY、GET、SET、およびその他の方法は実行時間ですが、オーバーヘッドの追加は、n要素のn要素がO(n)時間を必要とし、他のメソッドは線形です。
各ArrayListインスタンスには、ストレージ要素の配列のサイズを保存する容量(容量)があります。大量の要素を挿入する必要がある場合は、挿入効率を向上させるためにアレイリストの容量を増やすために挿入する前に、essurecapacityメソッドを呼び出すことができます。 LinkedListと同様に、ArrayListはスレッドではありません。
ArrayListによって提供される主な方法:
1.ブール酸(オブジェクトO)は、指定された要素をリストの最後に追加します。
2。BooleanAdd(int indexex、オブジェクト要素)には、リストに指定された要素を追加する位置を指定します。
3。BooleanAddall(Collection C)は、指定されたセットをリストの最後に追加します。
4.ブールアドラル(intインターレッグ、コレクションC)リスト内の指定された場所に指定されたコレクションを追加します。
5。booleanclear()リスト内のすべての要素を削除します。
6。booleanclone()リストのリストのコピーに戻ります。
7。Booleanが含まれます(オブジェクトo)リストに要素が含まれているかどうかを決定します。
8。ブールアレンカ科(int m)は、リストの容量を増加させます。
9。オブジェクトGET(int index)リスト内のリストで指定された要素を返します。
10。リスト内のindexof(オブジェクトエレム)は、指定された要素の入札を見つけます。
11。intsize()現在のリストの要素の数を返します。
ベクトルクラス
ベクトルはArrayListに非常に似ており、違いはベクトルがスレッドによって同期されることです。ベクトルによって作成された反復器は、アレイリストによって作成された反復器は同じポートです。ベクターが同期しているため、1つのイテレーターが作成および使用されると、他のスレッドはベクトルのステータスを変更しました(たとえば、一部の一部を追加または削除します。状態要素)、Iteratorメソッドが呼び出されると、concurrentModificationExceptionが廃止されるため、例外をキャプチャする必要があります。
スタッククラス
ベクトルから継承され、その後高度になったスタックを実現しました。 Stackは、ベクトルがスタックとして使用される5つの追加方法を提供します。基本的なプッシュメソッドとポップメソッドに加えて、空のメソッドがスタックが空であるかどうかをテストするためのピークメソッドと、スタック。スタックが作成された後、それは空のスタックであることに注意してください。
クラスを設定します
セットは、繰り返される要素のないコレクションです。つまり、任意の2つの要素E1とE2にE1.Equals(e2)= falseがあります。ほとんどの場合、ヌル要素があります。明らかに、セットのコンストラクターには制約条件があり、収集パラメーターの入力には重複要素を含めることはできません。変数オブジェクトを慎重に操作する必要があることに注意してください。
ハッシュテーブルクラス
ハッシュテーブルはマップインターフェイスを継承し、キー価値マッピングに基づいてハッシュテーブルを実装します。非ヌルオブジェクトは、キーまたは値として使用できます。 Put(key、value)を使用するデータを追加し、Get(key)を使用するデータを取り出します。
Hashtableは、初期容量と負荷係数の2つのパラメーターを使用してパフォーマンスを調整します。デフォルトの負荷係数0.75は、時間と空間のバランスをより良く実現します。負荷係数を増やすとスペースを節約できますが、対応する検索時間は増加し、GetやPutなどの操作に影響します。ハッシュテーブルの簡単な例を使用して、ハッシュテーブルに1、2、および3の3を配置します。
リスト2。ハッシュテーブルの例
hashtable numbers = new Hashtable(); numbers.put(“ One”、new Integer(1)); numbers.put(“ 2”、new Integer(2)); numbers.put(“ 3”、new Integer(3) );
2などの番号を取り出す必要がある場合は、対応するキーを使用してそれを取り出すことができ、コードをリスト3に示します。
リスト3。Hastableのデータを読む
integer n =(integer)numbers.get( "2"); out.println( "2 ="+ n);
キーのオブジェクトは、その分布関数を計算して対応する値の位置を決定することによって決定されるため、キーとしてのオブジェクトはハッシュコードを実装し、メソッドに等しくなります。ハッシュコードと等しいメソッドは、キーとしてカスタムクラスを使用する場合は、2つのオブジェクトが同じである場合、obj1.equals(obj2)に注意してください。 =ハッシュコードは同じでなければなりませんが、2つのオブジェクトが異なる場合、2つの異なるオブジェクトのハッシュコードが同じであるとは限りませんハッシュテーブルの動作をスピードアップできるHashCode()メソッド。
同じオブジェクトが異なるハッシュコードを持っている場合、ハッシュテーブルの操作には予期しない結果があります(この問題を回避するのを楽しみにしています)。それらの1つを書くだけではありません。
ハッシュマップクラス
ハッシュマップはハッシュテーブルに似ています。違いは、ハッシュマップが非同化スレッドであり、null値とnullキーを可能にすることです。ただし、ハッシュマップがコレクション(値()メソッドを返すことができる)と見なされる場合、反復的なサブ操作時間とハッシュマップの容量に比例します。したがって、反復操作のパフォーマンスが非常に重要な場合は、ハッシュマップの初期化容量を高すぎたり、負荷係数パラメーターで設定しすぎたりしないでください。
WeakHashmapクラス
Weakhashmapは、キーが外部で引用されなくなった場合、キーを「弱い参照」で改善します。
コレクションクラスの練習
ArrayList、Vector、およびLinkedListはすべてAbstractListから実装されており、AbstractListはリストインターフェイスを直接実装し、abstarctCollectionから拡張されます。 ArrayListとVectorは、ArrayListを実装しています。 LinkedListは、一連のテーブルアイテムに接続されている円形の2つのリンクデータ構造を使用します。
ArrayListの容量に対する需要が現在の配列のサイズを超える場合、拡張する必要があります。容量拡張プロセス中に、多数の配列複製操作が実行され、配列が複製されると、System.ArrayCopy()メソッドが最終的に呼び出されます。 LinkedListはリンクリストの構造を使用しているため、容量のサイズを維持する必要はありません。配列の連続性のため、要素が常に端に増加する場合、スペースが不十分な場合にのみ、アレイの拡張と配列の複製を生成できます。
ArrayListは配列に基づいており、配列の任意の場所に要素が挿入されている場合、その位置を再配置する必要があります。 LinkedListは、データの挿入によりパフォーマンスを低下させません。
ArrayListの各効果的な要素は、操作を削除した後に再編成する必要があり、削除された要素位置の位置が高いほど、アレイの再編成中のオーバーヘッドが大きくなります。 LinkedListは、半分のリストの中間データを削除する必要があります。
リスト4。ArrayListおよびLinkedListはコードを使用します
Java.util.util.linkedlist; = new object(); m currenttimemillis(); (); out.println(end-start); 0、obj2) 1000; list1.add(obj1);} system.out.println(end-start); System.Currentttimemillis(); ;}}
リスト5。出力を実行します
639129669690015
HashMapは、キーアルゴリズムを作成し、ハッシュ値をメモリアドレスにマッピングして、キーに対応するデータを直接取得することです。 HashMapでは、基礎となるデータ構造が配列を使用し、So -Calcaled Memoryアドレスは配列のラベルインデックスです。 Hashmapの高性能には、次のポイントが必要です。
1.ハッシュアルゴリズムは効率的でなければなりません。
2。メモリアドレスに対するハッシュ値のアルゴリズム(配列インデックス)は高速です。
3。メモリアドレス(配列インデックス)によると、対応する値を直接取得できます。
HashMapは、実際にはリンクリストの配列です。前述のように、ハッシュコード()およびハッシュ()メソッドが可能な限り競合の発生を減らすのに十分なほど達成されている限り、ハッシュマップに基づくリンクリストメソッドに基づく実装メカニズムは、ハッシュマップの動作はアレイの配列へのランダムアクセスにほぼ同等です。ただし、Hashcode()またはHash()メソッドがあまり達成されていない場合、Hashmapは実際にいくつかのリンクリストに分解されます今回は、パフォーマンスは非常に貧弱です。
ハッシュマップの機能的な欠点は、ハッシュマップを横断する場合、その出力が無秩序に保存されます。入力注文を維持する場合は、代わりにLinkedHashmapを使用できます。
LinkedhashmapはHashmapから継承され、同時にHashmapに基づいて、リンクされたリストが追加されて要素の順序を保存します。
HashMapは、Hashアルゴリズムと同じくらい速くput()およびget()を動作させることができます。 Treemapは、まったく異なるマップの実装を提供します。機能の観点から、TreemapはHashmapよりも強力な機能を備えています。つまり、要素をソートできることを意味します。 Treemapのパフォーマンスは、Hashmapよりもわずかに低いです。開発中の要素をソートする必要がある場合、この関数をハッシュマップで実装することはできません。 Linkedhashmapは、コレクションに入る要素の順序またはアクセスの順序に基づいています。
LinkedHashmapは、要素の増加またはアクセスの順序に従ってソートされ、Treemapは要素のキーに従ってソートされます。
リスト6は、コードがTreeMapを使用してビジネスロジックの順序を示していることを示しています。
リスト6。Treemapはソートを実装します
java.util.map.util.treemapをインポートします名前; score = score;} @ouverride // treemap public int compareto(sudent o){// todo-generated method(o.score <this.scまたは{return 1;} if if (O.Score> this.Score){return -1;} @overridepublic string toString(){StringBuffer sb = new StringBuffer( "name:"); ; sb.append( "); ();学生S1 =新しい学生( "1"、100);学生S2 =新しい学生( "2"、99);学生S3 =新しい学生( "3"、97);学生S4 =新しい学生( "4 4 "、91); map.put(s1、new Studentdetailinfo(s1)); map.put(s2、new Studentdetailinfo(s2)); map.put(s3、new Studentdetailinfo(s3)); s4、new StudentDetailinfo(S4(S4) ); //スコアMap1 =(treemap).submap(s4、s2);次(); system.out.println(key+" - >"+map.get(key));} out.println( "" submap end "); // map1 =((timemap)map)。 (s1)(iterator = map1.keyset() (key));} system.out.println( "submap end"); //印刷スコアmap1 =((treemap).tailmap(s1); ;){学生キー=(学生)次の(Student s){this.s = s;}@ounridepublic string toString(){return s.name + "'s detail情報";}}}
リスト7。出力を実行します
名前:4スコア:91-> 4の詳細情報名:3スコア:97-> 3の詳細情報版エンド名:4スコア:91-> 4の詳細情報名:3スコア:97-> 3の詳細情報名:2スコア:99- > 2の詳細情報ubmap endname:1スコア:100-> 1の詳細情報bmap end
WeakHashmapは、引用を除いてこのキーに他のcitherがない場合、このマップが値を自動的に破棄することを特徴としています。リスト8に示されているように、コードは2つのマップオブジェクトを表示します。1つはHashmapです。 null、彼らはnullを指します。この状況の理由は、オブジェクトAの場合、ハッシュマップが削除され、nullが弱いハッシュマップに加えてAを除いてAへのポインターはないため、nullを指している場合、ハッシュマップでBを指しているポインターがあるためBオブジェクトを保持します。
リスト8.WeakHashmapの例コード
Import Java.util.util.map; string( "); 、B、B、B、B、B、B、B、B、B、B、B、 "BBB"); 、「bbb」) .entry en =(map.entry)izext(); 。 +en.getValue());
リスト9。出力を実行します
マップ:B:BBBWeakMap:B:BBB
Weakhashmapは、主に、expungestaleentriesを介して内部の未使用のエントリを削除する目的を達成し、それによりメモリを自動的にリリースする目的を達成します。基本的に、WeakHashmapの内容にアクセスされる限り、この関数はもはや参照されていない内部エントリを実現するために呼び出されます。しかし、もしあなたがWeakHashmapになり、GCの前に、あなたが弱体ハッシュマップを訪問したことがないなら、メモリをリリースすることは無限ではありませんか?
リスト10。WeakHashMaptest1
java.util.arraylist; ] [] >> maps = new arrayList <weakhashmap <byte [] []、byte [] [] >>(); byte [] []> d = new weakhashmap <byte [] []、byte [] []>(); .add(d); gc();
操作リストに表示されているJVMパラメーターリスト10を変更しないでください。
リスト11。出力を実行します
241242243スレッドのexcetion "main" java.lang.outofmemoryerror:java heap spaceat weakhashmaptest1.main(weakhashmapst1.java:10)
案の定、WeakHashmapは現時点では不要なメモリを自動的に放出しませんでした。リスト12に示されているコードには、メモリオーバーフローがありません。
リスト12。WeakHashMaptest2
java.util.arraylist。 ] [] >> maps = new arrayList <weakhashmap <byte [] []、byte [] [] >>(); byte [] []> d = new weakhashmap <byte [] []、byte [] []>(); .add(d); system.err.println(i); .get(j).size());}}}}
操作の結果は、テスト出力が正常であり、メモリオーバーフローの問題が発生しなくなったことを発見しました。
一般に、WeakHashmapは、何かをしても内部で使用されないオブジェクトではなく、アクセス時に内部の未使用オブジェクトをリリースします。
WeakHashmapは、そのエントリ<K、V>がWeakReference <K>から継承されるため、弱い参照を実装します。
weakhashmap $ entry <k、v>のクラス定義とコンストラクターでは、リスト13に示されています。
リスト13。WeakHashmapクラスの定義
private static class entry <k、v> extends weakreference <k> extments map.entry <k、v> entry(k key、v value、referencequeue <k> queue、int hash、entry <k、v> next){super (キュー); value = hash = hash;}
父親の声明を構築してください:「super、queue); "; system.gc()では、キー内のバイト配列がリサイクルされ、値が残ります(値はエントリに強く関連付けられ、エントリはマップに関連付けられ、マップはアレイリストに関連付けられています)。
GCはweakReferenceキーでバイト配列をリサイクルし、参照キューにイベントを通知しますが、Put操作の後、毎回新しいWeakhashmapを使用するたびに、参照q Ueueを処理するためにWeakhashmapをトリガーする対応するアクションはありません。キーはまだ弱者に存在し、その対応する値も存在します。
値はいつリスト10とリスト11を分析しますか? ? WeakHashmapソースコードを確認してください。サイズメソッドは、このメソッドがJVMによって回収されるように通信し、エントリの値が空であることがわかります。したがって、効果は、GCがクリアされた後にGCとValueがWeakHashmapを訪れたときにキーがクリアされたことです。
WeakHashmapクラスは、collections.synchronizedmapメソッドを使用して、同期されたWeakhashmapを構築できます。したがって、マッピング内であろうとマッピングの外側であろうと、Garbage Recylerが特定のキーへの弱い参照を削除した後にのみ、キーは自動的に削除されます。 WeakHashmapの値オブジェクトは一般的な魅力によって保持されていることに注意する必要があります。したがって、値オブジェクトが独自のキーを直接または間接的に参照しないように注意する必要があります。値オブジェクトは、WeakHhashmap自体を介して対応するキーを間接的に引用できることに注意してください。つまり、特定の値オブジェクトは他のキーオブジェクトによって強く参照され、キーオブジェクトに関連付けられた値オブジェクトは最初のオブジェクトにターニングして最初のオブジェクトを参照してください。 1つ。
この問題に対処する1つの方法は、次のような挿入前に値自体を梱包することです「バッキングデバイスは急速に故障します。反復デバイスが作成された後、マッピングが構造から変更された場合、反復因子独自のメソッドを削除または追加しない限り、イテレーターはいつでも変更され、イテレーターはconcurrentModificationExceptionを投げます。したがって、並行性の変更に直面して、イテレーターは、将来いつでも任意の不確実な行動のリスクではなく、すぐに完全に失敗しました。
繰り返しと言えば、非同時の並行性の変更がある場合は、完全に決定された保証を行うことは不可能であることに注意してください。
以前の包括的なコードとインスタンスコードをまとめるには、スタック、キューなどを伴う場合は、リストの使用を検討する必要があることがわかります。迅速な挿入や削除要素などの操作には、LinkedListを使用する必要があります。要素に迅速にアクセスする必要がある場合は、ArrayListを使用する必要があります。プログラムが単一のスレッド環境で実行されるか、1つのスレッドでのみアクセスする場合、非麻痺性クラスを考慮して、効率的です。複数のスレッドが同時にクラスを操作できる場合は、同期クラスを使用する必要があります。ハッシュテーブルの操作に特に注意してください。等しいものとハッシュコードのオブジェクトは、等しいコードメソッドとハッシュコードメソッドを正しく書き込むことです。 ArrayListの代わりに戻るリストなど、実際のタイプの代わりにインターフェイスを返すようにしてください。これにより、ArrayListを将来LinkedListに置き換える必要がある場合、クライアントコードは抽象のプログラミングアイデアを実行する必要はありません。
この記事は、アプリケーションレベルの共有のみです。