Mein Kollege und ich hatten einen Fehler, der auf unserer Annahme beruhte, dass ein leerer Stream-Aufruf zurückkehren allMatch()
würde false
.
if (myItems.allMatch(i -> i.isValid()) {
//do something
}
Natürlich ist es unsere Schuld, Dokumentation anzunehmen und nicht zu lesen. Was ich jedoch nicht verstehe, ist, warum das Standardverhalten allMatch()
für einen leeren Stream zurückgegeben wird true
. Was war der Grund dafür? Wie die anyMatch()
(die im Gegensatz dazu false zurückgibt) wird diese Operation auf eine zwingende Weise verwendet, die von der Monade abweicht und wahrscheinlich in einer if
Anweisung verwendet wird. Gibt es angesichts dieser Tatsachen einen Grund, warum es für die meisten Verwendungszwecke wünschenswert ist , allMatch()
standardmäßig true
einen leeren Stream zu verwenden?
allMatch
wahr ist, dies auch der Fall sein sollteanyMatch
. Zusätzlich für den leeren Fall,allMatch(...) == noneMatch(...)
der auch komisch ist.i -> i.isValid()
Foo::isValid
Foo
Antworten:
Dies ist als leere Wahrheit bekannt . Alle Mitglieder einer leeren Sammlung erfüllen Ihre Bedingung; Können Sie auf einen zeigen, der dies nicht tut?
In ähnlicher Weise wird
anyMatch
zurückgegebenfalse
, da Sie kein Element Ihrer Sammlung finden können, das der Bedingung entspricht. Dies ist für viele Menschen verwirrend, stellt sich jedoch als die nützlichste und konsistenteste Methode heraus, um "any" und "all" für leere Mengen zu definieren.quelle
1
während die Summe eines leeren Satzes von Zahlen ist0
. Sie sind die neutralen Elemente für die Multiplikation / Addition. Im Fall von Booleschen Werten haben Sie dasTrue and x = x
undFalse or x = x
wenn Sie also verallgemeinernand
undor
Sequenzen (das ist wasall
undany
sind) verallgemeinern , erhalten SieTrue
undFalse
für den leeren Fall, dh sie sind jeweils neutrale Elemente.anyMatch
Tests für das Fehlen von Positiven,allMatch
Tests für das Fehlen von Negativen.Hier ist eine andere Möglichkeit, darüber nachzudenken:
allMatch()
ist zu&&
wassum()
ist zu+
Betrachten Sie die folgenden logischen Aussagen:
IntStream.of(1, 2).sum() + 3 == IntStream.of(1, 2, 3).sum() IntStream.of(1).sum() + 2 == IntStream.of(1, 2).sum()
Dies ist sinnvoll, da
sum()
es sich nur um eine Verallgemeinerung von handelt+
. Was passiert jedoch, wenn Sie ein weiteres Element entfernen?IntStream.of().sum() + 1 == IntStream.of(1).sum()
Wir können sehen, dass es sinnvoll ist
IntStream.of().sum()
, die Summe einer leeren Folge von Zahlen auf eine bestimmte Weise zu definieren. Dies gibt uns das "Identitätselement" der Summierung oder den Wert, der, wenn er zu etwas hinzugefügt wird, keine Wirkung hat (0
).Wir können dieselbe Logik auf die
Boolean
Algebra anwenden .Stream.of(true, true).allMatch(it -> it) == Stream.of(true).allMatch(it -> it) && true
Allgemeiner:
Wenn
stream = Stream.of()
dann muss diese Regel noch gelten. Wir können das "Identitätselement" von && verwenden, um dies zu lösen.true && thing == thing
, soStream.of().allMatch(it -> it) == true
.quelle
Wenn ich anrufe
list.allMatch
(oder seine Analoga in anderen Sprachen), möchte ich feststellen, ob Elemente inlist
nicht mit dem Prädikat übereinstimmen. Wenn keine Elemente vorhanden sind, stimmt möglicherweise keines überein. Meine folgende Logik würde Elemente auswählen und erwarten, dass sie mit dem Prädikat übereinstimmen. Für eine leere Liste wähle ich keine Elemente aus und die Logik ist weiterhin korrekt.Was passiert , wenn
allMatch
wiederfalse
für eine leere Liste?Meine einfache Logik würde scheitern:
if (!myList.allMatch(predicate)) { throw new InvalidDataException("Some of the items failed to match!"); } for (Item item : myList) { ... }
Ich muss daran denken, den Scheck durch zu ersetzen
!myList.empty() && !myList.allMatch()
.Kurz gesagt, die
allMatch
Rückkehrtrue
zu einer leeren Liste ist nicht nur logisch sinnvoll, sondern liegt auch auf dem glücklichen Weg der Ausführung, der weniger Überprüfungen erfordert.quelle
if (!allMatch)
Es sieht so aus, als ob die Basis die mathematische Induktion ist. Für die Informatik könnte eine Anwendung davon ein Basisfall eines rekursiven Algorithmus sein.
Der Schlüssel hier ist, dass es "leer zufrieden" ist, was von Natur aus etwas irreführend ist. Wikipedia hat eine anständige Diskussion darüber.
quelle
Während diese Frage bereits mehrfach richtig beantwortet wurde, möchte ich einen mathematischeren Ansatz einbringen.
Dafür möchte ich den Stream als Set betrachten (im mathematischen Sinne). Dann
entspricht while
entspricht .
Dass der zweite Teil falsch ist, liegt auf der Hand, da die leere Menge keine Elemente enthält. Der erste ist etwas kniffliger. Sie können entweder akzeptieren, dass es per Definition wahr ist, oder die anderen Antworten aus einigen Gründen prüfen, warum dies so sein sollte.
Ein Beispiel zur Veranschaulichung dieses Unterschieds sind Aussagen wie "Alle auf dem Mars lebenden Menschen haben 3 Beine" (wahr) und "Auf dem Mars lebt ein Mensch mit 3 Beinen" (falsch)
quelle