У нас с коллегой возникла ошибка, связанная с нашим предположением, что вызов пустого потока allMatch()
вернется false
.
if (myItems.allMatch(i -> i.isValid()) {
//do something
}
Конечно, это отчасти наша вина, если мы предполагаем, а не читаем документацию. Но я не понимаю, почему allMatch()
возвращается поведение по умолчанию для пустого потока true
. Что послужило причиной этого? Подобно anyMatch()
операции (которая, наоборот, возвращает false), эта операция используется императивным способом, который отходит от монады и, вероятно, используется в if
операторе. Учитывая эти факты, есть ли причина, по которой для большинства применений желательно использовать по allMatch()
умолчанию true
пустой поток?
allMatch
вернет true, то так и должно бытьanyMatch
. Вдобавок для пустого корпуса,allMatch(...) == noneMatch(...)
что тоже странно.i -> i.isValid()
, вы можете написатьFoo::isValid
(гдеFoo
, конечно, какой класс вы транслируете)Ответы:
Это известно как пустая правда . Все члены пустой коллекции удовлетворяют вашему условию; в конце концов, можете ли вы указать на то, что нет?
Точно так же
anyMatch
возвращаетсяfalse
, потому что вы не можете найти элемент своей коллекции, который соответствует условию. Многих это сбивает с толку, но оказывается, что это наиболее полезный и последовательный способ определить «все» и «все» для пустых множеств.источник
1
сумме пустого набора чисел0
. Это нейтральные элементы для умножения / сложения. В случае с логическими значениями это у вас есть,True and x = x
и,False or x = x
следовательно, если вы обобщаетеand
иor
на последовательности (вот чтоall
иany
есть), вы в конечном итоге получаетеTrue
иFalse
для пустого случая, то есть они соответствующие нейтральные элементы.anyMatch
тесты на отсутствие положительных результатов,allMatch
тесты на отсутствие отрицательных.Вот еще один способ подумать об этом:
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 = Stream.of()
тогда это правило все равно нужно применять. Мы можем использовать "элемент идентичности" &&, чтобы решить эту проблему.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
для пустого списка не только логически обоснован, но и находится на правильном пути выполнения, требуя меньшего количества проверок.источник
if (!allMatch)
Похоже, в основе его лежит математическая индукция. В информатике применение этого могло бы быть базовым случаем рекурсивного алгоритма.
Ключевым моментом здесь является то, что оно «удовлетворено пусто», что по своей природе несколько вводит в заблуждение. В Википедии есть достойное обсуждение этого вопроса.
источник
Хотя на этот вопрос уже неоднократно давались правильные ответы, я хочу предложить более математический подход.
Для этого я хочу рассматривать поток как Set (в математическом смысле). потом
соответствует пока
соответствует .
То, что вторая часть ложна, совершенно очевидно, поскольку в пустом наборе нет элементов. Первый вариант немного сложнее. Вы можете принять это как истину по определению или изучить другие ответы на некоторые из причин, почему так должно быть.
Примером, иллюстрирующим это различие, являются утверждения типа «Все люди, живущие на Марсе, имеют 3 ноги» (верно) и «На Марсе живет человек с 3 ногами» (ложь).
источник