Contents

Modern Java in Action 3 - collection API

book notes: collection API enhancements

New API (in Java 8)

Collection classes got a few nice additions.

Factory methods

They create immutable collection (if you try to add/remove elements, you get UnsupportedOperationException. There is no varargs variant - this variant would require additional array allocation, which non-varargs variants don’t have.

There are overloads from 1 to 10 elements.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//static <E> List<E> of(E... elements)

static <E> List<E> of(E e1)
static <E> List<E> of(E e1, E e2)
static <E> List<E> of(E e1, E e2, E e3)
static <E> List<E> of(E e1, E e2, E e3, E e4)
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5)
// ... other variants


static <E> Set<E> of(E e1)
static <E> Set<E> of(E e1, E e2)
//... etc, other variants up to 10 


static <K, V> Map<E> of(K k1, V v1)
static <K, V> Map<E> of(K k1, V v1, K k2, V v2)
// ... etc, variants up to 10 pairs
// or with entries
import static java.util.Map.entry;
static <K, V> Map<E> ofEntries(entry(k1, v1), entry(k2, v2))

lists: removeIf, replaceAll

On a list you can use removeIf and replaceAll

1
2
3
4
5
6
7
// removeIf: removes transation if it starts with a digit
transactions.removeIf(transaction ->
     Character.isDigit(transaction.getReferenceCode().charAt(0)));
// replaceAll: replaces each transaction code 
//with one that has first character uppercased
referenceCodes.replaceAll(code -> Character.toUpperCase(code.charAt(0)) +
     code.substring(1));

maps: forEach, comparingBy{Key,Value}

On a map you can iterate over pairs without the need to use an iterator that gives Map.Entry<K, V>:

1
2
ageOfFriends.forEach((friend, age) -> System.out.println(friend + " is " +
     age + " years old"));

and you can sort by keys or values:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Map<String, Integer> m = Map.of("Kaisa", 23, "Ola", 36, "Monika", 78);
// {Ola=36, Kaisa=23, Monika=78}
m.entrySet().stream().sorted(Entry.comparingByValue()).forEachOrdered(System.out::println);
//Kaisa=23
//Ola=36
//Monika=78
m.entrySet().stream().sorted(Entry.comparingByKey()).forEachOrdered(System.out::println);
//Kaisa=23
//Monika=78
//Ola=36

HashMap performance

If keys are Comparable, HashMap implementation uses sorted trees with O(log(n)) retrieval instead of LinkedList which have O(n) retrieval complexity (those data structures are used for keeping entries with the same key hashcode).

getOrDefault, compute{,IfAbsent,IfPresent}

Other methods worth mentioning allow:

  • V getOrDefault(Object key, V defaultValue): get value by key but provide a defualt value in case there is no such key
  • V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) - attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
  • V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) - if the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null
  • V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) - if the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value

replace, replaceAll, merge

  • replace - replace a value in the Map if a key is present
  • replaceAll - replaces each entry’s value with the result of applying a BiFunction
  • merge - takes a BiFunction to merge values that have a duplicate key

ConcurrentHashMap

Concurrency-friendly map with new methods that work with X where X means: keys, values, entries or pairs of key and value:

  • forEach{,Key,Value,Entry} - Performs a given action for each X
  • reduce{,Key,Value,Entry} - Combines all X-es given a reduction function into a result
  • search{,Key,Value,Entry} - Applies a function on each X until the function produces a non-null result
  • reduce{,Keys,Values,Entrys}{,ToInt, ToLong,ToDouble} - reduction, possibly to primitive types

These functions require providing parallelism threashold:

  • value of 1: maximal parallelism using the common thread pool
  • value of Long.MAX_VALUE: runs the operation on a single thread

Also:

  • mappingCount - returns long, not int; preferrable over size
  • keySet - creates a view of keys backed by original map