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

Last change on this file since 9280 was 9074, checked in by Don-vip, 8 years ago

pmd - Ternary operator with a boolean literal can be simplified with a boolean expression

  • 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.Set;
12
13/**
14 * MultiMap - maps keys to multiple values.
15 *
16 * Corresponds to Google guava LinkedHashMultimap and Apache Collections MultiValueMap
17 * but it is an independent (simple) implementation.
18 *
19 * @param <A> Key type
20 * @param <B> Value type
21 *
22 * @since 2702
23 */
24public class MultiMap<A, B> {
25
26 private final Map<A, Set<B>> map;
27
28 /**
29 * Constructs a new {@code MultiMap}.
30 */
31 public MultiMap() {
32 map = new HashMap<>();
33 }
34
35 /**
36 * Constructs a new {@code MultiMap} with the specified initial capacity.
37 * @param capacity the initial capacity
38 */
39 public MultiMap(int capacity) {
40 map = new HashMap<>(capacity);
41 }
42
43 /**
44 * Map a key to a value.
45 *
46 * Can be called multiple times with the same key, but different value.
47 * @param key key with which the specified value is to be associated
48 * @param value value to be associated with the specified key
49 */
50 public void put(A key, B value) {
51 Set<B> vals = map.get(key);
52 if (vals == null) {
53 vals = new LinkedHashSet<>();
54 map.put(key, vals);
55 }
56 vals.add(value);
57 }
58
59 /**
60 * Put a key that maps to nothing. (Only if it is not already in the map)
61 *
62 * Afterwards containsKey(key) will return true and get(key) will return
63 * an empty Set instead of null.
64 * @param key key with which an empty set is to be associated
65 */
66 public void putVoid(A key) {
67 if (map.containsKey(key))
68 return;
69 map.put(key, new LinkedHashSet<B>());
70 }
71
72 /**
73 * Map the key to all the given values.
74 *
75 * Adds to the mappings that are already there.
76 * @param key key with which the specified values are to be associated
77 * @param values values to be associated with the specified key
78 */
79 public void putAll(A key, Collection<B> values) {
80 Set<B> vals = map.get(key);
81 if (vals == null) {
82 vals = new LinkedHashSet<>(values);
83 map.put(key, vals);
84 }
85 vals.addAll(values);
86 }
87
88 /**
89 * Get the keySet.
90 * @return a set view of the keys contained in this map
91 * @see Map#keySet()
92 */
93 public Set<A> keySet() {
94 return map.keySet();
95 }
96
97 /**
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.
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)
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.
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
115 */
116 public Set<B> getValues(A key) {
117 if (!map.containsKey(key))
118 return new LinkedHashSet<>();
119 return map.get(key);
120 }
121
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 */
127 public boolean isEmpty() {
128 return map.isEmpty();
129 }
130
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 */
137 public boolean containsKey(A key) {
138 return map.containsKey(key);
139 }
140
141 /**
142 * Returns true if the multimap contains a value for a key.
143 *
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 && values.contains(value);
151 }
152
153 /**
154 * Removes all of the mappings from this map. The map will be empty after this call returns.
155 * @see Map#clear()
156 */
157 public void clear() {
158 map.clear();
159 }
160
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 */
167 public Set<Entry<A, Set<B>>> entrySet() {
168 return map.entrySet();
169 }
170
171 /**
172 * Returns the number of keys.
173 * @return the number of key-value mappings in this map
174 * @see Map#size()
175 */
176 public int size() {
177 return map.size();
178 }
179
180 /**
181 * Returns a collection of all value sets.
182 * @return a collection view of the values contained in this map
183 * @see Map#values()
184 */
185 public Collection<Set<B>> values() {
186 return map.values();
187 }
188
189 /**
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
193 *
194 * @return {@code true}, if something was removed
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 /**
205 * Removes all mappings for a certain key.
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)
209 */
210 public Set<B> remove(A key) {
211 return map.remove(key);
212 }
213
214 @Override
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;
227 return map.equals(((MultiMap<?, ?>) obj).map);
228 }
229
230 @Override
231 public String toString() {
232 List<String> entries = new ArrayList<>(map.size());
233 for (Entry<A, Set<B>> entry : map.entrySet()) {
234 entries.add(entry.getKey() + "->{" + Utils.join(",", entry.getValue()) + '}');
235 }
236 return '(' + Utils.join(",", entries) + ')';
237 }
238}
Note: See TracBrowser for help on using the repository browser.