[java] Java의 람다 forEach ()에서 반환

forEach()람다 식의 가능성을 발견 하기 위해 일부 for-each 루프를 람다 메서드 로 변경하려고합니다 . 다음이 가능한 것 같습니다.

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

람다와 함께 forEach()

players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});

하지만 다음은 작동하지 않습니다.

for (Player player : players) {
    if (player.getName().contains(name)) {
        return player;
    }
}

람다와 함께

players.forEach(player->{if (player.getName().contains(name)) {return player;}});

마지막 줄의 구문에 문제가 있거나 forEach()메서드 에서 반환 할 수 없습니까?



답변

return람다 식에서보다는 함유 방법에서이 반환된다. 대신 스트림 forEach이 필요 filter합니다.

players.stream().filter(player -> player.getName().contains(name))
       .findFirst().orElse(null);

여기 filter에서는 조건 자와 일치하는 항목으로 스트림을 제한 한 findFirst다음 Optional일치하는 첫 번째 항목과 함께 를 반환합니다 .

이는 for-loop 접근 방식보다 덜 효율적으로 보이지만 실제로 findFirst()단락 될 수 있습니다. 전체 필터링 된 스트림을 생성 한 다음 하나의 요소를 추출하지 않고 필요한만큼의 요소 만 필터링합니다. 첫 번째 일치하는 것을 찾으십시오. (주문 된) 스트림에서 첫 번째 일치하는 플레이어를 가져 오는 데 반드시 신경 쓰지 않고 일치하는 항목 만 있으면 findAny()대신 사용할 수도 있습니다 . 이렇게하면 병렬 처리가있을 때 효율성이 향상됩니다.findFirst()


답변

먼저 전체 그림에서 Java 8을 이해하려고 시도하는 것이 좋습니다. 가장 중요한 경우에는 스트림, 람다 및 메서드 참조가 될 것입니다.

당신이해야 결코 라인별로 자바 8 코드로 기존의 코드를 변환하지, 당신은 기능을 추출하고 사람들을 변환해야합니다.

귀하의 첫 번째 사례에서 제가 확인한 것은 다음과 같습니다.

  • 일부 술어와 일치하는 경우 입력 구조의 요소를 출력 목록에 추가하려고합니다.

어떻게하는지 살펴 보겠습니다. 다음과 같이 할 수 있습니다.

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

여기서하는 일은 :

  1. 입력 구조를 스트림으로 바꾸십시오 (여기서는 유형이 있다고 가정 Collection<Player>하고 이제 Stream<Player>.
  2. 를 사용하여 원하지 않는 모든 요소를 ​​필터링하고 Predicate<Player>유지하려는 경우 모든 플레이어를 부울 true로 매핑합니다.
  3. 를 통해 목록의 결과 요소를 수집합니다 Collector. 여기에서 표준 라이브러리 수집기 중 하나 인 Collectors.toList().

여기에는 다른 두 가지 사항도 포함됩니다.

  1. 인터페이스에 대한 코드이므로 List<E>over ArrayList<E>.
  2. 에서 유형 매개 변수에 다이아몬드 추론을 사용하십시오 new ArrayList<>(). 결국 Java 8을 사용하고 있습니다.

이제 두 번째 요점으로 넘어갑니다.

더 큰 그림을 보지 않고 레거시 Java를 Java 8로 다시 변환하고 싶습니다. 이 부분은 이미 @IanRoberts 에 의해 답변 되었지만 players.stream().filter(...)...그가 제안한 것을 극복 해야한다고 생각합니다 .


답변

부울 값을 반환하려면 다음과 같이 사용할 수 있습니다 (필터보다 훨씬 빠름).

players.stream().anyMatch(player -> player.getName().contains(name));


답변

이것은 나를 도왔습니다.

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

Java 8 에서 가져온 Lambda로 목록에서 특정 요소 찾기


답변

예외를 던질 수도 있습니다.

노트 :

가독성을 위해 스트림의 각 단계를 새 줄에 나열해야합니다.

players.stream()
       .filter(player -> player.getName().contains(name))
       .findFirst()
       .orElseThrow(MyCustomRuntimeException::new);

논리가 느슨하게 “예외 기반”인 경우 (예 : 코드에서 모든 예외를 포착하고 다음에 수행 할 작업을 결정하는 한 위치가있는 경우) 코드베이스를 배수로 흩 뜨리는 것을 피할 수있을 때만 예외 기반 개발을 사용하고 try-catch이러한 예외를 던지는 것은 예상하고 적절하게 처리 할 수있는 매우 특별한 경우입니다.)


답변