source: josm/trunk/src/org/openstreetmap/josm/tools/MultiMap.java@ 8540

Last change on this file since 8540 was 8510, checked in by Don-vip, 9 years ago

checkstyle: enable relevant whitespace checks and fix them

  • Property svn:eol-style set to native
File size: 6.8 KB
RevLine 
[8378]1// License: GPL. For details, see LICENSE file.
[2702]2package org.openstreetmap.josm.tools;
3
[4668]4import java.util.ArrayList;
[3674]5import java.util.Collection;
[2990]6import java.util.HashMap;
[5822]7import java.util.LinkedHashSet;
[4668]8import java.util.List;
[3637]9import java.util.Map;
[3674]10import java.util.Map.Entry;
[3637]11import java.util.Set;
[2702]12
13/**
[7275]14 * MultiMap - maps keys to multiple values.
[3674]15 *
16 * Corresponds to Google guava LinkedHashMultimap and Apache Collections MultiValueMap
[4668]17 * but it is an independent (simple) implementation.
[3674]18 *
[7275]19 * @param <A> Key type
20 * @param <B> Value type
21 *
22 * @since 2702
[2702]23 */
[3674]24public class MultiMap<A, B> {
[3637]25
[5783]26 private final Map<A, Set<B>> map;
[3674]27
[7005]28 /**
29 * Constructs a new {@code MultiMap}.
30 */
[3674]31 public MultiMap() {
[7005]32 map = new HashMap<>();
[3674]33 }
34
[7005]35 /**
[7275]36 * Constructs a new {@code MultiMap} with the specified initial capacity.
[7005]37 * @param capacity the initial capacity
38 */
[3674]39 public MultiMap(int capacity) {
[7005]40 map = new HashMap<>(capacity);
[3674]41 }
42
[2946]43 /**
[4685]44 * Map a key to a value.
45 *
46 * Can be called multiple times with the same key, but different value.
[7275]47 * @param key key with which the specified value is to be associated
48 * @param value value to be associated with the specified key
[2946]49 */
50 public void put(A key, B value) {
[5783]51 Set<B> vals = map.get(key);
[2702]52 if (vals == null) {
[7005]53 vals = new LinkedHashSet<>();
[3637]54 map.put(key, vals);
[2702]55 }
56 vals.add(value);
57 }
[2990]58
[2946]59 /**
[3674]60 * Put a key that maps to nothing. (Only if it is not already in the map)
[4685]61 *
[3674]62 * Afterwards containsKey(key) will return true and get(key) will return
63 * an empty Set instead of null.
[7275]64 * @param key key with which an empty set is to be associated
[2946]65 */
66 public void putVoid(A key) {
[3637]67 if (map.containsKey(key))
[2946]68 return;
[5822]69 map.put(key, new LinkedHashSet<B>());
[2946]70 }
71
72 /**
[4685]73 * Map the key to all the given values.
74 *
75 * Adds to the mappings that are already there.
[7275]76 * @param key key with which the specified values are to be associated
77 * @param values values to be associated with the specified key
[2946]78 */
[4685]79 public void putAll(A key, Collection<B> values) {
[5783]80 Set<B> vals = map.get(key);
[4685]81 if (vals == null) {
[7005]82 vals = new LinkedHashSet<>(values);
[4685]83 map.put(key, vals);
84 }
85 vals.addAll(values);
86 }
87
88 /**
89 * Get the keySet.
[7275]90 * @return a set view of the keys contained in this map
91 * @see Map#keySet()
[4685]92 */
[3674]93 public Set<A> keySet() {
94 return map.keySet();
95 }
96
97 /**
[4685]98 * Returns the Set associated with the given key. Result is null if
99 * nothing has been mapped to this key.
100 *
101 * Modifications of the returned list changes the underling map,
102 * but you should better not do that.
[7275]103 * @param key the key whose associated value is to be returned
104 * @return the set of values to which the specified key is mapped, or {@code null} if this map contains no mapping for the key
105 * @see Map#get(Object)
[3674]106 */
107 public Set<B> get(A key) {
108 return map.get(key);
109 }
110
111 /**
112 * Like get, but returns an empty Set if nothing has been mapped to the key.
[7275]113 * @param key the key whose associated value is to be returned
114 * @return the set of values to which the specified key is mapped, or an empty set if this map contains no mapping for the key
[3674]115 */
[5783]116 public Set<B> getValues(A key) {
[3637]117 if (!map.containsKey(key))
[7005]118 return new LinkedHashSet<>();
[3637]119 return map.get(key);
[2946]120 }
[3637]121
[7275]122 /**
123 * Returns {@code true} if this map contains no key-value mappings.
124 * @return {@code true} if this map contains no key-value mappings
125 * @see Map#isEmpty()
126 */
[3674]127 public boolean isEmpty() {
128 return map.isEmpty();
[3637]129 }
130
[7275]131 /**
132 * Returns {@code true} if this map contains a mapping for the specified key.
133 * @param key key whose presence in this map is to be tested
134 * @return {@code true} if this map contains a mapping for the specified key
135 * @see Map#containsKey(Object)
136 */
[3674]137 public boolean containsKey(A key) {
138 return map.containsKey(key);
[3637]139 }
[3674]140
141 /**
[4685]142 * Returns true if the multimap contains a value for a key.
143 *
[3674]144 * @param key The key
145 * @param value The value
146 * @return true if the key contains the value
147 */
148 public boolean contains(A key, B value) {
149 Set<B> values = get(key);
150 return (values == null) ? false : values.contains(value);
151 }
152
[7275]153 /**
154 * Removes all of the mappings from this map. The map will be empty after this call returns.
155 * @see Map#clear()
156 */
[3674]157 public void clear() {
158 map.clear();
159 }
160
[7275]161 /**
162 * Returns a Set view of the mappings contained in this map.
163 * The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
164 * @return a set view of the mappings contained in this map
165 * @see Map#entrySet()
166 */
[5783]167 public Set<Entry<A, Set<B>>> entrySet() {
[3674]168 return map.entrySet();
169 }
170
171 /**
[4685]172 * Returns the number of keys.
[7275]173 * @return the number of key-value mappings in this map
174 * @see Map#size()
[3674]175 */
176 public int size() {
177 return map.size();
178 }
179
180 /**
[4685]181 * Returns a collection of all value sets.
[7275]182 * @return a collection view of the values contained in this map
183 * @see Map#values()
[3674]184 */
[5783]185 public Collection<Set<B>> values() {
[3674]186 return map.values();
187 }
[4668]188
189 /**
[7275]190 * Removes a certain key=value mapping.
191 * @param key key whose mapping is to be removed from the map
192 * @param value value whose mapping is to be removed from the map
[4668]193 *
[7275]194 * @return {@code true}, if something was removed
[4668]195 */
196 public boolean remove(A key, B value) {
197 Set<B> values = get(key);
198 if (values != null) {
199 return values.remove(value);
200 }
201 return false;
202 }
203
204 /**
[4685]205 * Removes all mappings for a certain key.
[7275]206 * @param key key whose mapping is to be removed from the map
207 * @return the previous value associated with key, or {@code null} if there was no mapping for key.
208 * @see Map#remove(Object)
[4668]209 */
[5783]210 public Set<B> remove(A key) {
[4668]211 return map.remove(key);
212 }
213
[5783]214 @Override
[7276]215 public int hashCode() {
216 return map.hashCode();
217 }
218
219 @Override
220 public boolean equals(Object obj) {
221 if (this == obj)
222 return true;
223 if (obj == null)
224 return false;
225 if (!(obj instanceof MultiMap))
226 return false;
[8510]227 return map.equals(((MultiMap<?, ?>) obj).map);
[7276]228 }
229
230 @Override
[4668]231 public String toString() {
[7005]232 List<String> entries = new ArrayList<>(map.size());
[8332]233 for (Entry<A, Set<B>> entry : map.entrySet()) {
234 entries.add(entry.getKey() + "->{" + Utils.join(",", entry.getValue()) + "}");
[4668]235 }
236 return "(" + Utils.join(",", entries) + ")";
237 }
[2702]238}
Note: See TracBrowser for help on using the repository browser.