제 동료와 저는 빈 스트림 호출 allMatch()
이 반환 될 것이라는 가정으로 인해 버그가 발생했습니다 false
.
if (myItems.allMatch(i -> i.isValid()) {
//do something
}
물론 문서를 읽지 않고 가정하는 것은 우리의 잘못입니다. 그러나 내가 이해하지 못하는 allMatch()
것은 빈 스트림에 대한 기본 동작이 true
. 그 이유는 무엇입니까? anyMatch()
(반대로 false를 반환하는) 와 마찬가지로이 작업은 모나드를 떠나 if
명령문 에서 사용되는 명령형 방식으로 사용됩니다 . 이러한 사실을 고려할 때 대부분의 경우 빈 스트림에서 allMatch()
기본값을 true
사용하는 것이 바람직한 이유 가 있습니까?
답변
이것은 공허한 진실로 알려져 있습니다 . 빈 컬렉션의 모든 구성원이 조건을 충족합니다. 결국 그렇지 않은 것을 가리킬 수 있습니까?
마찬가지로, 조건과 일치하는 컬렉션 요소를 찾을 수 없기 때문에를 anyMatch
반환 false
합니다. 이것은 많은 사람들에게 혼란 스럽지만 빈 세트에 대해 “any”및 “all”을 정의하는 가장 유용하고 일관된 방법으로 밝혀졌습니다.
답변
이에 대해 생각하는 또 다른 방법이 있습니다.
allMatch()
이다 &&
무엇 sum()
이다+
다음 논리 문장을 고려하십시오.
IntStream.of(1, 2).sum() + 3 == IntStream.of(1, 2, 3).sum()
IntStream.of(1).sum() + 2 == IntStream.of(1, 2).sum()
이것은 sum()
단지 일반화 이기 때문에 의미 가 있습니다 +
. 그러나 요소를 하나 더 제거하면 어떻게됩니까?
IntStream.of().sum() + 1 == IntStream.of(1).sum()
IntStream.of().sum()
특정 방식으로, 또는 빈 숫자 시퀀스의 합 을 정의하는 것이 합리적이라는 것을 알 수 있습니다 . 이것은 우리에게 합산의 “정체성 요소”또는 어떤 것에 추가 될 때 효과가없는 값 ( 0
)을 제공합니다.
같은 논리를 Boolean
대수에 적용 할 수 있습니다 .
Stream.of(true, true).allMatch(it -> it) == Stream.of(true).allMatch(it -> it) && true
보다 일반적으로 :
stream.concat(Stream.of(thing)).allMatch(it -> it) == stream.allMatch(it -> it) && thing
그렇다면 stream = Stream.of()
이 규칙을 적용해야합니다. 이 문제를 해결하기 위해 &&의 “identity element”를 사용할 수 있습니다. true && thing == thing
, 그래서 Stream.of().allMatch(it -> it) == true
.
답변
호출 할 때 list.allMatch
(또는 다른 언어로 된 유사어)의 항목 list
이 술어와 일치하지 않는지 감지하고 싶습니다 . 항목이 없으면 일치하지 않을 수 있습니다. 다음 논리는 항목을 선택하고 조건 자와 일치 할 것으로 예상합니다. 빈 목록의 경우 항목을 선택하지 않고 논리는 여전히 유효합니다.
빈 목록이 allMatch
반환 되면 어떻게 false
됩니까?
내 간단한 논리는 실패합니다.
if (!myList.allMatch(predicate)) {
throw new InvalidDataException("Some of the items failed to match!");
}
for (Item item : myList) { ... }
수표를 !myList.empty() && !myList.allMatch()
.
요컨대, 빈 목록을 allMatch
반환 true
하는 것은 논리적으로 건전 할뿐만 아니라 실행의 행복한 경로에 있으며 확인이 더 적게 필요합니다.
답변
그것의 기초가 수학적 귀납처럼 보입니다. 컴퓨터 과학의 경우이를 적용하는 것이 재귀 알고리즘의 기본 사례가 될 수 있습니다.
스트림이 비어 있으면 정량화가 막연하게 충족되었다고하며 항상 참입니다. Oracle Docs : 스트림 작업 및 파이프 라인
여기서 핵심은 본질적으로 다소 오해의 소지가있는 “진공 적으로 만족”한다는 것입니다. Wikipedia에는 그것에 대해 적절한 토론이 있습니다.
순수 수학에서 막연하게 참된 진술은 일반적으로 그 자체로 흥미롭지는 않지만 수학적 귀납법에 의한 증명의 기본 사례로 자주 발생합니다. Wikipedia : 공허한 진실
답변
이 질문에 이미 정확한 곱셈에 대한 답변이 있었지만 더 수학적 접근 방식을 도입하고 싶습니다.
이를 위해 스트림을 (수학적 의미에서) 세트로 간주하고 싶습니다. 그때
emptyStream.allMatch(x-> p(x))
emtpyStream.anyMatch(x -> p(x))
두 번째 부분이 거짓이라는 것은 빈 집합에 요소가 없기 때문에 매우 분명합니다. 첫 번째는 좀 더 까다 롭습니다. 정의에 따라 사실이라고 받아들이거나 그 이유 중 일부에 대해 다른 답변을 살펴볼 수 있습니다.
이 차이를 설명하는 예로는 “화성에 사는 모든 인간은 다리가 3 개 있습니다”(참) 및 “화성에 다리가 3 개있는 인간이 살고 있습니다”(거짓)와 같은 명제를들 수 있습니다.
답변
