1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Objects.firstNonNull;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static java.util.Arrays.asList;
22
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.annotations.GwtIncompatible;
25
26 import java.io.IOException;
27 import java.io.InvalidObjectException;
28 import java.io.ObjectInputStream;
29 import java.io.ObjectOutputStream;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.Comparator;
34 import java.util.LinkedHashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38
39 import javax.annotation.Nullable;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 @GwtCompatible(serializable = true, emulated = true)
65 public class ImmutableSetMultimap<K, V>
66 extends ImmutableMultimap<K, V>
67 implements SetMultimap<K, V> {
68
69
70
71 @SuppressWarnings("unchecked")
72 public static <K, V> ImmutableSetMultimap<K, V> of() {
73 return (ImmutableSetMultimap<K, V>) EmptyImmutableSetMultimap.INSTANCE;
74 }
75
76
77
78
79 public static <K, V> ImmutableSetMultimap<K, V> of(K k1, V v1) {
80 ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
81 builder.put(k1, v1);
82 return builder.build();
83 }
84
85
86
87
88
89
90 public static <K, V> ImmutableSetMultimap<K, V> of(K k1, V v1, K k2, V v2) {
91 ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
92 builder.put(k1, v1);
93 builder.put(k2, v2);
94 return builder.build();
95 }
96
97
98
99
100
101
102 public static <K, V> ImmutableSetMultimap<K, V> of(
103 K k1, V v1, K k2, V v2, K k3, V v3) {
104 ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
105 builder.put(k1, v1);
106 builder.put(k2, v2);
107 builder.put(k3, v3);
108 return builder.build();
109 }
110
111
112
113
114
115
116 public static <K, V> ImmutableSetMultimap<K, V> of(
117 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
118 ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
119 builder.put(k1, v1);
120 builder.put(k2, v2);
121 builder.put(k3, v3);
122 builder.put(k4, v4);
123 return builder.build();
124 }
125
126
127
128
129
130
131 public static <K, V> ImmutableSetMultimap<K, V> of(
132 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
133 ImmutableSetMultimap.Builder<K, V> builder = ImmutableSetMultimap.builder();
134 builder.put(k1, v1);
135 builder.put(k2, v2);
136 builder.put(k3, v3);
137 builder.put(k4, v4);
138 builder.put(k5, v5);
139 return builder.build();
140 }
141
142
143
144
145
146
147 public static <K, V> Builder<K, V> builder() {
148 return new Builder<K, V>();
149 }
150
151
152
153
154
155 private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
156 BuilderMultimap() {
157 super(new LinkedHashMap<K, Collection<V>>());
158 }
159 @Override Collection<V> createCollection() {
160 return Sets.newLinkedHashSet();
161 }
162 private static final long serialVersionUID = 0;
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 public static final class Builder<K, V>
184 extends ImmutableMultimap.Builder<K, V> {
185
186
187
188
189 public Builder() {
190 builderMultimap = new BuilderMultimap<K, V>();
191 }
192
193
194
195
196
197 @Override public Builder<K, V> put(K key, V value) {
198 builderMultimap.put(checkNotNull(key), checkNotNull(value));
199 return this;
200 }
201
202
203
204
205
206
207 @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
208 builderMultimap.put(
209 checkNotNull(entry.getKey()), checkNotNull(entry.getValue()));
210 return this;
211 }
212
213 @Override public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
214 Collection<V> collection = builderMultimap.get(checkNotNull(key));
215 for (V value : values) {
216 collection.add(checkNotNull(value));
217 }
218 return this;
219 }
220
221 @Override public Builder<K, V> putAll(K key, V... values) {
222 return putAll(key, Arrays.asList(values));
223 }
224
225 @Override public Builder<K, V> putAll(
226 Multimap<? extends K, ? extends V> multimap) {
227 for (Entry<? extends K, ? extends Collection<? extends V>> entry
228 : multimap.asMap().entrySet()) {
229 putAll(entry.getKey(), entry.getValue());
230 }
231 return this;
232 }
233
234
235
236
237
238
239 @Override
240 public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
241 this.keyComparator = checkNotNull(keyComparator);
242 return this;
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256
257 @Override
258 public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
259 super.orderValuesBy(valueComparator);
260 return this;
261 }
262
263
264
265
266 @Override public ImmutableSetMultimap<K, V> build() {
267 if (keyComparator != null) {
268 Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
269 List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
270 builderMultimap.asMap().entrySet());
271 Collections.sort(
272 entries,
273 Ordering.from(keyComparator).<K>onKeys());
274 for (Map.Entry<K, Collection<V>> entry : entries) {
275 sortedCopy.putAll(entry.getKey(), entry.getValue());
276 }
277 builderMultimap = sortedCopy;
278 }
279 return copyOf(builderMultimap, valueComparator);
280 }
281 }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 public static <K, V> ImmutableSetMultimap<K, V> copyOf(
298 Multimap<? extends K, ? extends V> multimap) {
299 return copyOf(multimap, null);
300 }
301
302 private static <K, V> ImmutableSetMultimap<K, V> copyOf(
303 Multimap<? extends K, ? extends V> multimap,
304 Comparator<? super V> valueComparator) {
305 checkNotNull(multimap);
306 if (multimap.isEmpty() && valueComparator == null) {
307 return of();
308 }
309
310 if (multimap instanceof ImmutableSetMultimap) {
311 @SuppressWarnings("unchecked")
312 ImmutableSetMultimap<K, V> kvMultimap
313 = (ImmutableSetMultimap<K, V>) multimap;
314 if (!kvMultimap.isPartialView()) {
315 return kvMultimap;
316 }
317 }
318
319 ImmutableMap.Builder<K, ImmutableSet<V>> builder = ImmutableMap.builder();
320 int size = 0;
321
322 for (Entry<? extends K, ? extends Collection<? extends V>> entry
323 : multimap.asMap().entrySet()) {
324 K key = entry.getKey();
325 Collection<? extends V> values = entry.getValue();
326 ImmutableSet<V> set = valueSet(valueComparator, values);
327 if (!set.isEmpty()) {
328 builder.put(key, set);
329 size += set.size();
330 }
331 }
332
333 return new ImmutableSetMultimap<K, V>(
334 builder.build(), size, valueComparator);
335 }
336
337
338
339
340
341 private final transient ImmutableSet<V> emptySet;
342
343 ImmutableSetMultimap(ImmutableMap<K, ImmutableSet<V>> map, int size,
344 @Nullable Comparator<? super V> valueComparator) {
345 super(map, size);
346 this.emptySet = emptySet(valueComparator);
347 }
348
349
350
351
352
353
354
355
356
357 @Override public ImmutableSet<V> get(@Nullable K key) {
358
359 ImmutableSet<V> set = (ImmutableSet<V>) map.get(key);
360 return firstNonNull(set, emptySet);
361 }
362
363 private transient ImmutableSetMultimap<V, K> inverse;
364
365
366
367
368
369
370
371
372
373
374
375 public ImmutableSetMultimap<V, K> inverse() {
376 ImmutableSetMultimap<V, K> result = inverse;
377 return (result == null) ? (inverse = invert()) : result;
378 }
379
380 private ImmutableSetMultimap<V, K> invert() {
381 Builder<V, K> builder = builder();
382 for (Entry<K, V> entry : entries()) {
383 builder.put(entry.getValue(), entry.getKey());
384 }
385 ImmutableSetMultimap<V, K> invertedMultimap = builder.build();
386 invertedMultimap.inverse = this;
387 return invertedMultimap;
388 }
389
390
391
392
393
394
395
396 @Deprecated @Override public ImmutableSet<V> removeAll(Object key) {
397 throw new UnsupportedOperationException();
398 }
399
400
401
402
403
404
405
406 @Deprecated @Override public ImmutableSet<V> replaceValues(
407 K key, Iterable<? extends V> values) {
408 throw new UnsupportedOperationException();
409 }
410
411 private transient ImmutableSet<Entry<K, V>> entries;
412
413
414
415
416
417
418 @Override public ImmutableSet<Entry<K, V>> entries() {
419 ImmutableSet<Entry<K, V>> result = entries;
420 return (result == null)
421 ? (entries = new EntrySet<K, V>(this))
422 : result;
423 }
424
425 private static final class EntrySet<K, V> extends ImmutableSet<Entry<K, V>> {
426 private transient final ImmutableSetMultimap<K, V> multimap;
427
428 EntrySet(ImmutableSetMultimap<K, V> multimap) {
429 this.multimap = multimap;
430 }
431
432 @Override
433 public boolean contains(@Nullable Object object) {
434 if (object instanceof Entry) {
435 Entry<?, ?> entry = (Entry<?, ?>) object;
436 return multimap.containsEntry(entry.getKey(), entry.getValue());
437 }
438 return false;
439 }
440
441 @Override
442 public int size() {
443 return multimap.size();
444 }
445
446 @Override
447 public UnmodifiableIterator<Entry<K, V>> iterator() {
448 return multimap.entryIterator();
449 }
450
451 @Override
452 boolean isPartialView() {
453 return false;
454 }
455 }
456
457 private static <V> ImmutableSet<V> valueSet(
458 @Nullable Comparator<? super V> valueComparator,
459 Collection<? extends V> values) {
460 return (valueComparator == null)
461 ? ImmutableSet.copyOf(values)
462 : ImmutableSortedSet.copyOf(valueComparator, values);
463 }
464
465 private static <V> ImmutableSet<V> emptySet(
466 @Nullable Comparator<? super V> valueComparator) {
467 return (valueComparator == null)
468 ? ImmutableSet.<V>of()
469 : ImmutableSortedSet.<V>emptySet(valueComparator);
470 }
471
472
473
474
475
476 @GwtIncompatible("java.io.ObjectOutputStream")
477 private void writeObject(ObjectOutputStream stream) throws IOException {
478 stream.defaultWriteObject();
479 stream.writeObject(valueComparator());
480 Serialization.writeMultimap(this, stream);
481 }
482
483 @Nullable Comparator<? super V> valueComparator() {
484 return emptySet instanceof ImmutableSortedSet
485 ? ((ImmutableSortedSet<V>) emptySet).comparator()
486 : null;
487 }
488
489 @GwtIncompatible("java.io.ObjectInputStream")
490
491 @SuppressWarnings("unchecked")
492 private void readObject(ObjectInputStream stream)
493 throws IOException, ClassNotFoundException {
494 stream.defaultReadObject();
495 Comparator<Object> valueComparator =
496 (Comparator<Object>) stream.readObject();
497 int keyCount = stream.readInt();
498 if (keyCount < 0) {
499 throw new InvalidObjectException("Invalid key count " + keyCount);
500 }
501 ImmutableMap.Builder<Object, ImmutableSet<Object>> builder
502 = ImmutableMap.builder();
503 int tmpSize = 0;
504
505 for (int i = 0; i < keyCount; i++) {
506 Object key = stream.readObject();
507 int valueCount = stream.readInt();
508 if (valueCount <= 0) {
509 throw new InvalidObjectException("Invalid value count " + valueCount);
510 }
511
512 Object[] array = new Object[valueCount];
513 for (int j = 0; j < valueCount; j++) {
514 array[j] = stream.readObject();
515 }
516 ImmutableSet<Object> valueSet = valueSet(valueComparator, asList(array));
517 if (valueSet.size() != array.length) {
518 throw new InvalidObjectException(
519 "Duplicate key-value pairs exist for key " + key);
520 }
521 builder.put(key, valueSet);
522 tmpSize += valueCount;
523 }
524
525 ImmutableMap<Object, ImmutableSet<Object>> tmpMap;
526 try {
527 tmpMap = builder.build();
528 } catch (IllegalArgumentException e) {
529 throw (InvalidObjectException)
530 new InvalidObjectException(e.getMessage()).initCause(e);
531 }
532
533 FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap);
534 FieldSettersHolder.SIZE_FIELD_SETTER.set(this, tmpSize);
535 FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(
536 this, emptySet(valueComparator));
537 }
538
539 @GwtIncompatible("not needed in emulated source.")
540 private static final long serialVersionUID = 0;
541 }