
com.cinchapi.common.collect.AnyMaps Maven / Gradle / Ivy
Show all versions of accent4j Show documentation
/*
* Copyright (c) 2016 Cinchapi Inc.
*
* 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 com.cinchapi.common.collect;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import com.cinchapi.common.base.AnyStrings;
import com.cinchapi.common.base.Array;
import com.cinchapi.common.base.Verify;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Ints;
/**
* A collection of functions that efficiently operate on {@link Map maps}.
*
* @author Jeff Nelson
*/
public final class AnyMaps {
/**
* Return a {@link Map} that contains the specified
* {@code key}/{@code value} pair.
*
* @param key
* @param value
* @return the {@link Map}
*/
public static Map create(K key, V value) {
LinkedHashMap map = Maps.newLinkedHashMap();
map.put(key, value);
return map;
}
/**
* Explode a "flat" map that contains navigable keys to a nested structure
* that can be traversed using the {@link #navigate(String, Map)} method.
*
* For example, if the provided {@code map} has a key {@code foo.bar.0} that
* maps to the value "baz", this method will return a map that contains a
* mapping from {@code foo} to a mapping from {@code bar} to a list that
* contains the value "baz" at position 0.
*
*
* The map returned from this method is navigable such that a query for any
* of the keys in the original {@code map} will return the same associated
* value from the {@link #navigate(String, Map)} method. The advantage of
* exploding a map is that it makes it possible to fetch nested inner
* structures from a navigable query on one of the parent keys (e.g. the
* example above would return a map if one were to navigate for "foo")
*
*
* @param map
* @return a nested map
* @deprecated in favor of the {@link Association} framework. Create an
* {@link Association} using {@link Association#of(Map)} with a
* "flat" map. The map will be exploded, implicitly and
* traversable using the {@link Association#fetch(String)}
* method in a manner that is similar to the way the
* {@link #navigate(String, Map)} method worked.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Deprecated
public static Map explode(Map map) {
Map exploded = Maps.newLinkedHashMap();
map.forEach((key, value) -> {
String[] components = key.split("\\.");
String[] reversed = Array.reverse(components);
Verify.thatArgument(Ints.tryParse(components[0]) == null,
"The map cannot contain keys that start with a numeric component. "
+ "'{}' is an invalid key.",
key);
String originalKey = key;
try {
for (String component : reversed) {
key = component;
components = Arrays.copyOf(components,
components.length - 1);
String path = String.join(".", components);
Object container;
Integer index;
container = navigate(path, exploded);
if((index = Ints.tryParse(component)) != null) {
if(container == null) {
container = Lists.newArrayList();
}
List list = (List) container;
for (int i = list.size(); i < index; ++i) { // Pad the
// list, if
// necessary
list.add(null);
}
if(index < list.size()) {
// This means we are modifying an existing item in
// the list, so we must be sure to upsert instead of
// adding and shifting elements around.
list.set(index, value);
}
else {
list.add(index, value);
}
}
else {
if(container == null) {
container = Maps.newLinkedHashMap();
}
((Map) container).put(component, value);
}
value = container;
}
exploded.putAll((Map) value);
}
catch (ClassCastException e) {
throw new IllegalArgumentException(AnyStrings.format(
"Cannot explode '{}' because the path leads to a different "
+ "type tree than a previously exploded key.",
originalKey));
}
});
return exploded;
}
/**
* Merge the data {@code from} one {@link Map} {@code into} another one.
*
* @param into the Map to merge into
* @param from the Map to merge from
* @return the merged {@link Map}
*/
public static Map merge(Map into,
Map from) {
return merge(into, from, MergeStrategies::concat);
}
/**
* Merge the data {@code from} one {@link Map} {@code into} another one
* using the provided merge {@code strategy}.
*
* @param into the Map to merge into
* @param from the Map to merge from
* @param strategy a {@link MergeStrategies merge strategy} to use when a
* key in the {@code from} map already exists in the the
* {@code into} map
* @return the merged {@link Map}
*/
public static Map merge(Map into,
Map from,
BiFunction