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

org.cp.elements.util.MapUtils Maven / Gradle / Ivy

Go to download

Java Simplified. Extensions and Useful Constructs for the Java Platform. Codeprimate Elements (a.k.a. cp-elements) is a Java library and micro-framework used to simplify the development of software applications written in Java. Elements packages several APIs into one library in order to address various application concerns and aspects of software design and development collectively and conveniently. Elements is a highly simple, yet robust and proven library built on solid OO principles, software design patterns and best practices to effectively solve common and reoccurring problems in software development.

There is a newer version: 2.0.0-M1
Show newest version
/*
 * Copyright 2016 Author or Authors.
 *
 * 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 org.cp.elements.util;

import static org.cp.elements.util.ArrayUtils.nullSafeArray;
import static org.cp.elements.util.ArrayUtils.nullSafeLength;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.cp.elements.lang.Assert;
import org.cp.elements.lang.Constants;
import org.cp.elements.lang.Filter;
import org.cp.elements.lang.FilteringTransformer;
import org.cp.elements.lang.StringUtils;
import org.cp.elements.lang.Transformer;
import org.cp.elements.lang.annotation.NullSafe;

/**
 * The MapUtils class provides utility methods for working with the Java Collections Framework and specifically
 * the {@link Map} class.
 *
 * @author John J. Blum
 * @see java.util.Collections
 * @see java.util.Map
 * @see java.util.stream.Collectors
 * @since 1.0.0
 */
@SuppressWarnings("unused")
public abstract class MapUtils {

  /**
   * Determines the number of entries (key-value pairs) in the {@link Map}.  This method is null-safe and will
   * return 0 if the {@link Map} is null or empty.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map {@link Map} to evaluate.
   * @return the size, or number of elements in the {@link Map}, returning 0 if the {@link Map} is null or empty.
   */
  @NullSafe
  public static  int count(Map map) {
    return (map != null ? map.size() : 0);
  }

  /**
   * Counts the number of entries (key-value pairs) in the {@link Map} accepted by the {@link Filter}.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map {@link Map} to evaluate.
   * @param filter {@link Filter} used to determine the number of entries in the {@link Map} accepted by
   * the {@link Filter}.
   * @return an integer value indicating the number of entries in the {@link Map} accepted by the {@link Filter}.
   * @throws IllegalArgumentException if {@link Filter} is null.
   * @see org.cp.elements.lang.Filter
   * @see java.util.Map
   */
  public static  long count(Map map, Filter> filter) {

    Assert.notNull(filter, "Filter is required");

    return nullSafeMap(map).entrySet().stream().filter(filter::accept).count();
  }

  /**
   * Returns a filtered {@link Map} containing only the key-value entries from the given {@link Map} that are accepted
   * by the {@link Filter}.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map {@link Map} to filter.
   * @param filter {@link Filter} used to filter the {@link Map}.
   * @return a filtered {@link Map} containing only the key-value entries from the given {@link Map} }accepted by
   * the {@link Filter}.
   * @throws IllegalArgumentException if either the {@link Map} or {@link Filter} are null.
   * @see org.cp.elements.lang.Filter
   * @see java.util.Map
   */
  public static  Map filter(Map map, Filter> filter) {

    Assert.notNull(map, "Map is required");
    Assert.notNull(filter, "Filter is required");

    return map.entrySet().stream().filter(filter::accept)
      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  }

  /**
   * Filters and transform the entries in the given {@link Map} using the provided {@link FilteringTransformer}.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map {@link Map} to filter and transform.
   * @param filteringTransformer {@link FilteringTransformer} used to filter and transform the given {@link Map}.
   * @return a filtered, transformed {@link Map} of entries from the given {@link Map}.
   * @throws IllegalArgumentException if the {@link Map} or {@link FilteringTransformer} are null.
   * @see org.cp.elements.lang.FilteringTransformer
   * @see java.util.Map
   * @see #filter(Map, Filter)
   * @see #transform(Map, Transformer)
   */
  public static  Map filterAndTransform(Map map,
      FilteringTransformer> filteringTransformer) {

    Assert.notNull(map, "Map is required");
    Assert.notNull(filteringTransformer, "FilteringTransformer is required");

    return map.entrySet().stream().filter(filteringTransformer::accept).map(filteringTransformer::transform)
      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  }

  /**
   * Finds all key-value entries from the given {@link Map} accepted by the {@link Filter}.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map {@link Map} to search.
   * @param filter {@link Filter} used to find matching key-value entries from the {@link Map}.
   * @return a new {@link Map} containing key-value entries from the given {@link Map} accepted by the {@link Filter}.
   * @throws IllegalArgumentException if either the {@link Map} or {@link Filter} are null.
   * @see org.cp.elements.lang.Filter
   * @see java.util.Map
   * @see #filter(Map, Filter)
   */
  public static  Map findAll(Map map, Filter> filter) {
    return filter(map, filter);
  }

  /**
   * Converts the given associative array into a {@link Map}.
   *
   * @param associativeArray associate array to convert into a {@link Map}.
   * @return a {@link Map} populated with the key/value pairs in the associate array.
   * @see ArrayUtils#nullSafeArray(Object[], Class)
   * @see ArrayUtils#nullSafeLength(Object[])
   */
  @NullSafe
  public static Map fromAssociativeArray(String[] associativeArray) {

    Map map = new HashMap<>(nullSafeLength(associativeArray));

    int index = 0;

    for (String element : nullSafeArray(associativeArray, String.class)) {

      Assert.hasText(element, "Entry [%s] at index [%d] must be specified", element, index);

      String[] entry = element.split("=");

      Assert.isTrue(entry.length == 2, "Entry [%s] at index [%d] must have both a key and a value", element, index);

      String key = StringUtils.trim(entry[0]);
      String value = StringUtils.trim(entry[1]);

      map.put(key, value);
      index++;
    }

    return map;
  }

