2017-04-14 15 views
9

目的は、ストリーム・フィルタに使用可能な新たな述語を作成することである。Java関数の述語と関数を適切に構成する方法は?

myCollectionOfElement 
.stream() 
.filter(
    MyStaticHelperClass.compose(MyStaticHelperClass.getSubElement1OfTheElement(),MyStaticHelperClass.getPredicate1OnSubElement1())) 
.sorted(MyStaticHelperClass.getOtherSubElement().reversed()) 
.limit(10) 
.collect(Collectors.toList()) 

getSubElement1OfTheElement()戻りFunction<E,S>(EはSプロパティを含む) getPredicate1OnSubElement1()戻りPredicate<S>

Iメソッド参照を露出させるために静的関数を使用して機能。 ストリームはVelocityテンプレートと、この文脈に呼び出されたので、私はこれを行うには、ラムダ構文と方法参照をサポートしていません。 すべての可能な組み合わせに対して静的関数を作成したくないので、実際にはそれらを合成可能にしたいのです

たとえば、ここでは、は、getSubElement1OfTheElement()getPredicate1OnSubElement1()を組み立てることができるので、静的なgetPredicate1OnElementThatCheckProperty1OnTheSubElement1()を持っていません。

だから私はコンポーズ機能を必要とする:

Is there a convenience method to create a Predicate that tests if a field equals a given value?

// step by step with variables 
Function <S,Boolean> predicateFunction = predicate::test; 
// a kind of @FunctionalInterface implicit "conversion" ? Predicate -> Function. 
// is that safe ? 

Function <E,Boolean> composed = function.andThen(predicateFunction::apply); 
return composed::apply; 

編集に触発

// returns a new Predicate constructed by applying Predicate predicate on the result of Function function 
public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<S> predicate) 

// most intuitive : lambda 
return value -> predicate.test(function.apply(value)); 

// with method references 
return function.andThen(predicate::test)::apply; 
// predicate.compose is not available because Predicate interface doesn't extends Function interface 

https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

それはキャストコンテキストと呼ばれています

// the implementation of my compose can also be this ugly one-liner : 
return ((Function <S,Boolean>)predicate::test).compose(function)::apply; 

私は抽象メソッドの名前がそれぞれのインターフェース(私の場合はテストと適用)によって異なるので、機能的なインターフェース(私の場合はFunctionとPredicate)を取って汎用のcompose関数を実装することはできません。
私はそれで大丈夫です。私は本当に必要なもの

締結することは、2つの静的関数、関数と逆に述語を変換一つです。すべての述語は関数として使用され、最後の操作はフィルタ関数のパラメータ型と一致するように、合成された関数を述語に変換します。

public static <S> Function<S,Boolean> predicateToFunction(Predicate<S> predicate){ 
    return predicate::test; 
} 
public static <S> Predicate<S> functionToPredicate(Function<S,Boolean> function){ 
    return function::apply; 
} 

は正しいですか?
もしそうなら、関数シグネチャの範囲を解放することに興味はありますか?

+0

? –

+2

JDKにこれが組み込まれていない理由は、ラムダを明示的に書くだけで簡単にできるからです。 –

+0

@JacobG。文章を編集するために投稿を編集しました。 – fdelsert

答えて

3

私自身の質問に答えます。

使用ラムダ:

value -> predicate.test(function.apply(value)); 

それともあなたは本当に/は、コン機能を記述する必要がしたい場合は、署名のようなものでなければなりません:あなたはあなたが達成しようとしているかを説明することはでき

public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate) 
関連する問題