感谢您检查我的问题!使用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