Java 8 - 使用 BiPredicate 进行过滤
Java 8 - Filter with BiPredicate
我有一个整数流,我想找到两个数字之和等于另一个数字。所以我想出了以下解决方案:
BiPredicate<Integer, Integer> p = (price1, price2) -> price1.intValue() + price2.intValue() == moneyQty;
flavoursPrices.filter(p);
但是filter 方法没有接收到BiPredicate。为什么不?有什么替代方案?
Predicate
!= BiPredicate
Stream#filter
需要一个 Predicate
(Object -> boolean)
将一次处理每个元素。
您可能需要检查 StreamEx
库以找到解决方案。
它有方法对流中的连续元素进行配对。
StreamEx
因为 filter
不是那样工作的,它一次只过滤一个集合。对于您的任务,您需要类似 Python 的 itertools.product
;这可以使用 flatMap
来实现。在 Scala 中,这看起来很短:
prices.flatMap(p1 =>
prices.flatMap(p2 =>
if (p1 + p2 == 5) List((p1, p2)) else List()))
如果你想在(本地)Java中进行,会出现这样的结果:
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<Integer> prices = Arrays.asList(1,2,3,4,5,6,7,8,9);
List<List<Integer>> result = prices.stream().flatMap(p1 ->
prices.stream().flatMap(p2 ->
p1 + p2 == 5 ? Stream.of(Arrays.asList(p1, p2)) : Stream.empty()
)
).collect(Collectors.toList());
System.out.println(result);
}
}
... 打印 [[1, 4], [2, 3], [3, 2], [4, 1]]
。但我不会在现实中使用它;)至少,一个元组 class 会很好。
值得注意的是flatMap
最强大的功能之一;几乎所有的流转换(filter、map、cartesian product、flatten)都可以使用它来实现。休息(如 zip)几乎总是 fold/reduce(或者,很少,展开)。
如何使用 StreamEx library 实施您的解决方案:
StreamEx.ofPairs(prices, (p1, p2) -> p1 + p2 == 5 ? StreamEx.of(p1, p2) : StreamEx.empty())
.flatMap(Function.identity())
.forEach(price -> System.out.println(price));
您可能还想创建自己的 class 来封装对。
您仍然可以使用 Bipredicate。 filter-method 需要的参数是一个 Predicate,所以这里有一个如何使用这个 BiPredicate 的例子:
BiPredicate<Integer, Integer> p = (price1, price2) -> price1.intValue() + price2.intValue() == moneyQty;
flavoursPrices.stream().filter(el->p.test(el.price1,el.price2));
在此示例中,flavoursPrices 必须是一个列表。
我们正在使用的 lambda:
el->p.test(el.price1,el.price2)
正在替换匿名内部 class 声明以从 BiPredicate 中创建新的 Predicate:
Predicate<Integer> arg =new Predicate<Integer>() {
@Override
public boolean test(Element el) {
return p.test(el.price1,el.price2);
}
};
所以为了过滤流,我们正在为来自流的每个元素创建一个新的 Predicate,然后我们使用这个 Predicate 作为参数来使用它的测试方法。这样做的最大好处是,我们不必事先创建大量的 Predicates,但我们可以将每个元素传递到 lambda 函数中并获取它的属性。
我有一个整数流,我想找到两个数字之和等于另一个数字。所以我想出了以下解决方案:
BiPredicate<Integer, Integer> p = (price1, price2) -> price1.intValue() + price2.intValue() == moneyQty;
flavoursPrices.filter(p);
但是filter 方法没有接收到BiPredicate。为什么不?有什么替代方案?
Predicate
!= BiPredicate
Stream#filter
需要一个 Predicate
(Object -> boolean)
将一次处理每个元素。
您可能需要检查 StreamEx
库以找到解决方案。
它有方法对流中的连续元素进行配对。
StreamEx
因为 filter
不是那样工作的,它一次只过滤一个集合。对于您的任务,您需要类似 Python 的 itertools.product
;这可以使用 flatMap
来实现。在 Scala 中,这看起来很短:
prices.flatMap(p1 =>
prices.flatMap(p2 =>
if (p1 + p2 == 5) List((p1, p2)) else List()))
如果你想在(本地)Java中进行,会出现这样的结果:
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<Integer> prices = Arrays.asList(1,2,3,4,5,6,7,8,9);
List<List<Integer>> result = prices.stream().flatMap(p1 ->
prices.stream().flatMap(p2 ->
p1 + p2 == 5 ? Stream.of(Arrays.asList(p1, p2)) : Stream.empty()
)
).collect(Collectors.toList());
System.out.println(result);
}
}
... 打印 [[1, 4], [2, 3], [3, 2], [4, 1]]
。但我不会在现实中使用它;)至少,一个元组 class 会很好。
值得注意的是flatMap
最强大的功能之一;几乎所有的流转换(filter、map、cartesian product、flatten)都可以使用它来实现。休息(如 zip)几乎总是 fold/reduce(或者,很少,展开)。
如何使用 StreamEx library 实施您的解决方案:
StreamEx.ofPairs(prices, (p1, p2) -> p1 + p2 == 5 ? StreamEx.of(p1, p2) : StreamEx.empty())
.flatMap(Function.identity())
.forEach(price -> System.out.println(price));
您可能还想创建自己的 class 来封装对。
您仍然可以使用 Bipredicate。 filter-method 需要的参数是一个 Predicate,所以这里有一个如何使用这个 BiPredicate 的例子:
BiPredicate<Integer, Integer> p = (price1, price2) -> price1.intValue() + price2.intValue() == moneyQty;
flavoursPrices.stream().filter(el->p.test(el.price1,el.price2));
在此示例中,flavoursPrices 必须是一个列表。
我们正在使用的 lambda:
el->p.test(el.price1,el.price2)
正在替换匿名内部 class 声明以从 BiPredicate 中创建新的 Predicate:
Predicate<Integer> arg =new Predicate<Integer>() {
@Override
public boolean test(Element el) {
return p.test(el.price1,el.price2);
}
};
所以为了过滤流,我们正在为来自流的每个元素创建一个新的 Predicate,然后我们使用这个 Predicate 作为参数来使用它的测试方法。这样做的最大好处是,我们不必事先创建大量的 Predicates,但我们可以将每个元素传递到 lambda 函数中并获取它的属性。