방금 Java 8 람다로 연주하기 시작했으며 기능적 언어로 익숙한 것들 중 일부를 구현하려고합니다.
예를 들어, 대부분의 기능적 언어에는 시퀀스에서 작동하는 일종의 찾기 함수 또는 술어가 첫 번째 요소를 리턴하는 목록이 true
있습니다. Java 8에서 이것을 달성하는 유일한 방법은 다음과 같습니다.
lst.stream()
.filter(x -> x > 5)
.findFirst()
그러나 필터가 적어도 내 이해 (잘못 될 수 있음)까지 전체 목록을 스캔하므로 비효율적 인 것 같습니다. 더 좋은 방법이 있습니까?
답변
아니요, 필터는 전체 스트림을 스캔하지 않습니다. 지연 연산을 반환하는 중간 연산입니다 (실제로 모든 중간 연산이 지연 스트림을 반환 함). 설득하기 위해 다음 테스트를 수행하면됩니다.
List<Integer> list = Arrays.asList(1, 10, 3, 7, 5);
int a = list.stream()
.peek(num -> System.out.println("will filter " + num))
.filter(x -> x > 5)
.findFirst()
.get();
System.out.println(a);
어떤 출력 :
will filter 1
will filter 10
10
스트림의 첫 두 요소 만 실제로 처리된다는 것을 알 수 있습니다.
그래서 당신은 당신의 접근 방식으로 완벽하게 갈 수 있습니다.
답변
그러나 필터가 전체 목록을 스캔하므로 비효율적 인 것 같습니다.
아닙니다. 술어를 만족시키는 첫 번째 요소가 발견되는 즉시 “중단”합니다. 스트림 패키지 javadoc 에서 게으름에 대해 더 자세히 읽을 수 있습니다 . 특히 (강조 광산) :
필터링, 매핑 또는 중복 제거와 같은 많은 스트림 작업을 느리게 구현하여 최적화 기회를 제공 할 수 있습니다. 예를 들어, “세 개의 연속 모음으로 첫 번째 문자열 찾기”는 모든 입력 문자열을 검사 할 필요는 없습니다. 스트림 작업은 중간 (스트림 생성) 작업과 터미널 (값 또는 부작용 발생) 작업으로 구분됩니다. 중간 작업은 항상 게으르다.
답변
return dataSource.getParkingLots()
.stream()
.filter(parkingLot -> Objects.equals(parkingLot.getId(), id))
.findFirst()
.orElse(null);
객체 목록에서 하나의 객체 만 필터링해야했습니다. 그래서 나는 이것을 사용했는데 도움이되기를 바랍니다.
답변
Alexis C 의 답변 외에도 검색하려는 요소가 있는지 확실하지 않은 배열 목록으로 작업하는 경우이를 사용하십시오.
Integer a = list.stream()
.peek(num -> System.out.println("will filter " + num))
.filter(x -> x > 5)
.findFirst()
.orElse(null);
그럼 당신은 단순히 여부를 확인할 수 있습니다 A가 있습니다 null
.
답변
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
// Stream is ~30 times slower for same operation...
public class StreamPerfTest {
int iterations = 100;
List<Integer> list = Arrays.asList(1, 10, 3, 7, 5);
// 55 ms
@Test
public void stream() {
for (int i = 0; i < iterations; i++) {
Optional<Integer> result = list.stream()
.filter(x -> x > 5)
.findFirst();
System.out.println(result.orElse(null));
}
}
// 2 ms
@Test
public void loop() {
for (int i = 0; i < iterations; i++) {
Integer result = null;
for (Integer walk : list) {
if (walk > 5) {
result = walk;
break;
}
}
System.out.println(result);
}
}
}
답변
개선 된 One-Liner 답변 : 부울 반환 값을 찾고 있다면 isPresent를 추가하여 더 잘 수행 할 수 있습니다.
return dataSource.getParkingLots().stream().filter(parkingLot -> Objects.equals(parkingLot.getId(), id)).findFirst().isPresent();
답변
