在java中从lambda forEach()返回

sam*_*amm 76 java foreach lambda return-type java-8

我试图将一些for-each循环更改为lambda forEach()-methods以发现lambda表达式的可能性.以下似乎是可能的:

ArrayList<Player> playersOfTeam = new ArrayList<Player>();      
for (Player player : players) {
    if (player.getTeam().equals(teamName)) {
        playersOfTeam.add(player);
    }
}
Run Code Online (Sandbox Code Playgroud)

随着lambda forEach()

players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});
Run Code Online (Sandbox Code Playgroud)

但下一个工作不起作用:

for (Player player : players) {
    if (player.getName().contains(name)) {
        return player;
    }
}
Run Code Online (Sandbox Code Playgroud)

与lambda

players.forEach(player->{if (player.getName().contains(name)) {return player;}});
Run Code Online (Sandbox Code Playgroud)

最后一行的语法有问题还是不可能从forEach()方法返回?

Ian*_*rts 102

return那里,从λ表达式,而不是从包含方法返回.而不是forEach你需要filter流:

players.stream().filter(player -> player.getName().contains(name))
       .findFirst().orElse(null);
Run Code Online (Sandbox Code Playgroud)

这里filter将流限制为与谓词匹配的项,findFirst然后返回Optional带有第一个匹配条目的项.

这看起来效率低于for循环方法,但实际上findFirst()可以短路 - 它不会生成整个过滤流,然后从中提取一个元素,而是只过滤所需的元素,以便找到第一个匹配的.你也可以使用findAny()替代的findFirst(),如果你并不一定在乎获得第一个从(订购)流,但只是任何匹配项匹配的球员.当涉及并行性时,这可以提高效率.

  • 合理,但我建议你不要在`Optional`上使用`orElse(null)`."Optional"的要点是提供一种方法来指示值的存在与否,而不是重载null(导致NPE).如果你使用`optional.orElse(null)`它会回收所有null的问题.只有当你不能修改调用者并且它真的期望为null时我才会使用它. (9认同)

ski*_*iwi 11

我建议你首先尝试在整个图片中理解Java 8,最重要的是在你的情况下它将是stream,lambdas和方法引用.

永远不应该逐行将现有代码转换为Java 8代码,您应该提取功能并转换它们.

我在你的第一个案例中确定的内容如下:

  • 如果输入结构的元素与某个谓词匹配,则需要将其添加到输出列表中.

让我们看看我们是如何做到的,我们可以通过以下方式实现:

List<Player> playersOfTeam = players.stream()
    .filter(player -> player.getTeam().equals(teamName))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

你在这里做的是:

  1. 将您的输入结构转换为流(我假设它是类型Collection<Player>,现在你有一个Stream<Player>.
  2. 使用a过滤掉所有不需要的元素,Predicate<Player>如果希望保留,则将每个玩家映射到布尔值true.
  3. 通过a收集列表中的结果元素Collector,这里我们可以使用标准库收集器之一Collectors.toList().

这还包含另外两点:

  1. 对接口的代码,所以代码对List<E>ArrayList<E>.
  2. 对于类型参数使用菱形推理,new ArrayList<>()毕竟你使用的是Java 8.

现在进入第二点:

您再次希望将旧版Java的一些内容转换为Java 8,而无需考虑更大的图景.这部分已经被@IanRoberts回答,虽然我认为你需要做players.stream().filter(...)...他建议的事情.


Jav*_*Pro 5

这对我有帮助:

List<RepositoryFile> fileList = response.getRepositoryFileList();
RepositoryFile file1 = fileList.stream().filter(f -> f.getName().contains("my-file.txt")).findFirst().orElse(null);
Run Code Online (Sandbox Code Playgroud)

取自Java 8 使用 Lambda 在列表中查找特定元素


Sri*_*ram 5

如果要返回布尔值,则可以使用如下所示的方法(比filter快得多):

players.stream().anyMatch(player -> player.getName().contains(name));
Run Code Online (Sandbox Code Playgroud)