Java tutorial
/* * Copyright (C) 2008 feilong * * 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.discovery.darchrow.util; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.collections.comparators.ReverseComparator; import org.apache.commons.lang3.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.discovery.darchrow.bean.ConvertUtil; import com.discovery.darchrow.util.comparator.PropertyComparator; /** * {@link Map}. * * @author feilong * @version 1.0.0 Sep 8, 2012 8:02:44 PM * @see org.apache.commons.collections.MapUtils * @since 1.0.0 */ public final class MapUtil { /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(MapUtil.class); /** Don't let anyone instantiate this class. */ private MapUtil() { //AssertionError?. ?????. ???. //see Effective Java 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } /** * ??map??map. * * <p style="color:green"> * {@link LinkedHashMap},??? ? <code>singleValueMap</code>?? * </p> * * <p> * ?? {@link #toSingleValueMap(Map)} * </p> * * <h3>:</h3> * <blockquote> * * <pre class="code"> * Map{@code <String, String>} singleValueMap = new LinkedHashMap{@code <String, String>}(); * * singleValueMap.put("province", "??"); * singleValueMap.put("city", "?"); * * LOGGER.info(JsonUtil.format(ParamUtil.toArrayValueMap(singleValueMap))); * </pre> * * : * * <pre class="code"> * { * "province": ["??"], * "city": ["?"] * } * </pre> * * </blockquote> * * @param <K> * the key type * @param singleValueMap * the name and value map * @return ? <code>singleValueMap</code> nullempty, {@link Collections#emptyMap()}<br> * ? <code>singleValueMap</code> value?, <code>arrayValueMap</code> * @since 1.6.2 */ public static <K> Map<K, String[]> toArrayValueMap(Map<K, String> singleValueMap) { if (Validator.isNullOrEmpty(singleValueMap)) { return Collections.emptyMap(); } Map<K, String[]> arrayValueMap = newLinkedHashMap(singleValueMap.size());//????singleValueMap?? for (Map.Entry<K, String> entry : singleValueMap.entrySet()) { arrayValueMap.put(entry.getKey(), ConvertUtil.toArray(entry.getValue()));//?Value???V,???Object } return arrayValueMap; } /** * ?keysvalue,?,valuenull or empty,??. * * @param map * the map * @param includeKeys * ?key * @return the mer data * @since 1.2.1 */ public static String joinKeysValue(Map<String, String> map, String[] includeKeys) { if (Validator.isNullOrEmpty(map)) { throw new NullPointerException("map can't be null/empty!"); } StringBuilder sb = new StringBuilder(); //?? for (String key : includeKeys) { String value = map.get(key); //??,null?null if (Validator.isNotNullOrEmpty(value)) { sb.append(value); } } String merData = sb.toString(); return merData; } /** * map key ??map. * * @param <K> * the key type * @param <T> * the generic type * @param map * the map * @param keys * key,key ?map key ? ,map key * @return the sub map<br> * if (Validator.isNullOrEmpty(keys)) map<br> */ public static <K, T> Map<K, T> getSubMap(Map<K, T> map, K[] keys) { if (Validator.isNullOrEmpty(map)) { throw new NullPointerException("the map is null or empty!"); } if (Validator.isNullOrEmpty(keys)) { return map; } Map<K, T> returnMap = new HashMap<K, T>(); for (K key : keys) { if (map.containsKey(key)) { returnMap.put(key, map.get(key)); } else { LOGGER.warn("map don't contains key:[{}]", key); } } return returnMap; } /** * sub map(??keys). * * @param <K> * the key type * @param <T> * the generic type * @param map * the map * @param excludeKeys * the keys * @return the sub map<br> * if (Validator.isNullOrEmpty(keys)) map<br> * @since 1.0.9 */ public static <K, T> Map<K, T> getSubMapExcludeKeys(Map<K, T> map, K[] excludeKeys) { if (Validator.isNullOrEmpty(map)) { throw new NullPointerException("the map is null or empty!"); } if (Validator.isNullOrEmpty(excludeKeys)) { return map; } Map<K, T> returnMap = new HashMap<K, T>(map); for (K key : excludeKeys) { if (map.containsKey(key)) { returnMap.remove(key); } else { LOGGER.warn("map don't contains key:[{}]", key); } } return returnMap; } //*******************************?**************************************************** /** * Sort by key asc. * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return the map< k, v> * @see java.util.TreeMap#TreeMap(Map) * @since 1.2.0 */ public static <K, V> Map<K, V> sortByKeyAsc(Map<K, V> map) { if (Validator.isNullOrEmpty(map)) { throw new NullPointerException("map can't be null/empty!"); } return new TreeMap<K, V>(map); } /** * Sort by key desc. * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return the map< k, v> * @see org.apache.commons.collections.comparators.ReverseComparator#ReverseComparator(Comparator) * @see PropertyComparator#PropertyComparator(String) * @since 1.2.0 */ @SuppressWarnings("unchecked") public static <K, V> Map<K, V> sortByKeyDesc(Map<K, V> map) { if (Validator.isNullOrEmpty(map)) { throw new NullPointerException("map can't be null/empty!"); } return sort(map, new ReverseComparator(new PropertyComparator<Map.Entry<K, V>>("key"))); } /** * ?value ???asc. * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return the map< k, v> * @see PropertyComparator#PropertyComparator(String) * @see java.util.Map.Entry * @see #sortByValueDesc(Map) * @since 1.2.0 */ public static <K, V extends Comparable<V>> Map<K, V> sortByValueAsc(Map<K, V> map) { return sort(map, new PropertyComparator<Map.Entry<K, V>>("value")); } /** * ?value ???desc. * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @return the map< k, v> * @see org.apache.commons.collections.comparators.ReverseComparator#ReverseComparator(Comparator) * @see PropertyComparator#PropertyComparator(String) * @see java.util.Map.Entry * @see #sortByValueAsc(Map) * @since 1.2.0 */ @SuppressWarnings("unchecked") public static <K, V extends Comparable<V>> Map<K, V> sortByValueDesc(Map<K, V> map) { return sort(map, new ReverseComparator(new PropertyComparator<Map.Entry<K, V>>("value"))); } /** * {@link java.util.Map.Entry} <code>mapEntryComparator</code> ? <code>map</code>?. * * <p> * {@link java.util.Map.Entry}?, ?key??,?value?? * </p> * * @param <K> * the key type * @param <V> * the value type * @param map * the map * @param mapEntryComparator * {@link java.util.Map.Entry} {@link Comparator} * @return ??map * @since 1.2.0 */ public static <K, V> Map<K, V> sort(Map<K, V> map, Comparator<Map.Entry<K, V>> mapEntryComparator) { if (Validator.isNullOrEmpty(map)) { throw new NullPointerException("the map is null or empty!"); } if (Validator.isNullOrEmpty(mapEntryComparator)) { throw new NullPointerException("mapEntryComparator is null or empty!"); } //********************************************************** final int size = map.size(); List<Map.Entry<K, V>> mapEntryList = new ArrayList<Map.Entry<K, V>>(size); for (Map.Entry<K, V> entry : map.entrySet()) { mapEntryList.add(entry); } //**********************?************************************ Collections.sort(mapEntryList, mapEntryComparator); //********************************************************** Map<K, V> returnMap = new LinkedHashMap<K, V>(size); for (Map.Entry<K, V> entry : mapEntryList) { K key = entry.getKey(); V value = entry.getValue(); returnMap.put(key, value); } return returnMap; } /** * Creates a {@code LinkedHashMap} instance, with a high enough "initial capacity" that it <i>should</i> hold {@code expectedSize} * elements without growth. This behavior cannot be broadly guaranteed, but it is observed to be true for OpenJDK 1.7. <br> * It also can't be guaranteed that the method isn't inadvertently <i>oversizing</i> the returned map. * * @param <K> * the key type * @param <V> * the value type * @param expectedSize * the number of entries you expect to add to the returned map * @return a new, empty {@code LinkedHashMap} with enough capacity to hold {@code expectedSize} entries without resizing * @see "com.google.common.collect.Maps#newLinkedHashMapWithExpectedSize(int)" * @see java.util.LinkedHashMap#LinkedHashMap(int) * @since 1.7.1 */ public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(int expectedSize) { return new LinkedHashMap<K, V>(toInitialCapacity(expectedSize)); } /** * <code>size</code>? <code>initialCapacity</code> (for {@link java.util.HashMap}). * * <p> * ?? hashmap size,?? * </p> * * @param size * map size * @return the int * @see <a href="http://www.iteye.com/topic/1134016">java hashmap?100new HashMap(?)why </a> * @see <a href= * "http://stackoverflow.com/questions/30220820/difference-between-new-hashmapint-and-guava-maps-newhashmapwithexpectedsizein"> * Difference between new HashMap(int) and guava Maps.newHashMapWithExpectedSize(int)</a> * @see <a href="http://stackoverflow.com/questions/15844035/best-hashmap-initial-capacity-while-indexing-a-list">Best HashMap initial * capacity while indexing a List</a> * @see java.util.HashMap#HashMap(Map) * @see "com.google.common.collect.Maps#capacity(int)" * @see java.util.HashMap#inflateTable(int) * @see org.apache.commons.collections4.map.AbstractHashedMap#calculateNewCapacity(int) * @since 1.7.1 */ private static int toInitialCapacity(int size) { Validate.isTrue(size >= 0, "size :[%s] must >=0", size); // google guava ,? guava ???? //guava 19 (int) (expectedSize / 0.75F + 1.0F) //guava 18 expectedSize + expectedSize / 3 //google-collections 1.0 Math.max(expectedSize * 2, 16) //This is the calculation used in JDK8 to resize when a putAll happens it seems to be the most conservative calculation we can make. return (int) (size / 0.75f) + 1;//0.75 is the default load factor } }