All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aksw.commons.collections.MapUtils Maven / Gradle / Ivy

There is a newer version: 0.9.9
Show newest version
package org.aksw.commons.collections;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;

import com.google.common.base.Objects;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

/**
 * Created by IntelliJ IDEA.
 * User: raven
 * Date: 4/22/11
 * Time: 2:36 PM
 * To change this template use File | Settings | File Templates.
 */
public class MapUtils {

    public static  int addWithIntegerAutoIncrement(Map map, T key) {
        int result = map.computeIfAbsent(key, (k) -> map.size());
        return result;
    }

    public static  long addWithLongAutoIncrement(Map map, T key) {
        long result = map.computeIfAbsent(key, (k) -> (long)map.size());
        return result;
    }

    public static void removeAll(Map map, Iterable items) {
        for(Object o : items) {
            map.remove(o);
        }
    }

    /**
     * Set the same value for a given set of keys
     *
     * @param map
     * @param keys
     * @param value
     */
    public static  void putForAll(Map map, Iterable keys, V value) {
        for(K key : keys) {
            map.put(key, value);
        }
    }


    /**
     * Compatible means that merging the two maps would not result in the same
     * key being mapped to distinct values.
     *
     * Or put differently:
     * The union of the two maps retains a functional mapping.
     *
     * @param 
     * @param 
     * @param a
     * @param b
     * @return
     */
    public static  boolean isCompatible(Map a, Map b) {
        Set commonKeys = Sets.intersection(a.keySet(), b.keySet());
        boolean result = isCompatible(commonKeys, a, b);
        return result;
    }

    public static  boolean isCompatible(Set keysToTest, Map a, Map b) {
        boolean result = true;
        for(K key : keysToTest) {
            V av = a.get(key);
            V bv = b.get(key);
            result = Objects.equal(av, bv);
            if(!result) {
                break;
            }
        }

        return result;
    }

    // A version written before guava - Sets.intersection can make sure that any tested key is actually contained in the keyset.
    @Deprecated
    public static  boolean isPartiallyCompatible(Map a, Map b) {
        boolean result = isCompatible(a, b);
        return result;
    }

    public static  Multimap reverse(Map map) {
        Multimap result = HashMultimap.create();

        for(Map.Entry entry : map.entrySet()) {
            result.put(entry.getValue(), entry.getKey());
        }

        return result;
    }

    public static  V getOrElse(Map map, K key, V elze)
    {
        if(map.containsKey(key)) {
            return map.get(key);
        }

        return elze;
    }

      public static  Map createChainMap(Map a, Map b) {
        Map result = new HashMap();

        for(Map.Entry entry : a.entrySet()) {
            if(b.containsKey(entry.getValue())) {
                result.put(entry.getKey(), b.get(entry.getValue()));
            }
        }

        return result;
    }

