JavaRush /Java Blog /Random-JA /Java のコレクションに関する質問トップ 10
FedoraLinux
レベル 21
Москва

Java のコレクションに関する質問トップ 10

Random-JA グループに公開済み
この記事は、 「Java コレクションに関するトップ 10 の質問 という記事を翻訳したものです。以下は、Stackowerflow で質問および議論された、Java のコレクションに関する最も一般的な質問です。これらの質問を検討する前に、クラス階層図を確認することをお勧めします。 1. ArrayList の代わりに LinkedList を使用するのはどのような場合ですか? ArrayList は実際には配列であり、その要素にはインデックスによって直接アクセスできます。配列がオーバーフローした場合は、より多くのスペースを備えた新しい配列が必要になります。すべての要素を配置して移動するには、O(n) 時間がかかります。また、配列内の既存の要素を移動するには、要素の追加と削除が必要です。これはおそらく ArrayList を使用する際の最大の不便です。LinkedList は要素リンクの二重リストです。したがって、中央の要素にアクセスするには、シートの最初から最後まで検索する必要があります。一方、LinkedList 内の要素の追加と削除は、リスト自体を変更するだけであるため、より高速です。最悪の時間を以下で比較します。
方法 配列リスト リンクリスト
取得(インデックス) ○(1) の上)
追加(E) の上) ○(1)
add(E, インデックス) の上) の上)
削除(インデックス) の上) の上)
Iterator.remove() の上) ○(1)
イテレータ.add(E) の上) ○(1)
実行時間に関係なく、大きなリストの場合はメモリ使用量を個別に考慮する必要があります。LinkedList では、各ノードには前後のノードをリンクするために少なくとも 2 つの追加ポインターが必要ですが、ArrayList では要素の配列のみが必要です。 ArrayList、LinkedList、Vectorリストの比較の詳細。 2. コレクションの反復中に要素を削除するための効率的な同等の方法 反復中にコレクションを変更 (要素を削除) する唯一の正しい方法は、 Iterator.remove()を使用することです。例: 最も一般的なエラーは次のとおりです。 上記のコードの実行中に ConcurrentModificationException が発生します。これは、リスト全体を移動するためにイテレーターが生成されたが、同時に Iterator.remove() を呼び出すことによってシートが変更されたために発生します。この例外のドキュメントに書かれているように、 Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
「別のスレッドがコレクションを反復処理している間に、あるスレッドがコレクションを変更することは一般に許可されません。」
一般に、あるスレッドがコレクションを走査している間に、あるスレッドがコレクションを変更することは受け入れられません。 3. List を int[] 配列に変換するにはどうすればよいですか? これを行う最も簡単な方法は、 Apache Commons Langライブラリにある ArrayUtilsを使用することです。 JDK にはこの式のショートカットはありません。この式は List を Integer[] (プリミティブ型で はない)に変換するため、List.toArray() は使用できないことに注意してください。正しい方法は次のオプションです: 4. int[] 配列をリストに変換するにはどうすればよいですか? 最も簡単な方法は、上記のように、 Apache Commons Langライブラリの ArrayUtilsを使用することです。 また、JDK にはこの式のショートカットはありません。 5. コレクションをフィルタリングする最良の方法は何ですか? GuavaApache Commons Lang などのサードパーティ パッケージを使用して、機能を強化できます。これらのパッケージには両方とも、filter() メソッドがあります ( Guava の Collections2クラスとApache の CollectionUtils内)。filter() メソッドは、指定された述語に一致する要素を返します。JDK ではすべてがより複雑になります。良いニュースとしては、述語が Java 8 に追加される予定ですが 現時点ではコレクション全体を反復処理するために Iterator を使用する必要があります。 もちろん、新しい Predicate インターフェイスに慣れれば、Guava と Apache がたどる道を真似ることもできます。 ここで、次のコードを使用してコレクションをフィルタリングできます。 6. List を Set に簡単に変換するにはどうすればよいですか? これを行うには、平等をどのように定義するかに応じて 2 つの方法があります。コードの最初の部分は、リストを HashSet に入れます。この場合の重複は主に hashCode() によって決定されます。通常、これは機能します。ただし、比較パスを考慮する必要がある場合は、独自のコンパレータを定義できるコードの 2 番目の部分を使用することをお勧めします。 7. ArrayList から重複要素を削除するにはどうすればよいですか? この質問は上記の質問と多少関連しています。ArrayList 内の要素の順序が重要でない場合は、シートを Set に配置して重複を削除し、それを List に戻すのが賢明な方法です。以下に例を示します。 要素の順序が重要な場合は、標準 JDK に含まれる LinkedHashSetにリストを配置することで順序を確保できます。 8. 分類されたコレクション int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } List list = Arrays.asList(ArrayUtils.toObject(array)); int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } public interface Predicate { boolean test(T o); } public static void filter(Collection collection, Predicate predicate) { if ((collection != null) && (predicate != null)) { Iterator itr = collection.iterator(); while(itr.hasNext()) { T obj = itr.next(); if (!predicate.test(obj)) { itr.remove(); } } } } filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Java でソートされたコレクションをサポートするには、いくつかの方法があります。これらはすべて、自然な順序で、または指定されたコンパレータによってコレクションを提供します。自然な順序の場合は、要素に Comparableインターフェイスを実装する必要もあります。
  1. Collections.sort()はリストを並べ替えることができます。Java ドキュメントに記載されているように、このソートは安定しており、n log(n) のパフォーマンスが保証されています。
  2. PriorityQueue は秩序あるキューを提供します。PriorityQueue と Collections.sort() の違いは、PriorityQueue はキューの順序を常に維持しますが、取得できるのはキューの最初の要素のみであることです。PriorityQueue.get(4) のような要素にランダムにアクセスすることはできません。
  3. コレクションに重複がない場合は、TreeSetを選択できます。また、PriorityQueue と同様に、TreeSet は順序付けられたセットを常に維持します。TreeSet から最小または最大の要素を取得することはできますが、要素にランダムにアクセスすることはできません。
