[user]$ groovysh -q
groovy:000>
Groovy Shots - Collections - Spread operator
Sometimes it looks more natural handling collections and maps using operators rather than to use the correspondent method call. The spread operator in Groovy is one of those.
Groovy Shell
To write the examples I’m using the Groovy shell. To start the Groovy shell go to your terminal and start the Groovy shell:
I’ve minimized the verbosity of the Groovy shell in the examples by replacing the groovy:000>
prompt by just >
. Also remember that in the Groovy shell
you may not want to use the def
keyword to define a variable (here you can see why)
Lists
Of course the first case is to create an empty list:
> empty = []
> assert empty.size() == 0
Notice you can initialize the new list with any number of elements:
> myList = [1]
Now I would like to add one more element to the end of the previous list. Here the spread operator is used to add all elements from myList inside newList before the new element 2.
> myList = [1]
> newList = [*myList, 2]
> assert newList == [1, 2]
Or adding a new element at the beginning of the previous list.
> myList = [1]
> newList = [0, *myList]
> assert newList == [0, 1]
The previous examples were pretty trivial, and could be also be tackled by other operators available to lists:
> myList = [1]
> myList = [0] + myList // adding at the beginning
> myList = myList << 2 // adding at the end
> assert myList == [0, 1, 2]
But when adding in the middle of some lists, the spread operator really shines:
> myList = [4, 5]
> newList = [1, 2, 3, *myList, 6, 7, 8]
> assert newList == [1, 2, 3, 4, 5, 6, 7, 8]
Then you can also add two different lists:
> topTen = [*[1, 3, 5, 7, 9], *[2, 4, 6, 8, 10]]
> assert topTen == [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
Which is the same as adding one list to the other with simply + operators:
> topTen = [1, 3, 5, 7, 9] + [2, 4, 6, 8, 10]
> assert topTen == [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
You can also use array syntax to specify which elements of the list you would like to use. In the following example I’m combining two lists using a range as the initial source list.
> range = (0..10)
> mirror = [*range[1..6], *range[5..1]]
> assert mirror == [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
What about removing elements from a given list. Deleting one element is as simple as using the -
operator:
> myList = [1, 2, 3, 4, 5] - 5
> assert myList = [1, 2, 3, 4]
I can delete more than one element by subtracting one list to another:
> myList = [1, 2, 3, 4, 5] - [3, 5]
> assert myList = [1, 2, 4]
Maps
In maps spread operator can also be useful, specially when overriding values from a given map. Lets say we have a configuration map, and some of the entries are common to all scenarios whereas some elements can be changed.
> common = [y: 200, x: 100, type: "circle", color: "green"]
>
> pointA = [
> *: common,
> x: 200,
> ]
>
> assert pointA == [y: 200, x: 200, type: "circle", color: "green"]
Obviously changing the order will lead to always override my values:
> common = [y: 200, x: 100, type: "circle", color: "green"]
>
> pointA = [
> x: 200,
> *: common,
> ]
>
> assert pointA == [y: 200, x: 100, type: "circle", color: "green"]
Next, like we did in the lists examples we can do normal operations such as adding up whole maps:
> mapA = [a: 1, b: 2, c: 3]
> mapB = [d: 4]
> mapAB = [*: mapA, *: mapB]
> assert mapAB == [a: 1, b: 2, c: 3, d: 4]
To add only some elements of a map to another map there’s no operator for the subMap method. For completeness I’m adding here an example using the subMap method:
> mapA = [a: 1, b: 2, c: 3]
> mapB = [d: 4]
> mapAB = [*: mapA.subMap("a", "c"), *: mapB]
> assert mapAB == [a: 1, c: 3, d: 4]
Lastly you can remove entries from a map with the minus operator as we did previously in list:
> mapA = [a: 1, b: 2, c: 3, d: 4, e: 5]
> mapB = mapA - [b: 2, c: 3, d: 4]
> assert mapB == [a: 1, e: 5]
Again is also important to highlight the subMap method here as the example could be simplified:
> mapA = [a: 1, b: 2, c: 3, d: 4, e: 5]
> mapB = mapA - mapA.subMap("b".."d")
> assert mapB == [a: 1, e: 5]
Notice how subMap can take a range of map keys as parameter, building a map with a series of map entries.
Versions
-
Groovy 2.5.13