问题
The arrival of Java 9 brings many new features to Java's Collections API, one of which being collection factory methods.
What are they and how can I implement them properly?
回答1:
Note 1: To prevent the use of raw-types, I have opted to provide a generic type for each class that I mention below by using E, representing an element of a Collection<E>.
Note 2: This answer is subject to change; please edit this post if a typo has occurred.
What are collection factory methods?
A collection factory method in Java is a static method that provides a simple way of initializing an immutable Collection<E>.
Being immutable, no elements can be added to, removed from, or modified inside the Collection<E> after it is initialized.
With Java 9, collection factory methods are provided for the following interfaces: List<E>, Set<E>, and Map<K, V>
What do they improve?
Up until Java 9, there has been no simple, universal method to initialize a Collection<E> with initial elements/key-value entries. Previously, developers were required to initialize them as follows (assuming the generic types E, K, and V have been replaced with Integer):
List<Integer>- The following method is arguably the simplest to initialize a
List<Integer>with initial elements, however the result is simply a view of aList<Integer>; we are unable to add to or remove from thisList<Integer>, but we are still able to modify existing elements by usingList#set.List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
- If we wanted our
List<Integer>to be entirely mutable, then we would have to pass it to the constructor of anArrayList<Integer>, for example:List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
- The following method is arguably the simplest to initialize a
Set<Integer>- A
Set<Integer>required more code to initialize with initial elements than aList<Integer>does (seeing as aList<Integer>is required to initialize aSet<Integer>with initial elements), which can be seen below.Set<Integer> mutableSet = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
- A
Map<Integer, Integer>- A
Map<Integer, Integer>is arguably the most complicated to initialize with initial key-value entries; however, there are multiple ways to go about it.- One method was to first initialize an empty
Map<Integer, Integer>and simply callMap#putto add key-value entries. - Another method was to use an anonymous class with two curly braces, which would still require
Map#putto be called.
- One method was to first initialize an empty
- A
Why should I use them?
I argue that collection factory methods provide the developer with a concise method of initializing a List<E>, Set<E>, or Map<K, V> with initial elements/key-value entries, which can be seen by the examples below.
What is the proper syntax to use?
For simplicity, these examples will replace the generic types E, K, and V with Integer.
List<Integer>List<Integer> list = List.of();- Initializes an empty, immutable
List<Integer>.
- Initializes an empty, immutable
List<Integer> list = List.of(1);- Initializes an immutable
List<Integer>with one element.
- Initializes an immutable
List<Integer> list = List.of(1, 2);- Initializes an immutable
List<Integer>with two elements.
- Initializes an immutable
List<Integer> list = List.of(1, 2, 3, 4, 5, ...);- Initializes an immutable
List<Integer>with a variable amount of elements.
- Initializes an immutable
Set<Integer>Set<Integer> set = Set.of();- Initializes an empty, immutable
Set<Integer>.
- Initializes an empty, immutable
Set<Integer> set = Set.of(1);- Initializes an immutable
Set<Integer>with one element.
- Initializes an immutable
Set<Integer> set = Set.of(1, 2);- Initializes an immutable
Set<Integer>with two elements.
- Initializes an immutable
Set<Integer> set = Set.of(1, 2, 3, 4, 5, ...);- Initializes an immutable
Set<Integer>with a variable amount of elements.
- Initializes an immutable
Map<Integer, Integer>Map<Integer, Integer> map = Map.of();- Initializes an empty, immutable
Map<Integer, Integer>.
- Initializes an empty, immutable
Map<Integer, Integer> map = Map.of(1, 2);- Initializes an immutable
Map<Integer, Integer>with one key-value entry. - Note that the key is
1and the value is2.
- Initializes an immutable
Map<Integer, Integer> map = Map.of(1, 2, 3, 4);- Initializes an immutable
Map<Integer, Integer>with two key-value entries. - Note that the keys are
1and3and the values are2and4.
- Initializes an immutable
Map<Integer, Integer> map = Map.ofEntries(Map.entry(1, 2), Map.entry(3, 4), ...);- Initializes an immutable
Map<Integer, Integer>with a variable amount of key-value entries.
- Initializes an immutable
As you can see, this new method of initialization requires less code than its predecessors.
Can I use collection factory methods to create mutable objects?
The Collection<E> created by collection factory methods are inherently immutable, however we are able to pass them to a constructor of an implementation of the Collection<E> to produce a mutable version:
List<Integer>List<Integer> mutableList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
Set<Integer>Set<Integer> mutableSet = new HashSet<>(Set.of(1, 2, 3, 4, 5));
Map<Integer, Integer>Map<Integer, Integer> mutableMap = new HashMap<>(Map.of(1, 2, 3, 4));
来源:https://stackoverflow.com/questions/43533835/java-9-what-are-collection-factory-methods