簡単に言えば、Collections.sort() は 1 回限りの順序付きリストを提供します。PriorityQueue と TreeSet は、要素へのインデックス付きアクセスができないという代償を払って、順序付けられたコレクションを常に維持します。 9. Collections.emptyList() または新しいインスタンス 同じ質問が emptyMap() と emptySet() にも当てはまります。どちらのメソッドも空のリストを返しますが、Collections.emptyList() は不変のリストです。これは、「空の」リストに新しい要素を追加 できないことを意味します。バックグラウンドで Collections.emptyList() メソッドを呼び出すたびに、実際には空のリストの新しいインスタンスが作成されません。代わりに、既存の空のインスタンスを再利用します。 デザインパターンとしてシングルトンに精通している場合は、その意味が理解できるはずです。これにより、頻繁に呼び出すとパフォーマンスが 向上します。 10 コレクションのコピー Collections.copy() ソース リストを宛先リストにコピーするには 2 つの方法があります。1 つの方法は、ArrayList コンストラクターを使用することです。 もう 1 つの方法は、 Collections.copy()メソッド を使用することです。最初の行に注目してください。コレクションに関する Java ドキュメントには次のように書かれているため、元のリストの長さと少なくとも同じ長さのリストを割り当てています。 ArrayList dstList = new ArrayList (srcList);
宛先リストは、少なくとも送信元リストと同じ長さでなければなりません。
つまり、最終的なリストは元のリストよりも短くてはなりません。 どちらの方法も浅いコピーです。では、これら 2 つの方法の違いは何でしょうか? まず、Collections.copy() は、dstList に srcList のすべての要素を含めるのに十分な領域がない場合でも、dstList コレクションの容量を再割り当てしません。 代わりに、 IndexOutOfBoundsExceptionをスローします。これに何かメリットがあるのか​​と疑問に思う人もいるかもしれません。その理由は、これによりメソッドが時間内に直線的に実行されることが保証されるためです。これは、ArrayList コンストラクターでメモリを再割り当てするのではなく、配列を再利用したい場合にも適しています。 結論ではなく、 記事を読んだ後でも質問がある場合は、お気軽にコメントで質問してください。また、翻訳の不正確さやその他の間違いを見つけた場合は、PM に手紙を書いてください。修正され、感謝されます。 オリジナル。 ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION