私は配列する必要があります:arrA
とarrB
。 arrA
とarrB
は異なるタイプのオブジェクトのリストであり、add
関数はオブジェクトA
をオブジェクトB
に変換します。各オブジェクトをarrAからarrBに追加し、そのオブジェクトをarrAから削除します。ストリームでこれをしようとしています:
_arrA.stream().foreach(c -> {arrB.add(c); arrA.remove(c);});
_
これを実行すると、次の2つのことが起こります。
remove()
呼び出しのたびに配列の長さが減り、反復のカウンターが増えるためだと思います(奇数インデックスの下のオブジェクトのみがarrB
に渡されます)
今、私は1回のストリーム呼び出しで配列をコピーしてから2番目のストリーム呼び出しでオブジェクトを削除することでこれを解決できましたが、これは私にとっては正しくないようです。
この問題の適切な解決策は何ですか?
編集。追加情報:実際の実装では、以前にフィルタリングされた場合、このリスト
_arrA.stream().filter(some condition).foreach(c -> {arrB.add(c); arrA.remove(c);});
_
異なる条件に一致する要素を異なるリストに追加するために数回呼び出されます(_arrC, arrD
_など)が、各オブジェクトは1つのリストにしか存在できません
ストリームは、より機能的な方法で使用するように設計されており、できればコレクションを不変として扱います。
ストリーム以外の方法は次のとおりです。
arrB.addAll(arrA);
arrA.clear();
ただし、Streamsを使用している可能性があるため、入力をフィルタリングして、次のようにすることができます。
arrB.addAll(arrA.stream().filter(x -> whatever).toList())
次に、arrAから削除します(コメントについて@Holgarに感謝します)。
arrA.removeIf(x -> whatever)
述部が高価な場合は、次のように分割できます。
Map<Boolean, XXX> lists = arrA.stream()
.collect(Collectors.partitioningBy(x -> whatever));
arrA = lists.get(false);
arrB = lists.get(true);
または変更のリストを作成します。
List<XXX> toMove = arrA.stream().filter(x->whatever).toList();
arrA.removeAll(toMove);
arrB.addAll(toMove);
他の人が述べたように、これはforeach
では不可能です-for (A a: arrA)
ループでは要素を削除できないためです。
私の意見では、最もきれいな解決策は、イテレータでwhile
にプレーンを使用することです-イテレータを使用すると、反復処理中に要素を削除できます(コレクションがサポートしている限り)。
Iterator<A> it = arrA.iterator()
while (it.hasNext()) {
A a = it.next();
if (!check(a))
continue;
arrB.add(a);
it.remove();
}
これにより、arrA
をコピー/クローニングする必要もなくなります。
繰り返し処理中にarrAから削除できるとは思わない。
これを回避するには、新しいArrayList <>()でラップします。
new ArrayList <>(arrA).stream()。foreach(c-> {arrB.add(c); arrA.remove(c);});
各remove()呼び出しの後に配列の長さが減少し、反復のカウンターが増加するためだと思います
正しい。 for-each-loopは通常のfor-loopに似ていますが、読み書きが簡単です。あなたはそれを構文糖と考えることができます。内部的には、イテレータまたは配列インデックスを使用します。ストリームのforEach
メソッドは、より洗練されたバージョンであり、並列実行と機能的なコーディングスタイルを可能にします ただし、独自の欠点があります 。
インデックス付きループと同様に、ループ中に要素を削除するとループが中断します。インデックス0、1、および2の3つの要素を持つことを検討してください。最初の反復で要素0を削除すると、リスト項目は1つ上に移動し、次の反復では要素0(以前1)および1(以前2)になります。ループ変数は1を指すようになったため、実際に次の項目をスキップします。インデックス2に到達すると、作業中のループには1つのアイテムしか残っていません(2つ削除しました)。インデックスが範囲外であるため、エラーがスローされます。
可能な解決策:
List
メソッドを使用します。