  /**
   * Determines whether the given {@link Map} is empty.  A {@link Map} is empty if it contains no entries or is null.
   *
   * @param map {@link Map} to evaluate.
   * @return a boolean value indicating whether the {@link Map} is empty.
   * @see java.util.Map#isEmpty()
   * @see #isNotEmpty(Map)
   */
  @NullSafe
  public static boolean isEmpty(Map map) {
    return (map == null || map.isEmpty());
  }

  /**
   * Determines whether the given {@link Map} is not empty.  A {@link Map} is considered non-empty if it is not null
   * and contains at least 1 entry.
   *
   * @param map {@link Map} to evaluate.
   * @return a boolean value indicating whether the {@link Map} is not empty.
   * @see java.util.Map#isEmpty()
   * @see #isEmpty(Map)
   */
  @NullSafe
  public static boolean isNotEmpty(Map map) {
    return !isEmpty(map);
  }

  /**
   * Null-safe operation to determine whether the size of the given {@link Map} is 1.
   *
   * @param map {@link Map} to evaluate.
   * @return a boolean value indicating whether the size of the given {@link Map} is 1.
   * @see #nullSafeMap(Map)
   * @see java.util.Map
   */
  @NullSafe
  public static boolean isSizeOne(Map map) {
    return (size(map) == 1);
  }

  /**
   * Constructs a new instance of {@link Map.Entry} initialized with the given key and value.
   *
   * @param  {@link Class} type of the key.
   * @param  {@link Class} type of the value.
   * @param key key of the new {@link Map.Entry}.
   * @param value value of the new {@link Map.Entry}.
   * @return a new {@link Map.Entry} initialized with the given key and value.
   * @see java.util.Map.Entry
   */
  public static  Map.Entry newMapEntry(K key, V value) {

    return new Map.Entry() {

      @Override
      public K getKey() {
        return key;
      }

      @Override
      public V getValue() {
        return value;
      }

      @Override
      public V setValue(V value) {
        throw new UnsupportedOperationException(Constants.OPERATION_NOT_SUPPORTED);
      }
    };
  }

  /**
   * Returns the given {@link Map} if not null or an empty {@link Map}.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map the {@link Map} to evaluate.
   * @return the given {@link Map} if not null or an empty {@link Map} otherwise.
   * @see java.util.Collections#emptyMap()
   * @see java.util.Map
   */
  @NullSafe
  public static  Map nullSafeMap(Map map) {
    return (map != null ? map : Collections.emptyMap());
  }

  /**
   * Determines the size, or number of entries in the {@link Map}, returning 0 if the {@link Map} is null or empty.
   *
   * @param map {@link Map} to evaluate.
   * @return an integer value indicating the size or number of entries in the {@link Map}.
   * @see java.util.Map#size()
   * @see #count(Map)
   */
  @NullSafe
  public static int size(Map map) {
    return count(map);
  }

  /**
   * Converts the given {@link Map} into an associative array.
   *
   * The associative array takes the form of [key1=value1, key2=value2, ..., keyN=valueN].
   *
   * @param map {@link Map} to convert into an associative array.
   * @return an associative {@link String} array containing the keys and values
   * from the given {@link Map}.
   * @see java.util.Map
   * @see #size(Map)
   * @see #nullSafeMap(Map)
   */
  @NullSafe
  public static String[] toAssociativeArray(Map map) {

    List list = new ArrayList<>(size(map));

    for (Map.Entry entry : nullSafeMap(map).entrySet()) {
      list.add(String.format("%1$s=%2$s", String.valueOf(entry.getKey()), entry.getValue()));
    }

    return list.toArray(new String[list.size()]);
  }

  /**
   * Prints the given {@link Map} as a {@link String}.
   *
   * @param map {@link Map} to print as a {@link String}.
   * @return a {@link String} representation of the given {@link Map}.
   * @see java.lang.String
   * @see java.util.Map
   */
  @NullSafe
  public static String toString(Map map) {

    StringBuilder builder = new StringBuilder("[");

    int count = 0;

    map = new TreeMap(nullSafeMap(map));

    for (Map.Entry entry : map.entrySet()) {
      builder.append("\n\t");
      builder.append(entry.getKey());
      builder.append(" = ");
      builder.append(entry.getValue());
      builder.append(++count == map.size() ? "\n" : ",");
    }

    builder.append("]");

    return builder.toString();
  }

  /**
   * Transforms the values of the given Map with the specified Transformer.
   *
   * @param  Class type of the key.
   * @param  Class type of the value.
   * @param map {@link Map} to transform.
   * @param transformer {@link Transformer} used to transform the {@link Map}'s values.
   * @return a new {@link Map} from the given {@link Map} transformed by the {@link Transformer}.
   * @throws IllegalArgumentException if either the {@link Map} or {@link Transformer} are null.
   * @see org.cp.elements.lang.Transformer
   * @see java.util.Map
   */
  public static  Map transform(Map map, Transformer transformer) {

    Assert.notNull(map, "Map is required");
    Assert.notNull(transformer, "Transformer is required");

    return map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
      (entry) -> transformer.transform(entry.getValue())));
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy