ext.deployit.community.cli.mustachify.collect.Maps2.java Source code

Java tutorial

Introduction

Here is the source code for ext.deployit.community.cli.mustachify.collect.Maps2.java

Source

/*
 * @(#)Maps2.java     Jul 31, 2011
 *
 * Copyright  2010 Andrew Phillips.
 *
 * ====================================================================
 * 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 ext.deployit.community.cli.mustachify.collect;

import static com.google.common.base.Functions.forMap;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.ImmutableMap.copyOf;
import static com.google.common.collect.Maps.filterValues;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Maps.newHashMapWithExpectedSize;
import static com.google.common.collect.Maps.transformValues;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Nonnull;

import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * @author aphillips
 * @since Jul 31, 2011
 *
 */
public class Maps2 {

    /**
     * Constructs a map with the given keys where values are generated by the
     * given function. Supports duplicate and {@code null} values, but
     * {@code null} keys are <em>not</em> allowed.
     * 
     * @param <K>
     *            the type of the keys
     * @param <V>
     *            the type of the values
     * @param keys
     *            the keys to be included in the map. Keys must be non-
     *            <code>null</code>
     * @param valueFunction
     *            the function that produces values for the keys
     * @return a map containing the keys from the given set with values which
     *         are generated from the keys
     * @see Maps#uniqueIndex(Iterable, Function)
     */
    public static @Nonnull <K, V> Map<K, V> fromKeys(@Nonnull Set<K> keys,
            @Nonnull Function<? super K, V> valueFunction) {
        // can't use ImmutableMap.Builder as we're allowing null values
        Map<K, V> result = newHashMapWithExpectedSize(keys.size());
        for (K key : keys) {
            result.put(checkNotNull(key), valueFunction.apply(key));
        }
        return result;
    }

    public static @Nonnull <K1, K2, V> Map<K2, V> transformKeys(@Nonnull Map<K1, V> fromMap,
            Function<? super K1, K2> function) {
        // will catch dups
        Map<K2, K1> newKeys = Maps.uniqueIndex(fromMap.keySet(), function);
        // replace each old key with its value using a lookup in the input map
        return transformValues(newKeys, forMap(fromMap));
    }

    /**
     * Constructs a map that contains all unique, non-<code>null</code> values
     * from the input map as keys. The value for each key in the returned map is
     * the set of keys from the input map that contained that value (i.e. the
     * key in the returned map).
     * <p>
     * Keys in the input map with {@code null} values are <u>omitted</u> from the
     * returned map. 
     * <p>
     * This operation is similar to the <em>reduce</em> step in a map-reduce algorithm, 
     * hence the name.
     * <p>
     * Examples:
     * <ul>
     * <li>{"foo": 10, "bar": 10, "baz": 20} -> {10: {"foo", "bar"}, 20: {"baz"}}
     * <li>{"foo": 10, "bar": 15, "baz": null} -> {10: {"foo"}, 15: {"bar"}}
     * </ul>
     * 
     * @param <K>
     *            the type of the keys
     * @param <V>
     *            the type of the values
     * @param fromMap
     *            the map containing the value/key pairs to be inverted
     * @return a map containing, for every unique (according to
     *         {@link Object#equals(Object) equals} value, an entry with that
     *         value as the key and a set of all keys from the input map as the
     *         value. All entries of the input map that have {@code null} values
     *         are <u>omitted</u> from the returned map.
     */
    public static @Nonnull <K, V> Map<V, Set<K>> reduce(@Nonnull Map<K, V> fromMap) {
        Map<V, Set<K>> inProgress = newHashMap();
        for (Entry<K, V> entry : filterValues(fromMap, notNull()).entrySet()) {
            V value = entry.getValue();
            if (!inProgress.containsKey(value)) {
                inProgress.put(value, Sets.<K>newHashSet());
            }
            inProgress.get(value).add(entry.getKey());
        }
        return copyOf(inProgress);
    }

}