자바 8 스트림 API - 어떤 상태 중간 동작을 보증 새로운 소스 수집합니까?

니콜라스 :

다음 문은 사실인가요?

sorted()동작 후속 작업이 더 이상지지 컬렉션 작동 없다는 것을 의미는 "중간 동작 상태"이지만, 내부 상태에.

( 소스소스 - 그들은 서로 복사하거나 동일한 소스에서 온 것 같다.)

내가 테스트 한 Stream::sorted위의 소스 코드 조각으로 :

final List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());

list.stream()
    .filter(i -> i > 5)
    .sorted()
    .forEach(list::remove);

System.out.println(list);            // Prints [0, 1, 2, 3, 4, 5]

효과가있다. 나는 대체 Stream::sorted와 함께 Stream::distinct, Stream::limit그리고 Stream::skip:

final List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());

list.stream()
    .filter(i -> i > 5)
    .distinct()
    .forEach(list::remove);          // Throws NullPointerException

내 놀랍게도이 NullPointerException발생합니다.

모든 시험 방법은 다음과 상태 중간 동작 특성을. 그러나,이 독특한 동작은 Stream::sorted문서화되지 않으며 스트림 운영 및 파이프 라인 부분은 있는지 설명 상태 중간 작업은 정말 새로운 소스 수집을 보장합니다.

어디에 혼란에서 오는 이상 행동의 설명은 무엇인가?

홀거 :

API 설명서는, 따라서, 특정 구현의 이러한 행동에 의존해서는 안됩니다 "후속 작업이 더 이상 기가되는 콜렉션에서 작동 없다"그러한 보증을하지 않습니다.

귀하의 예를 실수로 원하는 일을하는 일; 것을 보증도이 아니다 List만든 collect(Collectors.toList())지원하는 remove작업은.

카운터 - 예를 표시하려면

Set<Integer> set = IntStream.range(0, 10).boxed()
    .collect(Collectors.toCollection(TreeSet::new));
set.stream()
    .filter(i -> i > 5)
    .sorted()
    .forEach(set::remove);

발생합니다 ConcurrentModificationException. 그 이유는 소스가 이미 정렬로 구현이 시나리오를 최적화한다는 것입니다. 원칙적으로, 그것으로, 원래 예를 들어 동일한 최적화를 할 수있는 forEach명시 적으로 지정하지 순서로 작업을 수행하고, 따라서 정렬이 필요하지 않습니다.

예를 들어, 상상할 수있는 다른 최적화있다 sorted().findFirst()정렬 새 스토리지로 요소를 복사 할 필요없이 "최소를 찾아"작업로 변환 얻을 수는.

결론은 그래서 할 수없는 동작에 의존 할 때, 어떤 새로운 최적화가 추가 내일을 깰 수있다, 오늘 일이 일어날 수 있습니다.

추천

출처http://43.154.161.224:23101/article/api/json?id=37988&siteId=1