io.atlassian.fugue.extras.ImmutableMaps Maven / Gradle / Ivy
/*
Copyright 2011 Atlassian
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package io.atlassian.fugue.extras;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import io.atlassian.fugue.Functions;
import io.atlassian.fugue.Iterables;
import io.atlassian.fugue.Option;
import io.atlassian.fugue.Options;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* Provides some utility methods to convert Iterables to ImmutableMap, and to
* transform Maps.
*
* @since 2.0
*/
public class ImmutableMaps {
// /CLOVER:OFF
private ImmutableMaps() {}
// /CLOVER:ON
/**
* Returns a function that takes a key of type K and a value of type V and
* returns a Map entry.
*
* @param the key type
* @param the value type
* @return a function that takes a K and a V and return the corresponding Map
* entry
*/
public static BiFunction> mapEntry() {
return Maps::immutableEntry;
}
/**
* Builds an immutable map from the given iterable of
* {@link java.util.Map.Entry}.
*
* Any null
entries will be filtered out. Additionally, any
* entries containing null
key or value will also be filtered
* out. If multiple entries return the same key,
* {@link java.lang.IllegalArgumentException} will be thrown.
*
* @param the key type
* @param the value type
* @param from the iterable we use as the source
* @return the transformed map
*/
public static ImmutableMap toMap(Iterable> from) {
ImmutableMap.Builder mapBuilder = ImmutableMap.builder();
for (Map.Entry entry : from) {
if (entry != null) {
K key = entry.getKey();
V value = entry.getValue();
if (key != null && value != null) {
mapBuilder.put(key, value);
}
}
}
return mapBuilder.build();
}
/**
* Builds an immutable map from the given iterable, with key derived from the
* application of the iterable to the keyTransformer, and value derived from
* the application of the iterable to the valueTransformer.
*
* null
value is allowed and will be passed to the keyTransformer
* and valueTransformer. However, if either the keyTransformer or the
* valueTransformer returns null
for an entry, the entry is
* ignored. If keyTransformer returns the same key for multiple entries,
* {@link java.lang.IllegalArgumentException} will be thrown.
*
* @param the input type
* @param the key type
* @param the value type
* @param from the iterable we use as the source
* @param keyTransformer transform keys
* @param valueTransformer transform values
* @return the transformed map
*/
public static ImmutableMap toMap(Iterable from, final Function super T, ? extends K> keyTransformer,
final Function super T, ? extends V> valueTransformer) {
return toMap(com.google.common.collect.Iterables.transform(from,
entry -> Maps.immutableEntry(keyTransformer.apply(entry), valueTransformer.apply(entry))));
}
/**
* Builds an immutable map that is keyed by the result of applying
* keyTransformer to each element of the given iterable of values.
*
* null
value is allowed but will be ignored. If keyTransformer
* returns the same key for multiple entries,
* {@link java.lang.IllegalArgumentException} will be thrown.
*
* @param the key type
* @param the value type
* @param from the iterable we use as the source
* @param keyTransformer transform keys
* @return the transformed map
*/
public static ImmutableMap mapBy(Iterable from, final Function super V, ? extends K> keyTransformer) {
return toMap(from, keyTransformer, Functions. identity());
}
/**
* Builds an immutable map from the given iterable and compute the value by
* applying the valueTransformer.
*
* null
value is allowed but will be ignored. If there are
* duplicate entries in the iterable,
* {@link java.lang.IllegalArgumentException} will be thrown.
*
* @param the key type
* @param the value type
* @param from the iterable we use as the source
* @param valueTransformer transform values
* @return the transformed map
*/
public static ImmutableMap mapTo(Iterable from, final Function super K, ? extends V> valueTransformer) {
return toMap(from, Functions. identity(), valueTransformer);
}
/**
* Returns an immutable map that applies function to each entry of
* {@code fromMap}. If null
is returned by the function for any
* entry, or if an entry returned by the function contains a null
* key or value, that entry is discarded in the result. If the function
* returns entries with the same key for multiple entries,
* {@link java.lang.IllegalArgumentException} will be thrown.
*
* @param the input key type
* @param the output key type
* @param the input value type
* @param the output value type
* @param from the map we use as the source
* @param function transform keys and values
* @return the transformed map
*/
public static ImmutableMap transform(Map from, Function, Map.Entry> function) {
return toMap(com.google.common.collect.Iterables.transform(from.entrySet(), function::apply));
}
/**
* Returns an immutable map that applies the keyTransformer and
* valueTransformer functions to each entry of {@code fromMap}. If for any
* entry, a null
key or value is returned, that entry is
* discarded in the result. If the keyTransformer function returns the same
* key for multiple entries, {@link java.lang.IllegalArgumentException} will
* be thrown.
*
* @param the input key type
* @param the output key type
* @param the input value type
* @param the output value type
* @param from the map we use as the source
* @param keyTransformer transform keys
* @param valueTransformer transform values
* @return the transformed map
*/
public static ImmutableMap transform(Map from, final Function super K1, ? extends K2> keyTransformer,
final Function super V1, ? extends V2> valueTransformer) {
return toMap(com.google.common.collect.Iterables.transform(from.entrySet(),
entry -> Maps.immutableEntry(keyTransformer.apply(entry.getKey()), valueTransformer.apply(entry.getValue()))));
}
/**
* Returns an immutable map that applies keyTransformer to the key of each
* entry of the source map. If null
is returned by the
* keyTransformer for any entry, that entry is discarded in the result. If an
* entry contains a null
value, it will also be discarded in the
* result. If the {@code function} returns the same result key for multiple
* keys, {@link java.lang.IllegalArgumentException} will be thrown.
*
* @param the input key type
* @param the output key type
* @param the value type
* @param from the map we use as the source
* @param keyTransformer transform keys
* @return the transformed map
*/
public static ImmutableMap transformKey(Map from, final Function super K1, ? extends K2> keyTransformer) {
return transform(from, keyTransformer, Functions. identity());
}
/**
* Returns an immutable map that applies valueTransformer to the value of each
* entry of the source map. If null
is returned by the
* valueTransformer for any entry, that entry is discarded in the result. If
* an entry contains a null
key, it will also be discarded in the
* result.
*
* @param the key type
* @param the input value type
* @param the output value type
* @param from the iterable we use as the source
* @param valueTransformer transform values
* @return the transformed map
*/
public static ImmutableMap transformValue(Map from, final Function super V1, ? extends V2> valueTransformer) {
return transform(from, Functions. identity(), valueTransformer);
}
/**
* Filters and maps (aka transforms) the source map.
*
* Applies the given partial function to each entry of the unfiltered map. If
* the application returns none, the entry will be left out; otherwise, the
* transformed entry contained in the Option will be added to the result map.
*
* @param the input key type
* @param the output key type
* @param the input value type
* @param the output value type
* @param from the iterable we use as the source
* @param partial transform and select entries
* @return the transformed map
*/
public static ImmutableMap collect(Map from, Function, Option>> partial) {
return toMap(Iterables.collect(from.entrySet(), partial));
}
/**
* Filters and maps (aka transforms) the source map.
*
* Applies the given partial key function and partial value function to the
* key and value of each entry of the unfiltered map. If either of the
* application returns none, the entry will be left out; otherwise, an entry
* of transformed key and transformed value contained in the options will be
* added to the result map.
*
* @param the input key type
* @param the output key type
* @param the input value type
* @param the output value type
* @param from the iterable we use as the source
* @param keyPartial transform and collect keys
* @param valuePartial transform and collect values
* @return the transformed map
*/
public static ImmutableMap collect(Map from, final Function super K1, Option> keyPartial,
final Function super V1, Option> valuePartial) {
return collect(from, input -> {
Option ok = keyPartial.apply(input.getKey());
Option ov = valuePartial.apply(input.getValue());
return Options.lift2(ImmutableMaps. mapEntry()).apply(ok, ov);
});
}
/**
* Filters and maps (aka transforms) the source map.
*
* Applies the given partial key function to the key of each entry of the
* unfiltered map. If the application returns none, the entry will be left
* out; otherwise, an entry of transformed key contained in the option and the
* original value will be added to the result map.
*
* @param the input key type
* @param the output key type
* @param the value type
* @param from the iterable we use as the source
* @param keyPartial transform and collect keys
* @return the transformed map
*/
public static ImmutableMap collectByKey(Map from, final Function super K1, Option> keyPartial) {
return collect(from, keyPartial, Options.toOption());
}
/**
* Filters and maps (aka transforms) the source map.
*
* Applies the given partial value function to the value of each entry of the
* unfiltered map. If the application returns none, the entry will be left
* out; otherwise, an entry of the original key and the transformed key
* contained in the option will be added to the result map.
*
* @param the key type
* @param the input value type
* @param the output value type
* @param from the iterable we use as the source
* @param valuePartial transform and collect values
* @return the transformed map
*/
public static ImmutableMap collectByValue(Map from, final Function super V1, Option> valuePartial) {
return collect(from, Options.toOption(), valuePartial);
}
}