In Java we can merge a key/value pair into a Map
with the merge
method. The first parameter is the key, the second the value and the third parameter of the merge
method is a remapping function that is applied when the key is already present in the Map
instance. The remapping function has the value of the key in the original Map
and the new value. We can define in the function what the resulting value should be. If we return null
the key is ignored.
If we want to merge multiple Map
instances we can use the Stream API. We want to convert the Map
instances to a stream of Map.Entry
instances which we then turn into a new Map
instance with the toMap
method from the class Collectors
. The toMap
method also takes a remapping function when there is a duplicate key. The function defines what the new value is based on the two values of the duplicate key that was encountered. We can choose to simply ignore one of the values and return the other value. But we can also do some computations in this function, for example creating a new value using both values.
Continue reading →
In Clojure we can use the merge
function to merge multiple maps into a single map. If a key is in multiple maps the value of the key merged last will be used in the resulting map. If we want to influence how the value of a duplicate key is set we can use merge-with
. We specify as first argument the function that will be used when the same key is available in multiple maps. The function must accept two arguments, where the the first argument is the value of the key in the first map and the second argument the value of the same key in the following map. The result is assigned to the key in the resulting map. If we pass more than two maps to the merge-with
the function will be called multiple times for a key if it is part of more than two maps.
In the following example we use Clojure core functions and a custom function to merge multiples maps, so we can alter the value for duplicate keys:
Continue reading →
In Java we can write single argument functions that implement the java.util.function.Function
interface. We can combine multiple functions into a new function using the andThen
and compose
methods from the Function
interface. We need to give another function as argument to these methods. When we use the andThen
method the output of the original function will be input of the function passed as argument. With the compose
method our function will get as input the output of the function that is passed as argument. It is important to know the difference, because it can change the result of the function we are composing. The andThen
and compose
methods are also available on the IntUnaryOperator
, LongUnaryOperator
and DoubleUnaryOperator
interface.
In the following example we use both andThen
and compose
to chain together some functions. We can see the result can be different when using andThen
and compose
with the same functions.
Continue reading →
The plugins
section in our Gradle build files can be used to define Gradle plugins we want to use. Gradle can optimize the build process if we use plugins {…}
in our build scripts, so it is a good idea to use it. But there is a restriction if we want to define a version for a plugin inside the plugins
section: the version is a fixed string value. We cannot use a property to set the version inside the plugins
section. We can overcome this by using a pluginsManagement
section in a settings file in the root of our project. Inside the pluginsManagement
section we can use properties to set the version of a plugin we want to use. Once it is defined inside pluginsManagement
we can use it in our project build script without having the specify the version. This allows us to have one place where all plugin versions are defined. We can even use a gradle.properties
file in our project with all plugin versions and use that in pluginsManagement
.
In the following settings file we use pluginsManagement
to use a project property springBootPluginVersion
to set the version to use for the Spring Boot Gradle plugin.
Continue reading →
When we have a multi-module project in Gradle we sometimes want to have dependencies, task configuration and other settings shared between the multiple modules. We can use the subprojects
or allprojects
blocks, but the downside is that it is not clear from the build script of the subproject where the configuration comes from. We must remember it is set from another build script, but there is no reference in the subproject to that connection. It is better to use a plugin with shared configuration and use that plugin in the subprojects. We call this a conventions plugin. This way it is explicitly visible in a subproject that the shared settings come from a plugin. Also it allows Gradle to optimize the build configuration.
Continue reading →
Clojure supports advanced destructure features. In a previous post we learned about destructuring maps, but we can also destructure vectors, list and sequences in Clojure using positional destructuring. We can define symbols for positions in the sequence to assign the value at a certain position to the symbol. The first symbol in the destructure vector gets the value of the first element in the sequence, the second symbol the value of the second element and so on. To get the remaining elements from the sequence without assigning them to specific symbols we can use &
followed by a symbol. Then all remaining elements are assigned as sequence the symbol. Finally we can use :as
to get the original vector, list or sequence.
The folowing examples show several destructure definitions for different type of collections and sequences:
Continue reading →
When we want to assign key values in a map to symbols we can use Clojure’s powerful destructure options. With destructuring a map we can use dense syntax to assign keys to new symbols. For example we can use that in a let
special form to assign symbols, but also for function parameters that are a map. When we use it for function parameters we can immediately assign keys to symbols we want to use in the function. Clojure provides a simple syntax to destructure a key value to a symbol using {symbol key}
syntax. The value of :key
will be assigned to symbol
. We can provide default values if a key is not set in the map using :or
followed by the symbol and default value. This is very useful if we know not all keys in a map will have values. Finally there is a shorthand syntax to assign keys to symbols with the same name as the key: :keys
. We must provide a vector to :keys
with the name of the keys, which will automatically assigned to symbols with the same name. To use this destructuring to its fullest the keys in the map must be keywords. We can use the keywordize-keys
function in the clojure.walk
namespace if we have a map with string keys and we want to transform them to keywords.
In the following example code we see several example of map destructuring:
Continue reading →
With the function distinct
we can remove duplicate elements from a collection. The function returns a lazy sequence when we use a collection argument. Without arguments the function returns a transducer. When we want to remove duplicates and we don’t need the lazy sequence result we could also turn a collection into a set with for example the set
or into
functions.
In the following example we use the distinct
function on several collections.
Continue reading →
The Clojure core namespace contains many functions. One of the functions is the dedupe
function. This function can remove consecutive duplicates from a collection and returns a lazy sequence where only one of the duplicates remain. It will not remove all duplicate elements from the collection, but only when the element is directly followed by a duplicate element. The function returns a transducer when no argument is given.
In the following code sample we use the dedupe
function on several collections:
Continue reading →
Accessing Java from Clojure is easy. With the dot (.
) special form we can invoke for example methods from a Java class or instance. If we want to invoke several methods together where the return value from one method is used to invoke the next method (method chaining) we can use the ..
macro. The macro will expand into a nested expression with the .
forms.
In the following example we see how to use the ..
macro and how we can achieve the same result using nested .
expressions and by using the thread first macro:
Continue reading →