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.Preconditions.checkNotNull;
20 import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
21
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.annotations.GwtIncompatible;
24
25 import java.io.Serializable;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.Comparator;
30 import java.util.Iterator;
31 import java.util.LinkedHashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.Set;
36
37 import javax.annotation.Nullable;
38
39
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(emulated = true)
65 public abstract class ImmutableMultimap<K, V> extends AbstractMultimap<K, V>
66 implements Serializable {
67
68
69 public static <K, V> ImmutableMultimap<K, V> of() {
70 return ImmutableListMultimap.of();
71 }
72
73
74
75
76 public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1) {
77 return ImmutableListMultimap.of(k1, v1);
78 }
79
80
81
82
83 public static <K, V> ImmutableMultimap<K, V> of(K k1, V v1, K k2, V v2) {
84 return ImmutableListMultimap.of(k1, v1, k2, v2);
85 }
86
87
88
89
90 public static <K, V> ImmutableMultimap<K, V> of(
91 K k1, V v1, K k2, V v2, K k3, V v3) {
92 return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3);
93 }
94
95
96
97
98 public static <K, V> ImmutableMultimap<K, V> of(
99 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
100 return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4);
101 }
102
103
104
105
106 public static <K, V> ImmutableMultimap<K, V> of(
107 K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
108 return ImmutableListMultimap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
109 }
110
111
112
113
114
115
116
117 public static <K, V> Builder<K, V> builder() {
118 return new Builder<K, V>();
119 }
120
121
122
123
124
125
126 private static class BuilderMultimap<K, V> extends AbstractMapBasedMultimap<K, V> {
127 BuilderMultimap() {
128 super(new LinkedHashMap<K, Collection<V>>());
129 }
130 @Override Collection<V> createCollection() {
131 return Lists.newArrayList();
132 }
133 private static final long serialVersionUID = 0;
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public static class Builder<K, V> {
155 Multimap<K, V> builderMultimap = new BuilderMultimap<K, V>();
156 Comparator<? super K> keyComparator;
157 Comparator<? super V> valueComparator;
158
159
160
161
162
163 public Builder() {}
164
165
166
167
168 public Builder<K, V> put(K key, V value) {
169 checkEntryNotNull(key, value);
170 builderMultimap.put(key, value);
171 return this;
172 }
173
174
175
176
177
178
179 public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
180 return put(entry.getKey(), entry.getValue());
181 }
182
183
184
185
186
187
188
189
190 public Builder<K, V> putAll(K key, Iterable<? extends V> values) {
191 if (key == null) {
192 throw new NullPointerException(
193 "null key in entry: null=" + Iterables.toString(values));
194 }
195 Collection<V> valueList = builderMultimap.get(key);
196 for (V value : values) {
197 checkEntryNotNull(key, value);
198 valueList.add(value);
199 }
200 return this;
201 }
202
203
204
205
206
207
208
209 public Builder<K, V> putAll(K key, V... values) {
210 return putAll(key, Arrays.asList(values));
211 }
212
213
214
215
216
217
218
219
220
221
222 public Builder<K, V> putAll(Multimap<? extends K, ? extends V> multimap) {
223 for (Entry<? extends K, ? extends Collection<? extends V>> entry
224 : multimap.asMap().entrySet()) {
225 putAll(entry.getKey(), entry.getValue());
226 }
227 return this;
228 }
229
230
231
232
233
234
235 public Builder<K, V> orderKeysBy(Comparator<? super K> keyComparator) {
236 this.keyComparator = checkNotNull(keyComparator);
237 return this;
238 }
239
240
241
242
243
244
245 public Builder<K, V> orderValuesBy(Comparator<? super V> valueComparator) {
246 this.valueComparator = checkNotNull(valueComparator);
247 return this;
248 }
249
250
251
252
253 public ImmutableMultimap<K, V> build() {
254 if (valueComparator != null) {
255 for (Collection<V> values : builderMultimap.asMap().values()) {
256 List<V> list = (List <V>) values;
257 Collections.sort(list, valueComparator);
258 }
259 }
260 if (keyComparator != null) {
261 Multimap<K, V> sortedCopy = new BuilderMultimap<K, V>();
262 List<Map.Entry<K, Collection<V>>> entries = Lists.newArrayList(
263 builderMultimap.asMap().entrySet());
264 Collections.sort(
265 entries,
266 Ordering.from(keyComparator).<K>onKeys());
267 for (Map.Entry<K, Collection<V>> entry : entries) {
268 sortedCopy.putAll(entry.getKey(), entry.getValue());
269 }
270 builderMultimap = sortedCopy;
271 }
272 return copyOf(builderMultimap);
273 }
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288 public static <K, V> ImmutableMultimap<K, V> copyOf(
289 Multimap<? extends K, ? extends V> multimap) {
290 if (multimap instanceof ImmutableMultimap) {
291 @SuppressWarnings("unchecked")
292 ImmutableMultimap<K, V> kvMultimap
293 = (ImmutableMultimap<K, V>) multimap;
294 if (!kvMultimap.isPartialView()) {
295 return kvMultimap;
296 }
297 }
298 return ImmutableListMultimap.copyOf(multimap);
299 }
300
301 final transient ImmutableMap<K, ? extends ImmutableCollection<V>> map;
302 final transient int size;
303
304
305
306
307 @GwtIncompatible("java serialization is not supported")
308 static class FieldSettersHolder {
309 static final Serialization.FieldSetter<ImmutableMultimap>
310 MAP_FIELD_SETTER = Serialization.getFieldSetter(
311 ImmutableMultimap.class, "map");
312 static final Serialization.FieldSetter<ImmutableMultimap>
313 SIZE_FIELD_SETTER = Serialization.getFieldSetter(
314 ImmutableMultimap.class, "size");
315 static final Serialization.FieldSetter<ImmutableSetMultimap>
316 EMPTY_SET_FIELD_SETTER = Serialization.getFieldSetter(
317 ImmutableSetMultimap.class, "emptySet");
318 }
319
320 ImmutableMultimap(ImmutableMap<K, ? extends ImmutableCollection<V>> map,
321 int size) {
322 this.map = map;
323 this.size = size;
324 }
325
326
327
328
329
330
331
332
333
334 @Deprecated
335 @Override
336 public ImmutableCollection<V> removeAll(Object key) {
337 throw new UnsupportedOperationException();
338 }
339
340
341
342
343
344
345
346 @Deprecated
347 @Override
348 public ImmutableCollection<V> replaceValues(K key,
349 Iterable<? extends V> values) {
350 throw new UnsupportedOperationException();
351 }
352
353
354
355
356
357
358
359 @Deprecated
360 @Override
361 public void clear() {
362 throw new UnsupportedOperationException();
363 }
364
365
366
367
368
369
370
371 @Override
372 public abstract ImmutableCollection<V> get(K key);
373
374
375
376
377
378
379
380
381 public abstract ImmutableMultimap<V, K> inverse();
382
383
384
385
386
387
388
389 @Deprecated
390 @Override
391 public boolean put(K key, V value) {
392 throw new UnsupportedOperationException();
393 }
394
395
396
397
398
399
400
401 @Deprecated
402 @Override
403 public boolean putAll(K key, Iterable<? extends V> values) {
404 throw new UnsupportedOperationException();
405 }
406
407
408
409
410
411
412
413 @Deprecated
414 @Override
415 public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
416 throw new UnsupportedOperationException();
417 }
418
419
420
421
422
423
424
425 @Deprecated
426 @Override
427 public boolean remove(Object key, Object value) {
428 throw new UnsupportedOperationException();
429 }
430
431
432
433
434
435
436
437 boolean isPartialView() {
438 return map.isPartialView();
439 }
440
441
442
443 @Override
444 public boolean containsKey(@Nullable Object key) {
445 return map.containsKey(key);
446 }
447
448 @Override
449 public boolean containsValue(@Nullable Object value) {
450 return value != null && super.containsValue(value);
451 }
452
453 @Override
454 public int size() {
455 return size;
456 }
457
458
459
460
461
462
463
464
465 @Override
466 public ImmutableSet<K> keySet() {
467 return map.keySet();
468 }
469
470
471
472
473
474 @Override
475 @SuppressWarnings("unchecked")
476 public ImmutableMap<K, Collection<V>> asMap() {
477 return (ImmutableMap) map;
478 }
479
480 @Override
481 Map<K, Collection<V>> createAsMap() {
482 throw new AssertionError("should never be called");
483 }
484
485
486
487
488
489
490 @Override
491 public ImmutableCollection<Entry<K, V>> entries() {
492 return (ImmutableCollection<Entry<K, V>>) super.entries();
493 }
494
495 @Override
496 ImmutableCollection<Entry<K, V>> createEntries() {
497 return new EntryCollection<K, V>(this);
498 }
499
500 private static class EntryCollection<K, V>
501 extends ImmutableCollection<Entry<K, V>> {
502 final ImmutableMultimap<K, V> multimap;
503
504 EntryCollection(ImmutableMultimap<K, V> multimap) {
505 this.multimap = multimap;
506 }
507
508 @Override public UnmodifiableIterator<Entry<K, V>> iterator() {
509 return multimap.entryIterator();
510 }
511
512 @Override boolean isPartialView() {
513 return multimap.isPartialView();
514 }
515
516 @Override
517 public int size() {
518 return multimap.size();
519 }
520
521 @Override public boolean contains(Object object) {
522 if (object instanceof Entry) {
523 Entry<?, ?> entry = (Entry<?, ?>) object;
524 return multimap.containsEntry(entry.getKey(), entry.getValue());
525 }
526 return false;
527 }
528
529 private static final long serialVersionUID = 0;
530 }
531
532 private abstract class Itr<T> extends UnmodifiableIterator<T> {
533 final Iterator<Entry<K, Collection<V>>> mapIterator = asMap().entrySet().iterator();
534 K key = null;
535 Iterator<V> valueIterator = Iterators.emptyIterator();
536
537 abstract T output(K key, V value);
538
539 @Override
540 public boolean hasNext() {
541 return mapIterator.hasNext() || valueIterator.hasNext();
542 }
543
544 @Override
545 public T next() {
546 if (!valueIterator.hasNext()) {
547 Entry<K, Collection<V>> mapEntry = mapIterator.next();
548 key = mapEntry.getKey();
549 valueIterator = mapEntry.getValue().iterator();
550 }
551 return output(key, valueIterator.next());
552 }
553 }
554
555 @Override
556 UnmodifiableIterator<Entry<K, V>> entryIterator() {
557 return new Itr<Entry<K, V>>() {
558 @Override
559 Entry<K, V> output(K key, V value) {
560 return Maps.immutableEntry(key, value);
561 }
562 };
563 }
564
565
566
567
568
569
570
571 @Override
572 public ImmutableMultiset<K> keys() {
573 return (ImmutableMultiset<K>) super.keys();
574 }
575
576 @Override
577 ImmutableMultiset<K> createKeys() {
578 return new Keys();
579 }
580
581 @SuppressWarnings("serial")
582 class Keys extends ImmutableMultiset<K> {
583 @Override
584 public boolean contains(@Nullable Object object) {
585 return containsKey(object);
586 }
587
588 @Override
589 public int count(@Nullable Object element) {
590 Collection<V> values = map.get(element);
591 return (values == null) ? 0 : values.size();
592 }
593
594 @Override
595 public Set<K> elementSet() {
596 return keySet();
597 }
598
599 @Override
600 public int size() {
601 return ImmutableMultimap.this.size();
602 }
603
604 @Override
605 Multiset.Entry<K> getEntry(int index) {
606 Map.Entry<K, ? extends Collection<V>> entry = map.entrySet().asList().get(index);
607 return Multisets.immutableEntry(entry.getKey(), entry.getValue().size());
608 }
609
610 @Override
611 boolean isPartialView() {
612 return true;
613 }
614 }
615
616
617
618
619
620
621 @Override
622 public ImmutableCollection<V> values() {
623 return (ImmutableCollection<V>) super.values();
624 }
625
626 @Override
627 ImmutableCollection<V> createValues() {
628 return new Values<K, V>(this);
629 }
630
631 @Override
632 UnmodifiableIterator<V> valueIterator() {
633 return new Itr<V>() {
634 @Override
635 V output(K key, V value) {
636 return value;
637 }
638 };
639 }
640
641 private static final class Values<K, V> extends ImmutableCollection<V> {
642 private transient final ImmutableMultimap<K, V> multimap;
643
644 Values(ImmutableMultimap<K, V> multimap) {
645 this.multimap = multimap;
646 }
647
648 @Override
649 public boolean contains(@Nullable Object object) {
650 return multimap.containsValue(object);
651 }
652
653 @Override public UnmodifiableIterator<V> iterator() {
654 return multimap.valueIterator();
655 }
656
657 @GwtIncompatible("not present in emulated superclass")
658 @Override
659 int copyIntoArray(Object[] dst, int offset) {
660 for (ImmutableCollection<V> valueCollection : multimap.map.values()) {
661 offset = valueCollection.copyIntoArray(dst, offset);
662 }
663 return offset;
664 }
665
666 @Override
667 public int size() {
668 return multimap.size();
669 }
670
671 @Override boolean isPartialView() {
672 return true;
673 }
674
675 private static final long serialVersionUID = 0;
676 }
677
678 private static final long serialVersionUID = 0;
679 }