EnumSet.spliterator без характерного Spliterator.NONNULL - PullRequest
0 голосов
/ 11 сентября 2018

Я думал об ответе на вопрос: Как проверить наличие нулевых ключей в любой реализации Java-карты?

Моей первой мыслью было проверить, имеет ли Spliterator набора ключей карты характеристику Spliterator.NONNULL:

map.keySet().spliterator().hasCharacteristics(Spliterator.NONNULL)

JavaDoc говорит:

Характеристическое значение, означающее, что источник гарантирует, что встреченные элементы не будут нулевыми. (Это относится, например, к большинство одновременных коллекций, очередей и карт.)

Прежде чем ответить, я сделал несколько проверок:

Spliterator TreeMap без предоставленного Compararator не имеет этой характеристики, даже если естественное упорядочение не допускает нулевые клавиши.

new TreeMap<>().keySet().spliterator().hasCharacteristics(Spliterator.NONNULL); // false 

Еще более удивительным был тот факт, что Spliterator с EnumMap клавиатурой и EnumSet не имеют такой характеристики.

EnumSet.allOf(DayOfWeek.class).spliterator().hasCharacteristics(Spliterator.NONNULL); // false

Я понимаю, что результат spliterator().hasCharacteristics(Spliterator.NONNULL) в вышеуказанных случаях возвращает false, поскольку оценивается реализация Set.spliterator() по умолчанию.

Но есть ли причина, по которой разделители этих наборов не переопределяют Set.spliterator() для создания Spliterator с Spliterator.NONNULL? Это нарушит спецификацию, о которой я не знаю?

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Но есть ли причина, по которой разделители этих наборов не переопределяют Set.spliterator() для создания Spliterator с Spliterator.NONNULL?

Мы можем только строить предположения, но, безусловно, это тот случай, когда некоторые TreeMap экземпляры, которые используют Comparator s для упорядочивания, допускают нулевые ключи, и поэтому сплитераторы их наборов ключей не должны иметь характеристику Spliterator.NONNULL. Хотя верно, что TreeMap, использующий естественное упорядочение своих ключей, не может вместить нулевые ключи, лично я не нахожу удивительным, что наборы ключей TreeMap не используют это для проведения различия. Это свойство, которое, как я ожидаю, будет зависеть исключительно от участвующих классов, а не от деталей каждого экземпляра.

Не нарушит ли это спецификацию, о которой я не знаю?

Возможно. Документы для Set.spliterator() указать

Spliterator сообщает Spliterator.DISTINCT. Реализации должны документировать отчеты о дополнительных значениях признаков.

(выделение добавлено.) Документы для TreeMap.keySet () скажем

Сплитератор набора - с поздним связыванием , , отказоустойчивый , и дополнительно сообщает Spliterator.SORTED и Spliterator.ORDERED о встрече порядок, который является возрастающим ключевым порядком. Компаратор сплитератора (см. Spliterator.getComparator()) равно null, если компаратор древовидной карты (см. SortedMap.comparator()) - это null. В противном случае, компаратор такой же, как или накладывает тот же общий порядок, что и компаратор карты дерева.

Обратите внимание, что документы для этого набора соответствуют ожиданиям, установленным в Set.spliterator() документах, без указания, даже условно, того, что Spliterator.NONNULL входит в число характеристик, о которых будет сообщать сплитератор наборов ключей. Также обратите внимание, что эти же документы do описывают другие характеристики этих наборов, которые различаются в зависимости от того, основан ли порядок карты на компараторе.

Таким образом, нет, вы не должны ожидать, что TreeMap наборов ключей ', сплитераторы будут иметь отчет Spliterator.NONNULL при любых обстоятельствах. Я не могу окончательно сказать, почему был сделан этот выбор, но это согласуется с моим восприятием философии дизайна Java.

Вы тоже написали,

Еще более удивительным было то, что Spliterator из EnumMap Набор ключей и самого EnumSet не имеют этой характеристики.

Я согласен, что эти сплитераторы могли разумно сообщить Spliterator.NONNULL. Я не знаю, почему был сделан выбор, что они не будут этого делать, если это не будет просто упущением. Тем не менее, я замечаю, что в их документах действительно не указано, что эти сплитераторы сообщат Spliterator.NONNULL. В таком случае следует ожидать, что эти сплитераторы не будут сообщать об этой характеристике.

0 голосов
/ 11 сентября 2018

Еще хуже:

System.out.println(Set.of(1)
             .spliterator()
             .hasCharacteristics(Spliterator.NONNULL)); // false

Даже если эти Set::of методы задокументированы как:

выдает исключение NullPointerException, если элемент имеет значение null

Так что в этом Set нет способа получить нулевое значение. Я предполагаю, что реальный ответ состоит в том, что это еще не сделано .

EDIT

См. комментарий Стюарта Маркса об этом

...