Удобные фабричные методы Java для коллекций
В JDK 9 к базовым интерфейсам Collection добавлены статические фабричные методы, такие как of() , для создания неизменяемых объектов коллекций. Это то же самое, что и неизменяемая (неизменяемая) коллекция, которую мы создаем в JDK 6, 7, 8. Она позволяет создавать список, набор и карту значений всего в одной строке. Java 9 не привносит столько кардинальных изменений в наш способ кодирования, как его предшественник, но, несомненно, у нас будут некоторые необычные функции.
Нижеперечисленные пути ведут к создание ненужных объектов. Чтобы преодолеть эту проблему, в Java 9 введены статические фабричные методы для создания неизменяемых списков, наборов и карт, которые будут обсуждаться позже. до этого давайте пересмотрим создание немодифицируемой коллекции до JDK 9 (JDK 7, 8).
Список в JDK 8
List<String> listOfString = new ArrayList<>();
listOfString.add("Geeks");
listOfString.add("Java");
listOfString.add("Kotlin");
listOfString.add("Groovy");
listOfString.add("Scala");
listOfString = Collections.unmodifiableList(listOfString);Способ 1: использование инициализации с двойными фигурными скобками
List<String> listOfString = Collections.unmodifiableList(new ArrayList<>() {
{
add(“Geeks”);
add(“Java”);
add(“Kotlin”);
add(“Groovy”);
add(“Scala”);
}
});
Способ 2: использование Arrays API для преобразования массива в ArrayList
List<String> listOfString = Collections.unmodifiableList(Arrays.asList(“Geeks”,”Java”,”Kotlin”,”Groovy”, “Scala”));
Способ 3: использование Stream API
List<String> listOfString = Collections.unmodifiableList(Stream.of(“Bruce”,”Steve”,”Adrian”, “Dave”, “Janick”,”Nicko”).collect(toList()));
Почему Ява 9?
Теперь давайте посмотрим на преимущества, прежде чем использовать статические фабричные методы Java 9, прежде чем переходить к ним.
- Позволяет создать список, набор и карту значений всего в одну строку.
- Создание неизменяемых объектов с использованием статических фабричных методов не позволяет нам вставлять пустые значения или дубликаты (в наборы или карты).
- Мы защищены от получения исключений NullPointerException при обходе элементов коллекции.
Теперь давайте обсудим создание немодифицируемой коллекции в JDK. Здесь list, Set и map обсуждаются ниже.
1. Список в Java 9
List<String> listOfString = List.of("Geeks", "Java", "Kotlin", "Groovy", "Scala");Всего одной строки кода достаточно для создания неизменяемого списка, поэтому создание ненужных объектов не требуется.
- List.of() позволяет создать пустой неизменяемый список.
- Любая модификация вызовет исключение UnsupportedOperationException.
- Несколько перегруженных версий List.of() доступны с точки зрения производительности.
Неизменяемый список имеет абстрактный базовый класс AbstractImmutableList<E> и четыре реализации:
- Список0<E>
- Список1<Е>
- Список2<Е>
- СписокN<E>
Каждому из этих типов соответствует количество элементов, которые используются для их создания. В интерфейсе java.util.List у нас есть 12 статических фабричных методов, которые используют приведенные выше реализации для создания неизменяемых объектов:
// creates empty immutable list static <E> List<E> of() // creates one-element immutable list static <E> List<E> of(E e1) // creates two-element immutable list static <E> List<E> of(E e1, E e2) // creates ten-element immutable list static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) // creates N-element immutable list static <E> List<E> of(E... elements)
Также ускользните от методов, которые выдают UnsupportedOperationException, а именно следующим образом:
- add(E e), addAll(Collection<? extends E> c), addAll(int index, Collection<? extends E> c)
- remove(Объект o), removeAll(Collection<?> c), removeIf(Predicate<? super E> filter)
- replaceAll (оператор UnaryOperator<E>)
- сохранитьВсе(Коллекция<?> c)
- sort(Comparator<? super E> c)
- Чисто()
Вставка значений Null вызовет исключение NullPointerException, как показано ниже.
List<String> listOfString = List.of("Geeks","Java","Kotlin", "Scala", "Groovy", null);
// throws NullPointerExceptionСледовательно, правильное создание неизменяемого списка выглядит следующим образом:
List<String> listOfString = List.of("Geeks","Java","Kotlin", "Scala", "Groovy","Pearl");2. Установить в Java 9
- Set.of() позволяет создать пустой неизменяемый набор.
- Любая модификация вызовет исключение UnsupportedOperationException.
- С точки зрения производительности доступно несколько перегруженных версий Set.of() .
Иллюстрация:
Неизменяемый набор реализован аналогично тому, как мы видели это в интерфейсе List. Он имеет абстрактный базовый класс AbstractImmutableSet<E> и четыре реализации:
- Установить0<E>
- Набор1<Е>
- Набор2<Е>
- ЗадатьN<E>
Это снова соответствует количеству элементов, которые используются при их создании. В интерфейсе java.util.Set у нас есть 12 статических фабричных методов:
// creates empty immutable set static <E> Set<E> of() // creates one-element immutable set static <E> Set<E> of(E e1) // creates two-element immutable set static <E> Set<E> of(E e1, E e2) // creates ten-element immutable set static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) // creates N-element immutable set static <E> Set<E> of(E... elements)
Методы, вызывающие исключение UnsupportedOperationException, следующие:
- добавить(E e), addAll(Collection<? extends E> c)
- remove(Объект o), removeAll(Collection<?> c), removeIf(Predicate<? super E> filter)
- сохранитьВсе(Коллекция<?> c)
- Чисто()
Иллюстрация:
Как и в случае с неизменяемыми списками, мы не можем создать экземпляр Set с нулевым значением, поскольку он выбрасывает исключение NullPointerException, где добавление дубликата приведет к исключению IllegalArgumentException, как показано ниже:
Set<String> setOfString = Set.of("Geeks", "Java", "Kotlin", "Scala", "Groovy", null);
// throws NullPointerException
Set<String> setOfString = Set.of("Geeks", "Java", "Kotlin", "Java");
// throws IllegalArgumentExceptionСледовательно, допустимое создание неизменяемого набора выглядит следующим образом:
Set<String> setOfString = Set.of("Geeks", "Java", "Kotlin", "Scala", "Groovy", "Pearl");3. Карта в Java 9
- Map.of() и Map.ofEntries() позволяют создать неизменяемую карту.
- Любая модификация вызовет исключение UnsupportedOperationException.
- Map.of() перегружен для создания карты не более чем из 10 пар ключ-значение.
- Map.ofEntries() будет использоваться для создания карты из более чем 10 пар ключ-значение.
Неизменная карта имеет абстрактный базовый класс AbstractImmutableMap<K, V> с тремя реализациями:
- Карта0<К, В>
- Карта1<К, В>
- Карта N<K, V>
Снова у нас есть следующий набор фабричных методов внутри интерфейса java.util.Map.
// creates an empty map
static <K, V> Map<K, V> of()
// creates one-element map
static <K, V> Map<K, V> of(K k1, V v1)
// creates two-element map
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2)
// creates ten-element map
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4,
K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8,
K k9, V v9, K k10, V v10)
// creates N-element map
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries)Опять же, методы, вызывающие исключение UnsupportedOperationException, следующие:
- Чисто()
- вычислить (клавиша K, BiFunction<? super K,? super V,? extends V> rf)
- calculateIfAbsent (клавиша K, Function<? super K,? extends V> mf)
- ComputeIfPresent(Ключ, BiFunction<? super K,? super V,? extends V> rf)
- слияние (ключ K, значение V, BiFunction<? super V,? super V,? extends V> rf)
- put(K ключ, значение V), putAll(Map<? расширяет K,? расширяет V> m), putIfAbsent(K ключ, значение V)
- удалить (ключ объекта), удалить (ключ объекта, значение объекта)
- заменить (ключ K, значение V), заменить (ключ K, старое значение V, новое значение V), заменить все (BiFunction<? super K,? super V,? extends V> f)
Иллюстрация:
Вставка ключа или значения Null вызовет NullPointerException :
Map<String, Integer> weightInKg = Map.of(null, 59, "John", 61); // throws NullPointerExcepton because of null key
Map<String, Integer> weightInKg = Map.of("Ron", null, "John", 61);
// throws NullPointerExcepton because of null valueMap<String, Integer> weightInKg = Map.ofEntries(Map.entry("Ron", 59), null);
// throws NullPointerExcepton because of null entryДобавление повторяющегося ключевого элемента вызовет исключение IllegalArgumentException:
Map<String, Integer> weightInKg = Map.of("Ron", 59, "Ron", 59);Map<String, Long> weightInKg = Map.ofEntries(Map.entry("Ron", 59), Map.entry("Ron", 59));Правильное создание неизменяемой карты выглядит следующим образом:
Map<String, Long> weightInKg = Map.of("Ron", 59, "John", 61, "Ed", 60, "Nick", 60, "Jack", 60L, "Ben", 65);Map<String, Long> age = Map.ofEntries(Map.entry("Ron", 59),
Map.entry("John", 61),
Map.entry("Ed", 60),
Map.entry("Nick", 60),
Map.entry("Jack", 60),
Map.entry("Ben", 65));