2015-10-21 3 views
5

私はオブジェクトのベクトルを持っており、それらを1ずつ比較する必要があります。つまり:for-eachループを使用してArrayList内のアイテムのカップルを比較するにはどうすればよいですか?

for (Object o1 : list) { 
    for (Object o2 : list) { 
    //Do something with o1 and o2 
    } 
} 

とにかくこのアプローチを使用して、私は2つのカップルを2回比較します! 「C」スタイルのアプローチを使用して、私はこれをやっているだろう:

​​

nは、リストの長さです。

for-eachループを使用してこれを行う方法はありますか?ため、各ループの

添加

使用は必須ではありません。とにかく、私は公演の問題に懸念しています。 for-eachループは、インデックスに直接アクセスするためのシンプルより高速ですか?

+4

なぜ 'for'ループを使いたくないのですか?彼らはC言語と同じように動作します。 –

+0

はい2つの変数を使用するか、次のインデックスを使用します – SacJn

答えて

6

あなたの意図がCのようなforループで明白に明確です - すべてのペアを一度ループします。その結果、逆のメンバーを持つ同じペア(例: (a、b)および(b、a)は再び処理されない。それが私がお勧めするものです。 Javaでも同様に動作します。

ただし、拡張されたforループを絶対に持っている必要がある場合は、内側のforループをサブリスト上で操作することができます。List's subList methodで始まり、次の要素から始まります。

for (Object o1 : list) { 
    List<Object> subList = list.subList(list.indexOf(o1) + 1, list.size()); 
    for (Object o2 : subList) { 
     //Do something with o1 and o2 
    } 
} 
+1

ありがとう! for-eachループの使用法は必須ではありません。とにかく、私は公演の問題に懸念しています。 for-eachループは、インデックスに直接アクセスするためのシンプルより高速ですか? –

+0

for-eachループはシーンの背後にある 'Iterator'を作成し、それを使ってループに値を与えます。ループのインデックスベースの標準よりも少し遅いかもしれませんが、ほぼすべてのアプリケーションについて、パフォーマンスの違いについては心配しません。 – rgettman

+0

非常に良い解決策! subListは考えていませんが、ここではパフォーマンスが失われています。それでも+1 upvote! – Noli

2

このコメントは、Cスタイルまたは明示的なインデックスを示すことを示唆しています。それらは良い提案です。しかし、あなたはループのための新しいスタイルでそれを行う上で主張すれば、方法がある:

for (Object o1 : list) { 
    final int o1Index = list.indexOf(o1); 
    final int listSize = list.size(); 
    for (Object o2 : list.subList(o1Index + 1, listSize)) { 
    //Do something with o1 and o2 
    } 
} 

アイデアがリストにO1の前に来るすべてのO2はすでに処理されている、とあなたが必要としないということです自分自身に対してo1を処理する。したがって、o1に続く要素のみからなるサブリストを取得し、そのサブリストからo2を描画します。

リストに複数の要素が複数表示されると、これは失敗します。

私はo1IndexlistSizeを分かりやすく説明していますが、実際にはインラインになっている可能性があります。

もう1つの方法は、元のリストをコピーして、内側のループを開始する前に、毎回フロント要素を削除することです。これは重複した要素を適切に説明しますが、より多くのスペースを必要とします。

final List<Object> newList = new ArrayList<>(list); 
for (Object o1 : list) { 
    newList.remove(0); 
    for (Object o2 : newList) { 
     // Do something 
    } 
} 
+0

私は多くのあなたのソリューションに感謝します。パフォーマンス(実行速度、割り当てられたスペースではない)はどうですか? –

+1

2番目のものは、c-style forループよりもはるかに悪いです。これはリストのコピーと、実行時間を追加する要素の削除です。 'sublist'のアイデアはおそらくCスタイルのforループに相当します。これはまったく新しいリストではなく、単にリストのビューを返すからです。ベンチマークもしていませんが、ハードな主張はできません。 –

0

これは非常に特殊な場合であり、比較は、他の操作の無限のちょうど動作である、他の非可換演算(これはほんの一例である)は、全ての組み合わせについての意味を有します。

したがって、このような場合の拡張ループはありません。 listList<Whatever>として宣言されている、あなたは、各ループListIteratorを使用してではなくにより適切にこの動作を達成することができると仮定すると、

+0

私のケースでは、o1とo2をo1と比較して同じ答えが返されます(可換性) –

+1

強化ループは、特定の必要性ごとに操作を追加すると、直交性が損なわれます。 –

3

ListIterator<Whatever> iteratorI = list.listIterator(); 
if (iteratorI.hasNext()) { 
    for (Whatever whateverI = iteratorI.next(); iteratorI.hasNext(); whateverI = iteratorI.next()) { 
     ListIterator<Whatever> iteratorJ = list.listIterator(iteratorI.nextIndex()); 
     for (Whatever whateverJ = iteratorJ.next(); iteratorj.hasNext(); whateverJ = iteratorJ.next()) { 
      //do the comparison here... 
     } 
    } 
} 
+0

私はイテレータを使ってインデックスアプローチを模倣しているので、このアプローチが好きです。とにかく、これはインデックスで直接アクセスするよりも遅いですか? –

+1

Java 8 HotSpotでは、 'ListIterator'を使用すると、インデックスで初期化されたときにLinkedListに最適化されますが、' ArrayList 'などの実装では、indexを通じて配列要素に直接アクセスできます。それでも、私は時代を測定していない、これはソースコードを読むことに基づいています。 –

+1

これはうまくいきません。 'ArrayList'に' list.listIterator(Object) 'メソッドはないので、コンパイルされません。それがあったとしても、外側の 'for'の繰り返しごとに' iteratorI.next() 'を2回呼び出し、リストの要素の半分をスキップします。 –

2

拡張forループは、すべての状況で適切ではありません。インデックスを使用しないでループ内でindexOfを使用すると、コードの効率が悪くなり(indexOfは線形検索)、非慣用です。

私の意見では、最良の答えは明示的なインデックスを使用することです。 LinkedListためgetが一定時間操作ではないのでListは、LinkedListある場合は、getを使用しないでください

for (i=0; i<n-1; i++) { 
    for (j=i+1; j<n; j++) { 
     // do something with list.get(i) and list.get(j) 
    } 
} 

つの状況があります。この場合、私はするでしょう

List<Object> copy = new ArrayList<>(linkedList); 
for (i=0; i<n-1; i++) { 
    for (j=i+1; j<n; j++) { 
     // do something with copy.get(i) and copy.get(j) 
    } 
} 
2

パフォーマンスをしたいですか? ここに行く!

ため、各ループの使用量はあなたが二回の組み合わせを比較することはありません

int s = list.size(); 

for(int i = 0; i < s-1; i++){ 
    for(int n = i+1; n< s;n++){ 
     if(list.get(i).equals(list.get(n))){ 
     System.out.println("Duplicate"); 
     } 
    } 
} 

必須ではありません。 foreachのは、より多くのリソースを必要としませんし、パフォーマンスが低下し

あなたは非常に多くのヒープを作成し、より多くの命令が処理されるも、アプリケーションを遅くしたいforeach文と同じ結果を達成するために:また、完全にあなたが質問に答えるために

あなたはメモリを失うだけでなく、コンピューティングのパフォーマンスも向上させます。 size()メソッドを複数回呼び出すことを避けて、このプロシージャ内でリストが変更されないようにしてください。これはまた、CPUの使用量を減らしますが、RAM(int s)を少し必要とします。

あなたの「C」スタイルのアプローチはほぼ最適です。

私はJava API呼び出しを簡単に使用できるように、ターゲットフレームワークでこの例を使用するのは簡単です。

EDIT:メソッドの呼び出しを減らすためにリストのサイズを保存することで、さらにパフォーマンスが向上します。

関連する問題