A map is a mapping from unique unordered keys to values:
It's a common idiom to construct an empty map and assign values:
We can use each() and eachWithIndex() to access keys and values:
We can check the contents of a map with various methods:
We can clear a map:
Further map methods:
Great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. A special case of this prohibition is that a map should not contain itself as a key.
Collection views of a map
We can inspect the keys, values, and entries in a view:
We can use these views for various checks:
These views also support the removeAll() and retainAll() operations:
Some more map operations:
Getting Map key(s) from a value.
The simplest way to achieve this with the previous map:
Note that the return is only the key dad. As you can see from the family Map both dad and son are keys for the same values.
So, let's get all of the keys with the value "John"
Basically, findAll returns a collection of Mappings with the value "John" that we then iterate through and print the key if the key is groovy true.
This will place your results for the keys into a List of keys
If you just wanted the collection of Mappings:
We can use special notations to access all of a certain key in a list of similarly-keyed maps:
We can group a list into a map using some criteria:
By using groupBy() and findAll() on a list of similarly-keyed maps, we can emulate SQL:
An example with more than one "table" of data:
A HashMap is constructed in various ways:
The capacity is the number of buckets in the HashMap, and the initial capacity is the capacity when it's created. The load factor measures how full the HashMap will get before its capacity is automatically increased. When the number of entries exceeds the product of the load factor and the current capacity, the HashMap is rehashed so it has about twice the number of buckets. A HashMap gives constant-time performance for lookup (getting and putting). Iterating over collection views gives time performance proportional to the capacity of the HashMap instance plus its the number of keys. So don't set the initial capacity too high or the load factor too low. As a general rule, the default load factor (0.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost. Creating a HashMap with a sufficiently large capacity will allow mappings to be stored more efficiently than letting it perform automatic rehashing as needed to grow the table.
A HashSet is implemented with a HashMap, and is constructed with the same choices of parameters:
A sorted map is one with extra methods that utilize the sorting of the keys. Some constructors and methods:
We can construct a TreeMap by giving a comparator to order the elements in the map:
The range-views, headMap() tailMap() and subMap(), are useful views of the items in a sorted map. They act similarly to the corresponding range-views in a sorted set.
We can convert a map into one that can't be modified:
We can create an empty map that can't be modified:
We can create a single-element list that can't be modified:
We can convert a map into an observable one with the 'as' keyword too. An observable map will trigger a PropertyChangeEvent every time a value changes:
We can also wrap an existing map with an ObservableMap
Lastly we can specify a closure as an additional parameter, it will work like a filter for properties that should or should not trigger a PropertyChangeEvent when their values change, this is useful in conjunction with Expando. The filtering closure may take 2 parameters (the property name and its value) or less (the value of the property).