Как правило, использование новых фабрик безопасно для нового кода, где нет существующего кода, зависящего от поведения существующих коллекций.
Есть несколько причин, по которым новые фабрики коллекций не являются простой заменой кода, который инициализирует коллекции с помощью существующих API. Очевидно, неизменность — одна из наиболее важных причин; если вам нужно изменить коллекцию позже, она, очевидно, не может быть неизменной! Но есть и другие причины, некоторые из них довольно тонкие.
Пример замены существующих API новыми API см. в разделе JDK-8134373. . Темы обзора находятся здесь: Часть 1 Часть 2.
Вот краткое изложение проблем.
Перенос массива в сравнении с копированием. Иногда у вас есть массив, например. параметр varargs, и вы хотите обработать его как список. Иногда Arrays.asList
здесь подходит больше всего, так как это просто оболочка. Напротив, List.of
создает копию, что может быть расточительным. С другой стороны, вызывающая сторона по-прежнему имеет дескриптор обернутого массива и может изменить его, что может быть проблемой, поэтому иногда вам нужно оплатить расходы на его копирование, например, если вы хотите сохранить ссылку на массив. список в переменной экземпляра.
Порядок итерации хешированной коллекции. Новые структуры Set.of
и Map.of
рандомизируют порядок итерации. Порядок итерации HashSet
и HashMap
не определен, но на практике оказывается относительно стабильным. В коде могут возникать непреднамеренные зависимости от порядка итерации. Переключение на новые фабрики коллекций может подвергнуть старый код зависимостям порядка итерации, выявив скрытые ошибки.
Запрет нулевых значений. Новые коллекции полностью запрещают пустые значения, в то время как обычные непараллельные коллекции (ArrayList
, HashMap
) их разрешают.
Формат сериализации. Новые коллекции имеют формат сериализации, отличный от старых. Если коллекция сериализована или хранится в другом сериализованном классе, сериализованный вывод будет другим. Это может быть или не быть проблемой. Но если вы планируете взаимодействовать с другими системами, это может стать проблемой. В частности, если вы передадите сериализованную форму новых коллекций на JVM Java 8, она не сможет десериализоваться, потому что новые классы не существуют в Java 8.
Строгое поведение метода мутатора. Новые коллекции неизменяемы, поэтому, конечно, они выдают UnsupportedOperationException
при вызове методов мутатора. Однако есть некоторые пограничные случаи, когда поведение не является одинаковым для всех коллекций. Например,
Collections.singletonList("").addAll(Collections.emptyList())
ничего не делает, тогда как
List.of("").addAll(Collections.emptyList())
кинет УОЭ. В общем, новые коллекции и неизменяемые оболочки последовательно строги в выбрасывании UOE при любом вызове метода мутатора, даже если фактическая мутация не произойдет. Другие неизменяемые коллекции, например из Collections.empty*
и Collections.singleton*
, вызовут UOE только в том случае, если произойдет фактическая мутация.
Дубликаты. Новые фабрики Set
и Map
отклоняют повторяющиеся элементы и ключи. Обычно это не проблема, если вы инициализируете коллекцию списком констант. Действительно, если список констант имеет дубликаты, это, вероятно, ошибка. Потенциально это может быть проблемой, когда вызывающему объекту разрешено передавать коллекцию или массив (например, varags) элементов. Если вызывающий объект передает дубликаты, существующие API-интерфейсы молча пропускают дубликаты, тогда как новые фабрики выдают IllegalArgumentException
. Это изменение поведения, которое может повлиять на вызывающих абонентов.
Ни одна из этих проблем не является фатальной, но они представляют собой поведенческие различия, о которых следует помнить при модификации существующего кода. К сожалению, это означает, что делать массовую замену существующих вызовов новыми фабриками коллекций, вероятно, не рекомендуется. Вероятно, необходимо провести некоторую инспекцию на каждом участке, чтобы оценить любое потенциальное влияние поведенческих изменений.
person
Stuart Marks
schedule
03.12.2016
if (beans == Collections.EMPTY_LIST) { beans = new ArrayList<>(); }
? - person marstran   schedule 30.11.2016something.getBeans().add(somethingElse)
не создавать новый список массивов на более высоком уровне и не устанавливать его и т. д. - person Shadov   schedule 30.11.2016