1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.collections4.multimap; 18 19 import java.io.IOException; 20 import java.io.ObjectInputStream; 21 import java.io.ObjectOutputStream; 22 import java.io.Serializable; 23 import java.util.ArrayList; 24 import java.util.Collection; 25 import java.util.HashMap; 26 import java.util.Map; 27 28 import org.apache.commons.collections4.MultiValuedMap; 29 30 /** 31 * Implements a {@code ListValuedMap}, using a {@link HashMap} to provide data 32 * storage and {@link ArrayList}s as value collections. This is the standard 33 * implementation of a ListValuedMap. 34 * <p> 35 * <strong>Note that ArrayListValuedHashMap is not synchronized and is not 36 * thread-safe.</strong> If you wish to use this map from multiple threads 37 * concurrently, you must use appropriate synchronization. This class may throw 38 * exceptions when accessed by concurrent threads without synchronization. 39 * </p> 40 * 41 * @param <K> the type of the keys in this map 42 * @param <V> the type of the values in this map 43 * @since 4.1 44 */ 45 public class ArrayListValuedHashMap<K, V> extends AbstractListValuedMap<K, V> 46 implements Serializable { 47 48 /** Serialization Version */ 49 private static final long serialVersionUID = 20151118L; 50 51 /** 52 * The initial map capacity used when none specified in constructor. 53 */ 54 private static final int DEFAULT_INITIAL_MAP_CAPACITY = 16; 55 56 /** 57 * The initial list capacity when using none specified in constructor. 58 */ 59 private static final int DEFAULT_INITIAL_LIST_CAPACITY = 3; 60 61 /** 62 * The initial list capacity when creating a new value collection. 63 */ 64 private final int initialListCapacity; 65 66 /** 67 * Creates an empty ArrayListValuedHashMap with the default initial 68 * map capacity (16) and the default initial list capacity (3). 69 */ 70 public ArrayListValuedHashMap() { 71 this(DEFAULT_INITIAL_MAP_CAPACITY, DEFAULT_INITIAL_LIST_CAPACITY); 72 } 73 74 /** 75 * Creates an empty ArrayListValuedHashMap with the default initial 76 * map capacity (16) and the specified initial list capacity. 77 * 78 * @param initialListCapacity the initial capacity used for value collections 79 */ 80 public ArrayListValuedHashMap(final int initialListCapacity) { 81 this(DEFAULT_INITIAL_MAP_CAPACITY, initialListCapacity); 82 } 83 84 /** 85 * Creates an empty ArrayListValuedHashMap with the specified initial 86 * map and list capacities. 87 * 88 * @param initialMapCapacity the initial hashmap capacity 89 * @param initialListCapacity the initial capacity used for value collections 90 */ 91 public ArrayListValuedHashMap(final int initialMapCapacity, final int initialListCapacity) { 92 super(new HashMap<>(initialMapCapacity)); 93 this.initialListCapacity = initialListCapacity; 94 } 95 96 /** 97 * Creates an ArrayListValuedHashMap copying all the mappings of the given map. 98 * 99 * @param map a {@code Map} to copy into this map 100 */ 101 public ArrayListValuedHashMap(final Map<? extends K, ? extends V> map) { 102 this(map.size(), DEFAULT_INITIAL_LIST_CAPACITY); 103 super.putAll(map); 104 } 105 106 /** 107 * Creates an ArrayListValuedHashMap copying all the mappings of the given map. 108 * 109 * @param map a {@code MultiValuedMap} to copy into this map 110 */ 111 public ArrayListValuedHashMap(final MultiValuedMap<? extends K, ? extends V> map) { 112 this(map.size(), DEFAULT_INITIAL_LIST_CAPACITY); 113 super.putAll(map); 114 } 115 116 @Override 117 protected ArrayList<V> createCollection() { 118 return new ArrayList<>(initialListCapacity); 119 } 120 121 private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException { 122 ois.defaultReadObject(); 123 setMap(new HashMap<>()); 124 doReadObject(ois); 125 } 126 127 /** 128 * Trims the capacity of all value collections to their current size. 129 */ 130 public void trimToSize() { 131 for (final Collection<V> coll : getMap().values()) { 132 final ArrayList<V> list = (ArrayList<V>) coll; 133 list.trimToSize(); 134 } 135 } 136 137 private void writeObject(final ObjectOutputStream oos) throws IOException { 138 oos.defaultWriteObject(); 139 doWriteObject(oos); 140 } 141 142 }