使用lambda表达式可以获得性能提升吗?

ycr*_*ycr 10 java performance lambda

我需要检查两个列表中是否存在共同元素.我提出了两种方法来做到这一点:

方法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;
}
Run Code Online (Sandbox Code Playgroud)

方法02:Lambda

private boolean func02 (List<String> list1, List<String> list2) {
    return list1.stream().filter(list2::contains).findAny().isPresent();
}
Run Code Online (Sandbox Code Playgroud)

在我看来,我发现第一种方法更具可读性.我需要了解的是,比较这两种方法时是否存在差异或优势?

hov*_*yan 4

方法一优化:

你不需要2个循环,当你有一个匹配时你可以立即返回,所以你在那个点停止遍历列表 - (例如阳光情况下你在第一个元素上得到一个匹配 - 你有1次迭代,最坏的情况是你的匹配是最后一个元素 - 你必须遍历整个列表才能匹配该匹配)

private boolean func01 (List<String> list1, List<String> list2) {
        for (String group : list1) {
            if (list2.contains(group)) return true;
        }

        return false;
    }
Run Code Online (Sandbox Code Playgroud)

lambda 等效优化:

  • findAny().isPresent()- 获取与谓词匹配的元素的可选值,并检查该可选值是否存在 - 这相当于anyMatch()因为两个表达式都返回boolean

  • filter()总是会遍历整个列表

  • anyMatch()有短路行为 - 意味着它将在第一场比赛时停止

所以你可以将其重写为:

private boolean func02 (List<String> list1, List<String> list2) {
  return list1.stream().anyMatch(list2::contains);
}
Run Code Online (Sandbox Code Playgroud)

回答您的问题- 这两种方法没有显着的性能差异,请考虑:

  • 为集合创建流有一点开销

  • 流操作可以并行运行 ( list1.stream().parallel().anyMatch(list2::contains))。例如,在这种情况下,anyMatch()在同一流上的并行线程中运行将定期检查先前的线程是否找到匹配项,并将停止遍历集合而不是继续遍历整个集合。因此,理论上,对于非常大的输入列表,您应该使用并行流获得更好的结果。