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

Last change on this file since 11348 was 9790, checked in by bastiK, 8 years ago

use intended units for east/north coordinates (see #12186)

When east/north coordinates are not in meter, but
feet, ... convert them to correct units.
Currently they are always stored in meters or degrees.
This makes no difference to JOSM internally, but affects
services like WMS/WMTS.
Only relevant for projections with +units=... or +to_meter=...
parameter set to non-default value.

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