2017-04-14 17 views
9

amacı akış filtresi kullanılabilir yeni bir doğrulama'yı oluşturmaktır:Bir Java işlevinde Predicate ve Function nasıl hazırlanır?

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

getSubElement1OfTheElement() döner Function<E,S> (E S özelliği içerir) getPredicate1OnSubElement1() döner

I yöntem başvuruları ortaya çıkarmak için statik fonksiyonlarını kullanabilmek Predicate<S> ve fonksiyonlar. Bunu yaptığım için akım bir Hız şablonu içinde çağrılır ve bu bağlam , lambda sözdizimini ve yöntem referansını desteklemez. Olası tüm kombinasyonlar için statik bir işlev yaratmak istemiyorum, bu yüzden bunların gerçekten composable olmasını istiyorum. Örneğin, ve getPredicate1OnSubElement1() türlerini oluşturabildiğim için statik bir getPredicate1OnElementThatCheckProperty1OnTheSubElement1() kullanmak istemiyorum.

Yani bir oluşturma işlevini gerekir:

// 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 

esinlenerek 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; 

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

: Bu bir döküm bağlam denir

Bu nedenle, her bir arabirim için (örnek benim durumumda test et ve uygula), soyut yöntemin adı her bir arabirim için farklı olduğu için, herhangi bir işlevsel arabirimi (Benim Durumumda ve Önceden) alarak genel bir oluşturma işlevini uygulayamayız.
Bunun için sorun yok.

Sonuç olarak, gerçekten ihtiyacım olan şey, bir Öngörüyü bir İşlev ve tersine dönüştüren iki statik işlevdir. Her Predicate bir Fonksiyon olarak kullanılacaktır ve son işlem, filtre fonksiyonunun parametre tipi ile eşleşmesi için oluşan Fonksiyonu Predicate'e dönüştürecektir.

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; 
} 

Doğru mu?
Öyleyse, işlev imzasındaki sınırları serbest bırakmanın bir yararı var mı?

+0

Eğer başarmak istediğiniz şeyi açıklayabilir:

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

Veya bir oluşturma işlevi yazmak zorunda gerçekten/isterseniz, imza gibi bir şey olmalı? –

+2

JDK'nın yerleşik olarak bulunamamasının nedeni, lambda'yı açıkça yazmak için genellikle daha basit olmasından kaynaklanmaktadır. –

+0

@JacobG. İçeriği tanımlamak için yayınımı düzenledim. – fdelsert

cevap

3

Kendi sorularıma cevap veriyorum.

Kullanım lambda:

public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate) 
İlgili konular