View in Java Collections Framework is a lightweight object which implements Collection or Map interface but is not a real collection in a traditional sense. In fact, view does store objects inside but references another collection, array or a single object and uses it to provide the data to a user.
To start with views let’s take a look at the simplest ones which represent empty collections. In Collections class you can find emptyList(), emptySet() and emptyMap() methods which create empty instance of List, Set or Map respectively:
List<String> clearList = Collections.emptyList(); Set<String> clearSet = Collections.emptySet(); Map<String, Integer> clearMap = Collections.emptyMap();
The returned instance is actually immutable so trying to add an element into it will result in an exception. However, this kind of empty collection is very convenient if some API requires a collection but for some reason we don’t want to pass any objects there.
View of a single object
Very often we need a collection with only one element. Achieving this with views is very easy. We can create such list, set or map by calling singletonList(), singleton() or singletonMap() methods respectively:
List<String> oneList = Collections.singletonList("elem"); Set<String> oneSet = Collections.singleton("elem"); Map<String, Integer> oneMap = Collections.singletonMap("one", 1);
It is also possible to create a list which contains specified element given number of times:
List<String> nTimesList = Collections.nCopies(9, "elem");
The created collections are immutable similarly to empty views. Additionally, the views does not have the overhead of a typical collection and are easier to create.
View of an array
If you ever needed to repack elements from an array into a list just to call a single method, you may appreciate asList() method from Arrays class which creates a list view backed by an array:
String monthArray = new String; List<String> monthList = Arrays.asList(monthArray);
For obvious reasons the returned collection is immutable which means it is impossible to add or remove elements from it. But it is still possible to modify the elements inside the view using get() or set() methods.
Since Java 5 it is also possible to use varargs in asList() method:
List<String> months = Arrays.asList("July", "August");
View of a portion of a collection
We can also create a view of a portion of a list:
List<String> nextFive = list.subList(5, 10);
The returned view contains 5 elements of the original list between index 5, inclusive, and 10, exclusive. The view is also mutable so any modification on the view (e.g. adding or removing elements), will also affect the original list.
The similar functionality is also possible on SortedSet using methods:
SortedSet<E> headSet(E toElement); SortedSet<E> subSet(E fromElement, E toElement); SortedSet<E> tailSet(E fromElement);
and on SortedMap:
SortedMap<K,V> headMap(K toKey); SortedMap<K,V> subMap(K fromKey, K toKey); SortedMap<K,V> tailMap(K fromKey);
Views of keys, values and entries
You should be probably aware of keySet(), entrySet() and values() methods of Map interface. They also return views instead of real collections which make them very efficient.
Class Collection provides methods which create immutable view for many collections types:
List<T> unmodifiableList(List<? extends T> list); Map<K,V> unmodifiableMap(Map<? extends K,? extends V> m); Set<T> unmodifiableSet(Set<? extends T> s); SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,? extends V> m); SortedSet<T> unmodifiableSortedSet(SortedSet<T> s);
If somebody tries to add or remove elements from the view, it will throw an exception. This kind of behaviour is very useful if we want to ensure that given method will not modify the collection. However, it is still possible to modify the elements inside the collection.
Creating unmodifiable view does not make the original collection unmodifiable. It is still possible to change it using the original reference.
Similarly to unmodifiable views we can create synchronized views using methods:
Collection<T> synchronizedCollection(Collection<T> c); List<T> synchronizedList(List<T> list); Map<K,V> synchronizedMap(Map<K,V> m); Set<T> synchronizedSet(Set<T> s); SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m); SortedSet<T> synchronizedSortedSet(SortedSet<T> s);
Every method of synchronized view is synchronized which make the view thread-safe. Of course, you should no longer hold or use the reference to the original collection because it would allow unsynchronized access to it.
I tried to mention most popular and useful views in Java Collections Framework. They greatly simplify some common tasks, reduce the number of times when repacking is needed and also reduce the amount of code to type. I hope you will find them useful too.