感謝您檢查我的問題!使用Java 8 Predicate查找「最」正確的值
我在使用包含多個謂詞並按特定順序應用的Streams時遇到了一些麻煩。
例如起見,請考慮以下IntPredicates:
IntPredicate divisibleByThree = i -> i % 3 == 0;
IntPredicate divisibleByFour = i -> i % 4 == 0;
IntPredicate divisibleByFive = i -> i % 5 == 0;
IntPredicate divisibleByThreeAndFour = divisibleByThree.and(divisibleByFour);
IntPredicate divisibleByThreeAndFive = divisibleByThree.and(divisibleByFive);
IntPredicate divisibleByThreeAndFiveAndFour = divisibleByThreeAndFour.and(divisibleByFive);
//....arbitrary Number of predicates.
第1部分
我已經轉換我已經下降到一個「FizzBuzz」 -esque版本的問題,試圖找到通過將特定順序的謂詞應用到流中來得到正確的答案。像這樣:
IntStream.range(1, 100).forEach(i -> {
//Order matters here!
if(divisibleByThreeAndFiveAndFour.test(i)){
System.out.println("Three and four and five");
} else if(divisibleByThreeAndFour.test(i)){
System.out.println("Three and four");
} else if(divisibleByThreeAndFive.test(i)){
System.out.println("Three and four");
} else if(divisibleByFive.test(i)){
System.out.println("Five");
}
//etc, etc.
});
我不認爲這是非常漂亮的代碼,有沒有更好的方式來實現這一目標?
第2部分
怎麼樣,如果我真的需要應用謂詞,看看是否合適的值出現在流,並計算相關的值返回(在這種情況下,一個字符串進行打印) 。那甚至看起來如何?
擬議天真的解決方案:
String bestValueFound = "None found";
if(IntStream.range(1, 100).filter(divisibleByThreeAndFiveAndFour).findFirst().isPresent()){
bestValueFound = "Three and four and five";
} else if(IntStream.range(1, 100).filter(divisibleByThreeAndFour).findFirst().isPresent()){
bestValueFound = "Three and four";
}else if(IntStream.range(1, 100).filter(divisibleByThreeAndFive).findFirst().isPresent()){
bestValueFound = "Three and five";
} else if(IntStream.range(1, 100).filter(divisibleByThreeAndFive).findFirst().isPresent()){
bestValueFound = "Five";
}
System.out.println(bestValueFound);
這似乎更糟,既美觀又因爲添加的迭代。
第3部分
難道這可能會被使用JavaSlang比賽更漂亮,更有效的方式解決了嗎?
//Note: Predicates needed to be changed from IntPredicate to Predicate<Integer> for correct compilation.
Function<Integer, String> findString = i -> API.Match(i).of(
Case(divisibleByThreeAndFiveAndFour, "Three and four and five"),
Case(divisibleByThreeAndFour, "Three and four"),
Case(divisibleByThreeAndFive, "Three and five"),
Case(divisibleByFive, "Fice"),
Case($(), "None found"));
String bestValueFound = IntStream.range(1, 100).boxed().map(findString).findFirst().orElseThrow(() -> new RuntimeException("Something went wrong?"));
System.out.println(bestValueFound);
這裏的明顯的問題是「.findFirst()」,這將是整數1上這種情況下,使得整個表達式評估爲‘無發現’,然後終止。
我想要的是基本上抓住匹配我匹配中第一個謂詞的任何東西,並使用該值(如果存在),並且只給第二個Case匹配任何匹配,如果找不到第一個匹配,如果流中沒有值匹配任何謂詞,則只給予默認值(「未找到」)。
必須有更好的方法來做到這一點,對吧?或者我只是在浪費時間試圖做一些更好的事情,而不是更傳統,更強制的風格?
謝謝你閱讀我的問題!
請只問1個問題。你有3個完全不同的問題。 – 4castle
在第2部分中,您應該使用['anyMatch'](https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#anyMatch-java.util.function。 IntPredicate-)。 – 4castle