2017-08-09 21 views
3

私は、リストからいくつかのエントリを除外するためにJavaの関数ライブラリを利用しようとしています。Javaで複数のプロパティでリストをフィルタリングする方法は?

私はBookオブジェクトのリストを持っています。Bookオブジェクトは最初にBook IDで、次にリビジョン番号で並べられます。以下の例では、リストに9つのブックオブジェクトがあります。

Book: ID 1, Revision Number 1 
Book: ID 1, Revision Number 2 
Book: ID 1, Revision Number 3 
Book: ID 2, Revision Number 1 
Book: ID 2, Revision Number 2 
Book: ID 2, Revision Number 3 
Book: ID 3, Revision Number 1 
Book: ID 3, Revision Number 2 
Book: ID 3, Revision Number 3 

各書籍IDのリビジョン番号が一番高くなるようにリストをフィルタしたいと思います。

Book: ID 1, Revision Number 3 
Book: ID 2, Revision Number 3 
Book: ID 3, Revision Number 3 

んJavaは、共通の値(書籍ID)に基づいて、私は複数のフィールドに基づいてフィルタリングできるようにするために、フィルタやコンパレータのようなものを使用して、いくつかの機能的能力を持っていますか?私はしようとすると、コレクションをループし、可能な場合はフィルタリングを行うために自分の関数を記述することを避ける...任意の提案ですか?

+0

多分、いくつかのコンパレータを持つ 'TreeSet' –

+0

あなたはmap wiにそれを集めることができますそれは実現可能ですか? – ByeBye

+0

java 8を使用していて、あらかじめフィルタリングする値を知っている場合は、https://stackoverflow.com/questions/122105/what-is-thebestway-to-filter-a-java-collectionの解決策を参照してください。 [Collection.removeIf()](https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#removeIf-java.util.function.Predicate-)に基づいて最適な場合がありますあなたが望むものに合っている – csunday95

答えて

4

:最後に、あなただけのList<Book>がちょうどMap<Integer,Optinal<Book>>

.values().stream().map(Optional::get).collect(Collectors.toList())); 

完全な例の値にストリームを使用する必要がある場合は

List<Book> books = Arrays.asList(
     new Book(1, 2), 
     new Book(1, 3), 
     new Book(2, 2), 
     new Book(2, 3) 
); 

System.out.println(
    books.stream() 
      .collect(
        groupingBy(Book::getID, 
         maxBy(comparingInt(Book::getRevison)) 
        ) 
      ) 

);// {1=Optional[Book{ID=1, revison=3}], 2=Optional[Book{ID=2, revison=3}]} 

更新:

System.out.println(books.stream() 
       .collect(
         groupingBy(Book::getID, 
           maxBy(comparingInt(Book::getRevison)) 
         ) 
       ).values() 
       .stream() 
       .map(Optional::get) 
       .collect(Collectors.toList()) 
); 
+0

このアプローチでは可能ではないように思われる新しい並べ替えリストを返す必要がありますが、指定する必要がありますか? – deanmau5

+0

@ deanmau5の場合は、私のアップデートをご覧ください。 –

0

それは、複数のプロパティに基づいて、真のフィルタリングではなく、あなたの問題に実行可能になります

final Map<String, Book> books = list.stream().collect(
    Collectors.toMap(
     b -> b.getId(), 
     b -> b, 
     (b1, b2) -> { 
      if(b1.getNumber() > b2.getNumber()) { 
       return b1; 
      } 
      return b2; 
     }) 
); 

それはユニークなIDを持つ(最高数をキーとしてIDを含むマップ、およびブックを返します。 )。

コレクタにmerge functionを追加すると、同じキーでの衝突が発生した場合の対処方法が決まります。この場合、番号の大きい本が返されます。

その呼び出しによるコレクションを希望する場合はvalues()です。

このようなものについては何
+0

'groupingBy()'のようなことができますこれに適しています。上記の私のコメントを参照してください。 – shmosel

+0

同意しますが、依然としてCollectors.maxBy()にコンパレータを作成する必要があります。 – ByeBye

+0

あなたが正しいです、私は私のコメントを修正しました。 – shmosel

関連する問題