Utility Classes of The JDK - Collections and Arrays PDF
Utility Classes of The JDK - Collections and Arrays PDF
You have 2 free stories left this month. Sign up and get an extra one for free.
The JDK is evolving with every new release, adding more and improving
existing features. Beneath the surface are hidden gems that can make
our lives as developers much easier.
The first article highlights the utility classes with their static methods for
dealing with collections and arrays.
. . .
Set<T> emptySet()
List<T> emptyList()
Map<K,V> emptyMap()
SortedSet<E> emptySortedSet()
SortedMap<K,V> emptySortedMap()
NavigableSet<E> emptyNavigableSet()
NavigableMap<K,V> emptyNavigableMap()
Enumeration<T> emptyEnumeration()
Iterator<T> emptyIterator()
ListIterator<T> emptyListIterator()
Singletons
Instead of an empty collection, we can also return an immutable
collection with exactly one element:
Set<T> singleton(T o)
List<T> singletonList(T o)
Immutability
Creating an unmodifiable view backed by an existing collection. This way
we can make a pre-existing collection immutable:
SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)
NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s)
Binary search
Instead of iterating over collections, the index of a specific element can
be located using the binary search algorithm:
Thread-safety
Creating a synchronized (thread-safe) view of an existing collection:
Collection<T> synchronizedCollection(Collection<T> c)
Set<T> synchronizedSet(Set<T> s)
Map<K,V> synchronizedMap(Map<K,V> m)
SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s)
NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m)
1 List<String> threadSafe =
2 Collections.synchronizedCollection(data);
3
4 synchronized (threadSafe) {
5 // This call MUST be inside a synchronized block
6 Iterator<String> i = c.iterator();
7 while (i.hasNext()) {
8 // ...
9 }
10 }
Collection<E> checkedCollection(Collection<E> c,
Class<E> type)
Set<E> checkedSet(Set<E> s,
Class<E> type)
Map<K,V> checkedMap(Map<K,V> m,
Class<K> keyType,
Class<V> valueType)
SortedSet<E> checkedSortedSet(SortedSet<E> s,
Class<E> type)
SortedMap<K,V> checkedSortedMap(SortedMap<K,V> m,
Class<K> keyType,
Class<V> valueType)
NavigableSet<E> checkedNavigableSet(NavigableSet<E> s,
Class<E> type)
NavigableMap<K,V> checkedNavigableMap(NavigableMap<K,V> m,
Class<K> keyType,
Class<V> valueType)
1 // UNTYPED COLLECTION
2 List untyped = new ArrayList();
3 untyped.add("A");
4 untyped.add("B");
5 // untyped.add(1); <-- this would be valid, but is undesired
6
7 // CREATE TYPE-SAFE VIEW
8 List<String> typed = Collections.checkedList(untyped, String.class);
. . .
To not list every single method, the placeholder type[] will be used as a
stand-in for the different types. The type boolean is a special case and
won’t support a method unless it’s mentioned.
List creation
The easiest way to create a list from an arbitrary amount of elements:
List<T> asList(T... a)
Sorting
Just like collections before, arrays can be sorted. In case of value types,
this means in numerical order, for Object and <T> , in the natural order.
void sort(type[] a)
void parallelSort(type[] a)
void parallelSort(T[] a)
void sort(type[] a,
int fromIndex,
int toIndex)
void sort(T[] a,
int fromIndex,
int toIndex, Comparator<? super T> c)
void parallelSort(type[],
int fromIndex,
int toIndex)
void parallelSort(T[] a,
int fromIndex,
int toIndex)
void sort(T[] a,
Comparator<? super T> c)
void sort(T[] a,
int fromIndex,
int toIndex,
Comparator<? super T> c)
void parallelSort(T[] a,
Comparator<? super T> cmp)
void parallelSort(T[] a,
int fromIndex,
int toIndex,
Comparator<? super T> cmp)
Streams
I have written multiple times about how much I love Streams. With the
help of Arrays we can easily create Stream<T> and value-type Streams, at
least for the supported types:
type[] | ValueTypeStream
----------|-----------------
int[] | IntStream
long[] | LongStream
double[] | DoubleStream
Spliterator
Java 8 introduced the java.util.Spliterator interface, a base utility for
Streams. It's used for traversing and partitioning sequences.
type[] | ValueTypeSpliterator
----------|---------------------
int[] | Spliterator.OfInt
long[] | Spliterator.OfLong
double[] | Spliterator.OfDouble
String representations
For better debugging or logging output, we can create a string
representation of arrays. In addition to the listed types above, boolean is
supported. Object[] might contain other arrays, so a method for a deep
string representation is also available:
String toString(type[] a)
String deepToString(Object[] a)
Equality
Like string representation, boolean is supported, and we can check
Object[] for deep equality:
boolean equals(type[] a,
type[] a2)
Hashcodes
Calculating a hashcode also supports boolean and deep calculation:
int hashCode(type[] a,
type[] a2)
Binary search
Finds the index a specific element in an array using the binary search
algorithm:
int binarySearch(type[] a,
type key)
int binarySearch(type[] a,
int fromIndex,
int toIndex,
type key)
int binarySearch(T[] a,
T key,
Comparator<? super T> c)
int binarySearch(T[] a,
int fromIndex,
int toIndex,
T key,
Comparator<? super T> c)
Copying
We can copy any array to a specific length, either truncating it, or
padding the new space with the appropriate uninitialized value, or null .
void fill(type[] a,
type val)
void fill(type[] a,
int fromIndex,
int toIndex,
type val)
type[] | ValueGenerator
----------|---------------------
int[] | IntUnaryOperator
long[] | IntToLongFunction
double[] | IntToDoubleFunction
Parallel prefixing
The parallelPrefixing methods cumulate each element of an array in
parallel. For larger arrays, this kind of operation is usually more efficient
than sequential processing:
type[] | ValueOperator
----------|---------------------
int[] | IntBinaryOperator
long[] | LongBinaryOperator
double[] | DoubleBinaryOperator
If you haven’t used this method before, it can be unclear what exactly it
does, at least that has been my experience. Here’s an example to explain
it:
. . .
Conclusion
Many common tasks that we might either code ourselves, or use a third-
party-library, can be safely done directly with the JDK. This way we
depend on fewer externalities, don’t introduce bugs by writing additional
code and handle common tasks in a concise, consistent, and
reproducible way.
The next part will present utility classes for handling I/O.
. . .
Resources
java.util.Arrays
java.util.Collections
94 claps
WRIT T EN BY
How to decouple Views Here Are the Most 7 Alternatives to the Web Applications using
from their State Interesting Developer <div> HT ML Tag Python and Django
Liviu Coman in Zero Equals Podcasts Zac Heisey Francisco Igor
False Indrek Lasn in Better
Programming