Collections
The utility class Collections is a library class that provides collection functionality that doesn’t fit neatly into any of the collection interfaces. Here is a quick overview of what is available.
Searching
The indexOf() operation takes time proportional to the size of the list. However, if the elements are sorted, binary search can find the index of an element in log2 n time. Call Collections.binarySearch(list, element) to return the index of an element in the list. If the element does not appear in the list, a negative number will be returned. If the list is not sorted, the results are unpredictable.
Binary search only improves performance for lists with constant-time random access, like ArrayList (see Figure 9.6).
Figure 9.6 Comparing indexOf() and binary search
Sorting
Collections also provides operations to change the order of the elements of a list. Reverse(list) reverses the order of all the elements of the list. Shuffle(list) places the elements in random order. Sort(list) and sort(list, comparator) place the elements in ascending order. Unlike binary search, sorting performance is roughly the same for ArrayList and LinkedList, because the elements are first copied into an array, the array is sorted, and then the elements are copied back (run the timer test Sorting in Appendix A to verify this).
Unmodifiable Collections
As mentioned in the discussion of Iterable above, even the most basic collection interfaces allow collections to be modified. If you are passing a collection to untrusted code, you can ensure that it won’t be modified by having Collections wrap it in an implementation that throws a runtime exception if clients try to modify it. There are variants that work with Collection, List, Set, and Map.
@Test(expected=UnsupportedOperationException.class) public void unmodifiableCollectionsThrowExceptions() { List<String> l= new ArrayList<String>(); l.add("a"); Collection<String> unmodifiable= Collections.unmodifiableCollection(l); Iterator<String> all= unmodifiable.iterator(); all.next(); all.remove(); }
Single-Element Collections
If you have a single element and you need to pass it to an interface that expects a collection, you can quickly convert it by calling Collections.singleton(), which returns a Set. There are also variants that convert to a List or Map. All the collections returned are not modifiable.
@Test public void exampleOfSingletonCollections() { Set<String> longWay= new HashSet<String>(); longWay.add("a"); Set<String> shortWay= Collections.singleton("a"); assertEquals(shortWay, longWay); }
Empty Collections
Similarly, if you need to use an interface that expects a collection and you know you have no elements, Collections will create an unmodifiable empty collection for you.
@Test public void exampleOfEmptyCollection() { assertTrue(Collections.emptyList().isEmpty()); }