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

Last change on this file since 9499 was 9371, checked in by simon04, 8 years ago

Java 7: use Objects.equals and Objects.hash

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