2016-03-29 7 views
7

特定のインデックスでList内の項目をフィルタリングする簡潔な方法を探しています。私の例入力は次のようになります。私は、インデックス2468でアイテムをフィルタしたい特定のインデックスのJavaストリームフィルタ項目

List<Double> originalList = Arrays.asList(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); 
List<Integer> filterIndexes = Arrays.asList(2, 4, 6, 8); 

。私は索引と一致する項目をスキップするforループを持っていますが、ストリームを使用して簡単な方法があることを望んでいました。最終的な結果は、次のようになります。

List<Double> filteredList = Arrays.asList(0.0, 1.0, 3.0, 5.0, 7.0, 9.0, 10.0); 
+7

これは 'for'ループと' remove(int) 'を使って非常に簡単です。すべてのストリームを使用しないでください。 –

+0

ありがとう@PaulBoddington。 NETの作業から来て、私はほとんどの配列/リスト操作のLINQを使用することに慣れているので、LINQを使ってこれを行うのが簡単です。同様のものがJava 8ストリームにあることを期待していました。 – Vedanth

+6

ストリームと_まあまあ。 –

答えて

14

あなたはその後、filteredIndexesリストにあるものを削除してからの対応する要素にそれらのインデックスをマッピングし、元のリストのインデックスを模倣するIntStreamを生成することができますリスト(より良い方法は、インデックスのためにを持つことです。それらは定義によって一意であるため、containsは一定の時間演算です)。あなたのfilteredIndexesリストが事前にソートされている場合は、あなたがこのようにすべての要素をチェックする避けることができ

List<Double> filteredList = 
    IntStream.range(0, originalList.size()) 
      .filter(i -> !filterIndexes.contains(i)) 
      .mapToObj(originalList::get) 
      .collect(Collectors.toList()); 
4

ここ
List<Double> filteredList = IntStream.rangeClosed(0, filterIndexes.size()) 
    .mapToObj(idxPos -> idxPos == 0 
      ? originalList.subList(0, filterIndexes.get(idxPos)) 
      : idxPos == filterIndexes.size() 
      ? originalList.subList(filterIndexes.get(idxPos-1)+1, originalList.size()) 
      : originalList.subList(filterIndexes.get(idxPos-1)+1, filterIndexes.get(idxPos))) 
    .flatMap(List::stream) 
    .collect(Collectors.toList()); 

我々だけで、その後、フィルタのインデックス間のすべての要素が含まれているサブリストの数を作成します単一の最終リストにそれらを平らにする。大きな入力(例えば、数百万の数)の場合、この解決策は、@AlexisCによって提案されたものよりも速い大きさであり得る。

2

インデックスを並べ替える場合降順の場合、java.util.List.remove(int)を使用してアイテムを削除できます。

List<Double> originalList = new ArrayList<>(Arrays.asList(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); 
List<Integer> filterIndexes = Arrays.asList(2, 4, 6, 8); 

filterIndexes.stream() 

    // remove higher indixes first, because each remove affects all indexes to the right 
    .sorted(Comparator.reverseOrder()) 

    // make sure to use remove(int) not remove(Object) in java.util.List to use indexes 
    .mapToInt(Integer::intValue) 

    // remove each index 
    .forEach(originalList::remove); 

// print results 
originalList.forEach(System.out::println); 
+0

'.mapToInt(Integer :: valueOf)'を使わないでください。これはうまくいきますが、 'Integer'オブジェクトを' int'値に変換して 'Integer valueOf(int)'に渡して 'Integer'オブジェクトを再び取得し、' int'に自動的にアンボックスします'mapToInt'を使っています。あなたは、確かに '.mapToInt(i-> i)'または '.mapToInt(Integer :: intValue)'のどちらかが必要で、代わりに単一のアンボックスを実行します。 – Holger

+0

@Holgerありがとう! 'Integer :: intValue'私が探していたもの。私も 'Function.identity()'を試みたが、うまくいかなかった。 – slartidan

+0

はい、 'Function.identity()'は 'ToIntFunction'ではなく' Function'を返すので、 'x - > xを使うときと同じように機能的な署名のマッチングではなく、 '直接... – Holger

関連する問題