您可以对 上的流进行筛选,然后在返回 时运行收集器。然后,您可以测试您的集合是否同时包含这两个键。"Civic" or "Focus"
getModel()
Set<String>
Set<String> models = reportElements.stream()
.map(Car::getModel)
.filter(model -> model.equals("Focus") || model.equals("Civic"))
.collect(Collectors.toSet());
return models.contains("Focus") && models.contains("Civic");
但是,这将处理整个流;当两者都被发现时,它不会“快速成功”。
以下是一种“快速成功”的短路方法。(更新以包括评论和评论中的澄清,如下所示)
return reportElements.stream()
.map(Car::getModel)
.filter(model -> model.equals("Focus") || model.equals("Civic"))
.distinct()
.limit(2)
.count() == 2;
一次分解一个流操作,我们有:
.map(Car::getModel)
此操作将汽车流转换为汽车模型流。我们这样做是为了提高效率。我们不是在管道其余部分的不同位置多次调用(在 中两次以针对每个所需模型进行测试,然后再次为操作调用),而是应用此映射操作一次。请注意,这不会创建注释中提到的“临时地图”;它只是将汽车转换为下一阶段管道的汽车模型。car.getModel()
filter(...)
distinct()
.filter(model -> model.equals("Focus") || model.equals("Civic"))
这会过滤汽车模型流,仅允许“Focus”和“Civic”汽车模型通过。
.distinct()
此管道操作是有状态的中间操作。它会记住它在临时 .(这可能是评论中提到的“临时地图”。只有当模型在临时集中不存在时,才会(a)将其添加到集合中,并且(b)传递到管道的下一阶段。Set
在管道中的这一点上,流中最多只能有两个元素:“Focus”或“Civic”,或者两者都不是,或者两者兼而有之。我们知道这一点,因为我们知道只会通过这两个模型,我们知道这将删除任何重复项。filter(...)
distinct()
但是,此流管道本身并不知道这一点。它将继续将汽车对象传递到舞台上,以转换为模型字符串,将这些模型传递到舞台,并将任何匹配的物品发送到舞台。它无法分辨这是徒劳的,因为它不明白没有其他任何东西可以通过算法;它简单地执行指令。map
filter
distinct
但我们确实理解。最多两个不同的模型可以通过舞台。因此,我们遵循以下条件:distinct()
.limit(2)
这是一种短路状态的中间操作。它维护通过的项目数的计数,并在指示的数量之后终止流,导致所有后续项目被丢弃,甚至没有启动管道。
在管道中的这一点上,流中最多只能有两个元素:“Focus”或“Civic”,或者两者都不是,或者两者兼而有之。但是,如果两者兼而有之,则流已被截断并处于末尾。
.count() == 2;
计算通过管道的项目数,并根据所需的数量进行测试。
如果我们找到两个模型,流将立即终止,将返回2,并将返回。当然,如果两个模型都不存在,则流将被处理直到苦涩结束,将返回小于2的值,并产生结果。count()
true
count()
false
示例,使用无限的模型流。每三个模型中就有一个是“思域”,每七个模型是一个“焦点”,其余的都是“模型#”:
boolean matched = IntStream.iterate(1, i -> i + 1)
.mapToObj(i -> i % 3 == 0 ? "Civic" : i % 7 == 0 ? "Focus" : "Model "+i)
.peek(System.out::println)
.filter(model -> model.equals("Civic") || model.equals("Focus"))
.peek(model -> System.out.println(" After filter: " + model))
.distinct()
.peek(model -> System.out.println(" After distinct: " + model))
.limit(2)
.peek(model -> System.out.println(" After limit: " + model))
.count() == 2;
System.out.println("Matched = "+matched);
输出:
Model 1
Model 2
Civic
After filter: Civic
After distinct: Civic
After limit: Civic
Model 4
Model 5
Civic
After filter: Civic
Focus
After filter: Focus
After distinct: Focus
After limit: Focus
Matched = true
请注意,有 3 个模型通过了 ,但只有 2 个模型通过了 。更重要的是,请注意,早在无限模型流的结束之前很久就返回了。filter()
distinct()
limit()
true
概括解决方案,因为OP想要一些可以与人,信用卡或IP地址等一起使用的东西,并且搜索条件可能不是两个项目的固定集合:
Set<String> models = Set.of("Focus", "Civic");
return reportElements.stream()
.map( Car::getModel )
.filter( models::contains )
.distinct()
.limit( models.size() )
.count() == models.size();
这里,给定一个任意的集合,可以获得任何特定模型集合的存在,而不限于2。models