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