我需要检查两个列表中是否存在共同元素。我想出了两种方法:
方法01:循环
private boolean func01 (List<String> list1, List<String> list2) {
for (String group : list1) {
for (String funcGroup : list2) {
if (group.equals(funcGroup)) {
return true;
}
}
}
return false;
}
方法02:Lambda
private boolean func02 (List<String> list1, List<String> list2) {
return list1.stream().filter(list2::contains).findAny().isPresent();
}
在我看来,我发现第一种方法更具可读性。我需要了解的是,比较这两种方法时是否存在任何差异或优势?
答案 0 :(得分:4)
要回答您的直接问题,如果您想知道通过使用lambda表达式是否有性能提升,您应该创建一个微基准测试和测量。
但是,我想指出你的第二个解决方案不仅使用lambda表达式(实际上是方法引用),而且也使用Stream
。通常,由于运行流管道所需的所有基础结构,基于流的解决方案需要更长的时间。然而,在大多数情况下,这些解决方案的扩展也会更好。
现在,关于您的具体问题,检查两个列表中是否存在公共元素的最佳方法是使用自Java 1.5以来可用的Collections.disjoint
方法:
return !Collections.disjoint(list1, list2);
答案 1 :(得分:3)
方法1优化:
你不需要2个循环,你可以在匹配时立即返回,所以你在那个时候停止遍历列表 - (例如阳光情况你得到第一个元素的匹配 - 你有1次迭代,最糟糕的情况是你的匹配是最后一个元素 - 你必须遍历整个列表以达到匹配)
private boolean func01 (List<String> list1, List<String> list2) {
for (String group : list1) {
if (list2.contains(group)) return true;
}
return false;
}
lambda等效优化:
findAny().isPresent()
- 获取与谓词匹配的元素的可选项,并检查Optional是否存在 - 这相当于anyMatch()
,因为两个表达式都返回boolean
filter()
将始终遍历整个列表
anyMatch()
有短路行为 - 意味着它将在第一场比赛中停止所以你可以把它重写为:
private boolean func02 (List<String> list1, List<String> list2) {
return list1.stream().anyMatch(list2::contains);
}
回答您的问题 - 这两种方法没有明显的性能差异,但会考虑到:
为集合创建流有轻微的开销
流操作可以并行运行(list1.stream().parallel().anyMatch(list2::contains)
)。例如,在这种情况下,在同一个流上并行线程运行的anyMatch()
将定期检查先前的线程是否找到匹配,并将停止遍历集合,而不是继续遍历整个集合。因此理论上对于大量输入列表,您应该通过并行流获得更好的结果。
答案 2 :(得分:2)
例如,您可以找到与非常相关的比较here。
一旦代码足够热(第一个会胜利),性能将无关紧要
考虑哪个更易于阅读 - 您的意见是第一个,我的是第二个。一旦你在java-8中使用了流,就没有回头路了。
此外,有多种情况下使用stream-api做事远更具可读性,能够并行化。此外,流具有内部不同的优化,使它们非常好。这些优化必须由您主要完成