Интерфейс Set не делает promises о том, позволяют ли реализации использовать элементы null. Каждая реализация должна объявить об этом в своей документации.
Collectors.toSet() promises, чтобы вернуть реализацию Set, но явно не дает никаких гарантий относительно типа, изменчивости, сериализуемости, или безопасность потока Set возвращена ". Нулевая безопасность не упоминается.
Текущая реализация Collectors.toSet() в OpenJDK всегда использует HashSet, которая допускает нулевые элементы, но это может измениться в будущем, а другие реализации могут по-другому.
Если реализация Set запрещает элементы null, она бросает NullPointerException в разное время, в частности во время попытки add(null). Казалось бы, если Collectors.toSet() решил использовать реалистичную реализацию Set с нулевым нетерпимостью, вызов stream.collect(Collectors.toSet()) на Stream stream бросить. Спецификация collect не содержит никаких исключений, а также не спецификация любого из методов Collector. Это может означать, что вызов collect разрешает null в пределах stream, но, с другой стороны, неясно, действительно ли это означает много, поскольку NullPointerException является неконтролируемым исключением и не обязательно должен быть указан.
Является ли это более четким в любом другом месте? В частности, является ли следующий код гарантированным не бросать? Гарантируется ли возврат true?
import java.util.stream.*;
class Test {
public static boolean setContainsNull() {
return Stream.of("A", "list", "of", null, "strings")
.collect(Collectors.toSet())
.contains(null);
}
}
Если нет, то я предполагаю, что мы всегда должны гарантировать, что поток не содержит нулей перед использованием Collectors.toSet() или будет готов к обработке NullPointerException. (Достаточно ли этого исключения?) Альтернативно, когда это неприемлемо или сложно, мы можем запросить конкретную реализацию набора с использованием кода типа Collectors.toCollection(HashSet::new).
Изменить: существует существующий вопрос, который кажется поверхностным схожим, и этот вопрос закрылся как предполагаемый дубликат этого. Однако связанный вопрос вообще не затрагивает Collectors.toSet(). Более того, ответы на этот вопрос составляют основные предположения моего вопроса. Этот вопрос спрашивает: допустимы ли пустые значения в потоках? Да. Но что происходит, когда (полностью разрешенный) поток, содержащий нули, собирается через стандартный сборщик?