    public static  V getOrCreate(Map map, K key, Class clazz, Object ... ctorArgs)
    {
        V result = map.get(key);
        if(result == null) {
            // TODO Invoke the correct constructor based on the arguments
            //Class[] classes = new Class[ctorArgs.length];
            //clazz.getConstructor();


            if(ctorArgs.length > 0) {
                throw new RuntimeException("Constructor arguments not supported yet");
            } else  {
                try {
                    result = (V)clazz.newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            map.put(key, result);
        }

        return result;
    }

    /**
         * Find a mapping of variables from cand to query, such that the pattern of
         * cand becomes a subset of that of query
         *
         * null if no mapping can be established
         *
         * @param query
         * @param cand
         * @return
         */
    //
    //    public Iterator> computeVarMapQuadBased(PatternSummary query, PatternSummary cand, Set> candVarCombos) {
    //
    //        IBiSetMultimap>, Quad> cnfToCandQuad = cand.getQuadToCnf().getInverse();
    //        IBiSetMultimap>, Quad> cnfToQueryQuad = query.getQuadToCnf().getInverse();
    //
    //        //IBiSetMultimap candToQuery = new BiHashMultimap();
    ////        Map>, QuadGroup> cnfToQuadGroup = new HashMap>, QuadGroup>();
    //        List quadGroups = new ArrayList();
    //        for(Entry>, Collection> entry : cnfToCandQuad.asMap().entrySet()) {
    //
    //            //Quad candQuad = entry.getKey();
    //            Set> cnf = entry.getKey();
    //
    //            Collection candQuads = entry.getValue();
    //            Collection queryQuads = cnfToQueryQuad.get(cnf);
    //
    //            if(queryQuads.isEmpty()) {
    //                return Collections.>emptySet().iterator();
    //            }
    //
    //            QuadGroup quadGroup = new QuadGroup(candQuads, queryQuads);
    //            quadGroups.add(quadGroup);
    //
    //            // TODO We now have grouped together quad having the same constraint summary
    //            // Can we derive some additional constraints form the var occurrences?
    //
    //
    ////            SetMultimap summaryToQuadsCand = quadJoinSummary(new ArrayList(candQuads));
    ////            System.out.println("JoinSummaryCand: " + summaryToQuadsCand);
    ////
    ////            SetMultimap summaryToQuadsQuery = quadJoinSummary(new ArrayList(queryQuads));
    ////            System.out.println("JoinSummaryQuery: " + summaryToQuadsQuery);
    ////
    ////            for(Entry> candEntry : summaryToQuadsCand.asMap().entrySet()) {
    ////                queryQuads = summaryToQuadsQuery.get(candEntry.getKey());
    ////
    ////                // TODO What if the mapping is empty?
    ////                QuadGroup group = new QuadGroup(candEntry.getValue(), queryQuads);
    ////
    ////                cnfToQuadGroup.put(cnf, group);
    ////            }
    //        }
    //
    //        // Figure out which quads have ambiguous mappings
    //
    ////        for(Entry>, QuadGroup>entry : cnfToQuadGroup.entrySet()) {
    ////            System.out.println(entry.getKey() + ": " + entry.getValue());
    ////        }
    //
    //        // Order the quad groups by number of candidates - least number of candidates first
    ////        List quadGroups = new ArrayList(cnfToQuadGroup.values());
    //        Collections.sort(quadGroups, new Comparator() {
    //            @Override
    //            public int compare(QuadGroup a, QuadGroup b) {
    //                int i = getNumMatches(a);
    //                int j = getNumMatches(b);
    //                int r = j - i;
    //                return r;
    //            }
    //        });
    //
    //
    //        List>> cartesian = new ArrayList>>(quadGroups.size());
    //
    //        // TODO Somehow obtain a base mapping
    //        Map baseMapping = Collections.emptyMap();
    //
    //        for(QuadGroup quadGroup : quadGroups) {
    //            Iterable> it = IterableVarMapQuadGroup.create(quadGroup, baseMapping);
    //            cartesian.add(it);
    //        }
    //
    //        CartesianProduct> cart = new CartesianProduct>(cartesian);
    //
    //        Iterator> result = new IteratorVarMapQuadGroups(cart.iterator());
    //
    //        return result;
    //    }

        public static > R mergeCompatible(Iterable> maps, Supplier resultSupplier) {
            R result = resultSupplier.get();

            for(Map map : maps) {
                if(isCompatible(map, result)) {
                    result.putAll(map);
                } else {
                    result = null;
                    break;
                }
            }

            return result;
        }

//    public static > R mergeCompatible(Map a, Map b, Supplier resultSupplier) {
//        R result = mergeCompatible(Arrays.asList(a, b), resultSupplier);
//        return result;
//    }

    public static > R mergeCompatible(Map a, Map b, Supplier resultSupplier) {
        R result = mergeCompatible(Arrays.asList(a, b), resultSupplier);
        return result;
    }



    /*
     * Lazy map views based on a comment at https://github.com/google/guava/issues/912
     */

    /**
     * Returns a view of the union of two maps.
     *
     * For all keys k, if either map contains a value for k, the returned map contains that value. If both maps
     * contain a value for the same key, this map contains the value in the second of the two provided maps.
     */
    public static  Map union(Map a, Map b) {
        return union(a, b, (v1, v2) -> v2);
    }

    /**
     * Returns a view of the union of two maps.
     *
     * For all keys k, if either map contains a value for k, the returned map contains that value. If both maps
     * contain a value for the same key, the conflict is resolved with the provided function.
     */
    public static  Map union(
            Map a,
            Map b,
            BinaryOperator conflictHandler) {
        return Maps.asMap(Sets.union(a.keySet(), b.keySet()),
                (K k) -> {
                    V r;
                    if (!a.containsKey(k)) {
                        r = b.get(k);
                    } else if (!b.containsKey(k)) {
                        r = a.get(k);
                    } else {
                        V v1 = a.get(k);
                        V v2 = b.get(k);
                        r = conflictHandler.apply(v1, v2);
                    }
                    return r;
                });
    }

    /**
     * Returns a view of the map where all keys present in 'deletions' are hidden
     */
    public static  Map difference(
            Map map,
            Set deletions) {
        return Maps.asMap(Sets.difference(map.keySet(), deletions), map::get);
    }


    public static  Map index(Collection keys, Function fn) {
        Map result = index(keys, fn, new HashMap<>());
        return result;
    }

    public static  Map indexIdentity(Collection keys, Function fn) {
        Map result = index(keys, fn, new IdentityHashMap<>());
        return result;
    }

    public static  Map index(Collection keys, Function fn, Map result) {
        for(K key : keys) {
            V value = fn.apply(key);
            result.put(key, value);
        }
        return result;
    }

    public static  Map transformKeys(Map original,
            Function map) {
        Map result = new HashMap<>();

        for (Entry entry : original.entrySet()) {
            K i = entry.getKey();
            K o = map.apply(i);
            if (o == null) {
                o = i;
            }

            result.put(o, entry.getValue());
        }

        return result;
    }

    /** Put a key value pair. Removes the key if the value is null. Returns the prior value (null if there was none). */
    public static  V putWithRemoveOnNull(Map map, K key, V value) {
        V result;
        if (value == null) {
            result = map.get(key);
            map.remove(key);
        } else {
            result = map.put(key, value);
        }
        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy