2015-10-23 7 views
12

私は多くの場合、Streamをフィルターに掛ける必要があるか、または指定されたフィールドに所定の値があるかどうかを調べる述部を使用する必要があります。フィールドが指定された値と等しいかどうかをテストする述語を作成する便利な方法はありますか?

言ってやる例えば、私は、このPOJOがあります

public class A { 
    private Integer field; 

    public A(final Integer field) { 
     this.field = field; 
    } 

    public Integer getField() { 
     return field; 
    } 
} 

をそして、私はfieldの値に基づいてオブジェクトのStreamをフィルタリングする:

final Integer someValue = 42; 
    Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
      .filter(a -> Objects.equals(a.getField(), someValue)) 
      ... 

便利な方法に存在することになりますfilterメソッドの述語を生成しますか?私はPredicate.isEqualがあることに気づいたが、それは必要性に合わない。

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return v -> Objects.equals(value, f.apply(v)); 
} 

をし、としてそれを使用します:

私はかなり簡単にこのようなものを書くことができ

Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
      .filter(isEqual(A::getField, someValue)) 
      ... 

が、私は可能であればJDKから、既存の方法を再利用することを好むだろう。

+5

わかりません。しかし、 'someValue'が' null'でないことを知っているなら、単純な 'a - > someValue.equals(a.getField())'で十分です。なぜなら、 'A'がむしろ' NameOfARealLifeClass'だと思えば、それは 'isEqual(A :: getField、someValue)'より悪くはありません... – Holger

答えて

8

all usages of Predicate within the JFCを見て簡単に確認できる「組み込みファクトリメソッド」はありません。 Predicate内のメソッドのほかに、を返すPattern.asPredicate()しかありません。

このようなファクトリメソッドを実装する前に、実際にその価値があるかどうかを確認する必要があります。 .filter(a -> Objects.equals(a.getField(), someValue))のラムダ式が複雑に見えるのは、nullであるかどうかを少なくとも1つの引数で予測できる場合には、Objects.equalsの使用は不要です。それでもファクトリメソッドを実装し、創造がすでにあるものを使用して、ユーザーが使用できるの料金を勝ちたい場合

final Integer someValue = 42; 
Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
    .filter(a -> someValue.equals(a.getField())) 
    … 

:ここにいるので、someValueは、あなたが式を簡素化することができ、nullことはありません

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return f.andThen(Predicate.isEqual(value)::test)::apply; 
} 
これは詐欺かどうかのテストを行う要因

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return value==null? t -> f.apply(t)==null: t -> value.equals(f.apply(t)); 
} 

しかし、生産コードのために、私はむしろ、このような実装をお勧めします各テストで実行される操作を簡略化するためにはnullです。したがって、それでもまだObjects.equalsは必要ありません。 Predicate.isEqualも同様です。

+0

'value == null? ..'解決策は 'Objects.equals'よりも好ましいですか? – Roland

+0

@Roland:すべての関数評価で 'Objects.equals'を呼び出すと、変更されなくてもすべての関数評価で' value'が 'null'かどうかを再確認します。明らかに、結果は関数 't - > f.apply(t)== null'が' Objects.equals'よりもはるかに安いので、 'value'が' null'ならば最大効果が得られます。このようなユーティリティメソッドをさまざまな場所で使用すると、効果が蓄積されます。言われているように、['Predicate.isEqual'も同様です。](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/function/Predicate.java #114) – Holger

+0

説明をありがとう!ああああ...それは私が最初に価値を抽出した理由さえあった...週末の時間だ。 – Roland

関連する問題