MultiMap.java (4332B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 package org.mozilla.gecko; 6 7 import androidx.annotation.NonNull; 8 import androidx.annotation.Nullable; 9 import java.util.ArrayList; 10 import java.util.Collections; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.Map; 14 import java.util.Set; 15 16 /** 17 * Defines a map that holds a collection of values against each key. 18 * 19 * @param <K> Key type 20 * @param <T> Value type 21 */ 22 public class MultiMap<K, T> { 23 private HashMap<K, List<T>> mMap; 24 private final List<T> mEmptyList = Collections.unmodifiableList(new ArrayList<>()); 25 26 /** 27 * Creates a MultiMap with specified initial capacity. 28 * 29 * @param count Initial capacity 30 */ 31 public MultiMap(final int count) { 32 mMap = new HashMap<>(count); 33 } 34 35 /** Creates a MultiMap with default initial capacity. */ 36 public MultiMap() { 37 mMap = new HashMap<>(); 38 } 39 40 private void ensure(final K key) { 41 if (!mMap.containsKey(key)) { 42 mMap.put(key, new ArrayList<>()); 43 } 44 } 45 46 /** 47 * @return A map of key to the list of values associated to it 48 */ 49 public Map<K, List<T>> asMap() { 50 return mMap; 51 } 52 53 /** 54 * @return The number of keys present in this map 55 */ 56 public int size() { 57 return mMap.size(); 58 } 59 60 /** 61 * @return whether this map is empty or not 62 */ 63 public boolean isEmpty() { 64 return mMap.isEmpty(); 65 } 66 67 /** 68 * Checks if a key is present in this map. 69 * 70 * @param key the key to check 71 * @return True if the map contains this key, false otherwise. 72 */ 73 public boolean containsKey(final @Nullable K key) { 74 return mMap.containsKey(key); 75 } 76 77 /** 78 * Checks if a (key, value) pair is present in this map. 79 * 80 * @param key the key to check 81 * @param value the value to check 82 * @return true if there is a value associated to the given key, false otherwise 83 */ 84 public boolean containsEntry(final @Nullable K key, final @Nullable T value) { 85 if (!mMap.containsKey(key)) { 86 return false; 87 } 88 89 return mMap.get(key).contains(value); 90 } 91 92 /** 93 * Gets the values associated with the given key. 94 * 95 * @param key the key to check 96 * @return the list of values associated with keys, an empty list if no values are associated with 97 * key. 98 */ 99 @NonNull 100 public List<T> get(final @Nullable K key) { 101 if (!mMap.containsKey(key)) { 102 return mEmptyList; 103 } 104 105 return mMap.get(key); 106 } 107 108 /** 109 * Add a (key, value) mapping to this map. 110 * 111 * @param key the key to add 112 * @param value the value to add 113 */ 114 @Nullable 115 public void add(final @NonNull K key, final @NonNull T value) { 116 ensure(key); 117 mMap.get(key).add(value); 118 } 119 120 /** 121 * Add a list of values to the given key. 122 * 123 * @param key the key to add 124 * @param values the list of values to add 125 * @return the final list of values or null if no value was added 126 */ 127 @Nullable 128 public List<T> addAll(final @NonNull K key, final @NonNull List<T> values) { 129 if (values == null || values.isEmpty()) { 130 return null; 131 } 132 133 ensure(key); 134 135 final List<T> result = mMap.get(key); 136 result.addAll(values); 137 return result; 138 } 139 140 /** 141 * Remove all mappings for the given key. 142 * 143 * @param key the key 144 * @return values associated with the key or null if no values was present. 145 */ 146 @Nullable 147 public List<T> remove(final @Nullable K key) { 148 return mMap.remove(key); 149 } 150 151 /** 152 * Remove a (key, value) mapping from this map 153 * 154 * @param key the key to remove 155 * @param value the value to remove 156 * @return true if the (key, value) mapping was present, false otherwise 157 */ 158 @Nullable 159 public boolean remove(final @Nullable K key, final @Nullable T value) { 160 if (!mMap.containsKey(key)) { 161 return false; 162 } 163 164 final List<T> values = mMap.get(key); 165 final boolean wasPresent = values.remove(value); 166 167 if (values.isEmpty()) { 168 mMap.remove(key); 169 } 170 171 return wasPresent; 172 } 173 174 /** Remove all mappings from this map. */ 175 public void clear() { 176 mMap.clear(); 177 } 178 179 /** 180 * @return a set with all the keys for this map. 181 */ 182 @NonNull 183 public Set<K> keySet() { 184 return mMap.keySet(); 185 } 186 }