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

ma.vi.base.collections.Maps Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2018 Vikash Madhow
 */

package ma.vi.base.collections;

import ma.vi.base.tuple.T2;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkState;

/**
 * Utilities to work with Maps.
 *
 * @author Vikash Madhow ([email protected])
 */
public class Maps {
  /**
   * Given a root map and a set of n objects Obj(1) to Obj(n), a multiLevelGet
   * will get the first object from the root map. This first object is expected
   * to be a map or null. If it is a map, this map is in turn used to
   * get Obj(2) and so on until Obj(n-1). The map for Obj(n-1) is then used
   * to get Obj(n) and whatever b is there is returned. If any level
   * returns null, the whole method returns null.
   *
   * @param map     Root map
   * @param objects The objects at each level in proper order.
   */
  public static  T multiLevelGet(Map map, Object... objects) {
    for (int i = 0; i < objects.length - 1; i++) {
      map = (Map) map.get(objects[i]);
      if (map == null) {
        return null;
      }
    }
    return (T) map.get(objects[objects.length - 1]);
  }

  /**
   * Given a root map and a set of n objects O(1) to O(n), a multiLevelPut
   * will first get O(1) from the root map which is expected to also be a
   * map. If this is null, a HashMap is created and associated to O(1) in the
   * root map. This process is repeated up to O(n-2), the map for which is
   * used to associate O(n-1) to O(n).
   *
   * @param map     The root map
   * @param objects The objects at each level in proper order.
   * @return The previous b associated with O(n-1) if any or null.
   * Null can also indicate that O(n-1) was previously associated
   * to the null b.
   */
  public static Object multiLevelPut(Map map, Object... objects) {
    for (int i = 0; i < objects.length - 2; i++) {
      Map levelMap = (Map) map.get(objects[i]);
      if (levelMap == null) {
        levelMap = new HashMap();
        map.put(objects[i], levelMap);
      }
      map = levelMap;
    }
    return map.put(objects[objects.length - 2], objects[objects.length - 1]);
  }

  /**
   * Create a hashmap from the array of pairs.
   */
  public static  Map of(T2... pairs) {
    return put(new HashMap<>(), pairs);
  }

  /**
   * Adds all the pairs to the map and return it.
   */
  public static  Map put(Map map, T2... pairs) {
    for (T2 t2 : pairs) {
      map.put(t2.a, t2.b);
    }
    return map;
  }

  public static  Map put(Map map, Map values) {
    for (Map.Entry t2 : values.entrySet()) {
      map.put(t2.getKey(), t2.getValue());
    }
    return map;
  }

  /**
   * Returns a string representation of the map.
   */
  public static String toString(Map map) {
    if (map == null) {
      return "";
    } else {
      return map.entrySet().stream()
          .map(e -> String.valueOf(e.getKey()) + ": " + String.valueOf(e.getValue()))
          .collect(Collectors.joining(", ", "{", "}"));
    }
  }

  /**
   * Returns the inverse of a map, i.e, for every mapping a->b in the map, the
   * return map will contain the mapping b->a. Inverse can only exist for one-to-one
   * maps, i.e., if the original maps contains two mappings from different keys to the
   * same b (a->b, c->b), the inverse will only contain one such mapping
   * since the map cannot contain the same keys twice. Which mapping is present in the inverse
   * depends on the type of the source map and the natural order of its keys.
   */
  public static  Map invert(Map map) {
    if (map == null) {
      return null;
    }
    Map inv = new HashMap<>();
    for (Map.Entry entry : map.entrySet()) {
      A key = entry.getKey();
      B value = entry.getValue();
      checkState(!inv.containsKey(value), "Map is not invertible as value %s is mapped to " +
          "both %s and %s", value, key, inv.get(value));
      inv.put(value, key);
    }
    return inv;
  }

  private Maps() {
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy