2015-05-20 37 views
2

我想用方法引用來壓縮我的代碼。下面是我試圖改善線:方法引用和鏈式謂詞

assertThat("only true & false strings allowed", 
     records.stream().map(Record::getType) 
     .allMatch(s -> "true".equals(s) || "false".equals(s))); 

有了方法引用它可能是更漂亮:

assertThat("only true & false strings allowed", 
     records.stream().map(Record::getType).allMatch("true"::equals)); 

但我無論如何加上「假」的謂詞?

+1

有一個[討論](http://mail.openjdk.java.net/pipermail/core- libs-dev/2015-May/033137.html)在core-libs-dev上添加「Predicate.of」。如果發生這種情況,我們可以編寫'.allMatch(Predicate.of(「true」:: equals)。或(「false」:: equals))' – Misha

回答

5

String類或JDK中沒有任何方法,我知道這與您的Predicate等效。您可以自定義一個

public static boolean match(String arg) { 
    return "true".equals(arg) || "false".equals(arg); 
} 

,並用它

assertThat("only true & false strings allowed", 
    records.stream().map(Record::getType).allMatch(Example::match); 

或者你可以使用一個Pattern正則表達式作爲Predicate

assertThat("only true & false strings allowed", 
    records.stream().map(Record::getType) 
      .allMatch(Pattern.compile("^(false|true)$").asPredicate())); 

而且,通過Holger in comments的建議,你可以使用

.allMatch(Arrays.asList("true", "false")::contains) 

或從Set創建的類似物。

+3

請注意'Pattern.predicate'使用'find'而不是「匹配」。因此,您需要'^(false | true)$'作爲模式來實現* matches *語義。 – Holger

+3

另一個也適用於非'String'元素的解決方案是'.allMatch(Arrays.asList(「true」,「false」):: contains)'(儘管這隻適用於少數元素) 。 – Holger

0

你可以鏈Predicates一起使用Predicate.and()Predicate.or()但首先你要你的方法引用強制對謂詞

Predicate<String> trueTest = "true"::equals; 

然後,您可以做你的比賽裏面的鏈接

records.stream().map(Record::getType).allMatch(trueTest.or("false"::equals)); 

或在流外創建謂詞

Predicate<String> trueTest = "true"::equals; 
Predicate<String> trueOrFalseTest = trueTest.or("false"::equals); 


records.stream().map(Record::getType).allMatch(trueOrFalseTest); 

無論哪種方式,我都沒有發現任何一個比你的原始代碼更清晰。

0

這不是一個一行,但是你可以使用在Predicate.or()方法:

Predicate<String> isTrue = "true"::equals; 
Predicate<String> isFalse = "false"::equals; 

assertThat("only true & false strings allowed", 
    records.stream().map(Record::getType).allMatch(isTrue.or(isFalse)))