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.collect.Maps.transformEntries;
20 import static com.google.common.collect.Maps.transformValues;
21 import static com.google.common.collect.testing.Helpers.mapEntry;
22 import static com.google.common.truth.Truth.assertThat;
23
24 import com.google.common.annotations.GwtCompatible;
25 import com.google.common.base.Converter;
26 import com.google.common.base.Equivalence;
27 import com.google.common.base.Function;
28 import com.google.common.base.Functions;
29 import com.google.common.base.Predicate;
30 import com.google.common.base.Predicates;
31 import com.google.common.collect.Maps.EntryTransformer;
32 import com.google.common.collect.Maps.ValueDifferenceImpl;
33 import com.google.common.collect.SetsTest.Derived;
34 import com.google.common.testing.EqualsTester;
35 import com.google.common.testing.SerializableTester;
36
37 import junit.framework.TestCase;
38
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.Comparator;
42 import java.util.EnumMap;
43 import java.util.HashMap;
44 import java.util.IdentityHashMap;
45 import java.util.Iterator;
46 import java.util.LinkedHashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Map.Entry;
50 import java.util.Set;
51 import java.util.SortedMap;
52 import java.util.SortedSet;
53 import java.util.TreeMap;
54 import java.util.concurrent.ConcurrentMap;
55
56
57
58
59
60
61
62
63 @GwtCompatible(emulated = true)
64 public class MapsTest extends TestCase {
65
66 private static final Comparator<Integer> SOME_COMPARATOR =
67 Collections.reverseOrder();
68
69 public void testHashMap() {
70 HashMap<Integer, Integer> map = Maps.newHashMap();
71 assertEquals(Collections.emptyMap(), map);
72 }
73
74 public void testHashMapWithInitialMap() {
75 Map<String, Integer> original = new TreeMap<String, Integer>();
76 original.put("a", 1);
77 original.put("b", 2);
78 original.put("c", 3);
79 HashMap<String, Integer> map = Maps.newHashMap(original);
80 assertEquals(original, map);
81 }
82
83 public void testHashMapGeneralizesTypes() {
84 Map<String, Integer> original = new TreeMap<String, Integer>();
85 original.put("a", 1);
86 original.put("b", 2);
87 original.put("c", 3);
88 HashMap<Object, Object> map =
89 Maps.newHashMap((Map<? extends Object, ? extends Object>) original);
90 assertEquals(original, map);
91 }
92
93 public void testCapacityForNegativeSizeFails() {
94 try {
95 Maps.capacity(-1);
96 fail("Negative expected size must result in IllegalArgumentException");
97 } catch (IllegalArgumentException ex) {
98 }
99 }
100
101 public void testCapacityForLargeSizes() {
102 int[] largeExpectedSizes = new int[] {
103 Integer.MAX_VALUE / 2 - 1,
104 Integer.MAX_VALUE / 2,
105 Integer.MAX_VALUE / 2 + 1,
106 Integer.MAX_VALUE - 1,
107 Integer.MAX_VALUE};
108 for (int expectedSize : largeExpectedSizes) {
109 int capacity = Maps.capacity(expectedSize);
110 assertTrue(
111 "capacity (" + capacity + ") must be >= expectedSize (" + expectedSize + ")",
112 capacity >= expectedSize);
113 }
114 }
115
116 public void testLinkedHashMap() {
117 LinkedHashMap<Integer, Integer> map = Maps.newLinkedHashMap();
118 assertEquals(Collections.emptyMap(), map);
119 }
120
121 @SuppressWarnings("serial")
122 public void testLinkedHashMapWithInitialMap() {
123 Map<String, String> map = new LinkedHashMap<String, String>() {{
124 put("Hello", "World");
125 put("first", "second");
126 put("polygene", "lubricants");
127 put("alpha", "betical");
128 }};
129
130 LinkedHashMap<String, String> copy = Maps.newLinkedHashMap(map);
131
132 Iterator<Entry<String, String>> iter = copy.entrySet().iterator();
133 assertTrue(iter.hasNext());
134 Entry<String, String> entry = iter.next();
135 assertEquals("Hello", entry.getKey());
136 assertEquals("World", entry.getValue());
137 assertTrue(iter.hasNext());
138
139 entry = iter.next();
140 assertEquals("first", entry.getKey());
141 assertEquals("second", entry.getValue());
142 assertTrue(iter.hasNext());
143
144 entry = iter.next();
145 assertEquals("polygene", entry.getKey());
146 assertEquals("lubricants", entry.getValue());
147 assertTrue(iter.hasNext());
148
149 entry = iter.next();
150 assertEquals("alpha", entry.getKey());
151 assertEquals("betical", entry.getValue());
152 assertFalse(iter.hasNext());
153 }
154
155 public void testLinkedHashMapGeneralizesTypes() {
156 Map<String, Integer> original = new LinkedHashMap<String, Integer>();
157 original.put("a", 1);
158 original.put("b", 2);
159 original.put("c", 3);
160 HashMap<Object, Object> map
161 = Maps.<Object, Object>newLinkedHashMap(original);
162 assertEquals(original, map);
163 }
164
165 public void testIdentityHashMap() {
166 IdentityHashMap<Integer, Integer> map = Maps.newIdentityHashMap();
167 assertEquals(Collections.emptyMap(), map);
168 }
169
170 public void testConcurrentMap() {
171 ConcurrentMap<Integer, Integer> map = Maps.newConcurrentMap();
172 assertEquals(Collections.emptyMap(), map);
173 }
174
175 public void testTreeMap() {
176 TreeMap<Integer, Integer> map = Maps.newTreeMap();
177 assertEquals(Collections.emptyMap(), map);
178 assertNull(map.comparator());
179 }
180
181 public void testTreeMapDerived() {
182 TreeMap<Derived, Integer> map = Maps.newTreeMap();
183 assertEquals(Collections.emptyMap(), map);
184 map.put(new Derived("foo"), 1);
185 map.put(new Derived("bar"), 2);
186 assertThat(map.keySet()).has().exactly(
187 new Derived("bar"), new Derived("foo")).inOrder();
188 assertThat(map.values()).has().exactly(2, 1).inOrder();
189 assertNull(map.comparator());
190 }
191
192 public void testTreeMapNonGeneric() {
193 TreeMap<LegacyComparable, Integer> map = Maps.newTreeMap();
194 assertEquals(Collections.emptyMap(), map);
195 map.put(new LegacyComparable("foo"), 1);
196 map.put(new LegacyComparable("bar"), 2);
197 assertThat(map.keySet()).has().exactly(
198 new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
199 assertThat(map.values()).has().exactly(2, 1).inOrder();
200 assertNull(map.comparator());
201 }
202
203 public void testTreeMapWithComparator() {
204 TreeMap<Integer, Integer> map = Maps.newTreeMap(SOME_COMPARATOR);
205 assertEquals(Collections.emptyMap(), map);
206 assertSame(SOME_COMPARATOR, map.comparator());
207 }
208
209 public void testTreeMapWithInitialMap() {
210 SortedMap<Integer, Integer> map = Maps.newTreeMap();
211 map.put(5, 10);
212 map.put(3, 20);
213 map.put(1, 30);
214 TreeMap<Integer, Integer> copy = Maps.newTreeMap(map);
215 assertEquals(copy, map);
216 assertSame(copy.comparator(), map.comparator());
217 }
218
219 public enum SomeEnum { SOME_INSTANCE }
220
221 public void testEnumMap() {
222 EnumMap<SomeEnum, Integer> map = Maps.newEnumMap(SomeEnum.class);
223 assertEquals(Collections.emptyMap(), map);
224 map.put(SomeEnum.SOME_INSTANCE, 0);
225 assertEquals(Collections.singletonMap(SomeEnum.SOME_INSTANCE, 0), map);
226 }
227
228 public void testEnumMapNullClass() {
229 try {
230 Maps.<SomeEnum, Long>newEnumMap((Class<MapsTest.SomeEnum>) null);
231 fail("no exception thrown");
232 } catch (NullPointerException expected) {
233 }
234 }
235
236 public void testEnumMapWithInitialEnumMap() {
237 EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class);
238 original.put(SomeEnum.SOME_INSTANCE, 0);
239 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original);
240 assertEquals(original, copy);
241 }
242
243 public void testEnumMapWithInitialEmptyEnumMap() {
244 EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class);
245 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original);
246 assertEquals(original, copy);
247 assertNotSame(original, copy);
248 }
249
250 public void testEnumMapWithInitialMap() {
251 HashMap<SomeEnum, Integer> original = Maps.newHashMap();
252 original.put(SomeEnum.SOME_INSTANCE, 0);
253 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original);
254 assertEquals(original, copy);
255 }
256
257 public void testEnumMapWithInitialEmptyMap() {
258 Map<SomeEnum, Integer> original = Maps.newHashMap();
259 try {
260 Maps.newEnumMap(original);
261 fail("Empty map must result in an IllegalArgumentException");
262 } catch (IllegalArgumentException expected) {}
263 }
264
265 public void testToStringImplWithNullKeys() throws Exception {
266 Map<String, String> hashmap = Maps.newHashMap();
267 hashmap.put("foo", "bar");
268 hashmap.put(null, "baz");
269
270 assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap));
271 }
272
273 public void testToStringImplWithNullValues() throws Exception {
274 Map<String, String> hashmap = Maps.newHashMap();
275 hashmap.put("foo", "bar");
276 hashmap.put("baz", null);
277
278 assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap));
279 }
280
281 private static final Map<Integer, Integer> EMPTY
282 = Collections.emptyMap();
283 private static final Map<Integer, Integer> SINGLETON
284 = Collections.singletonMap(1, 2);
285
286 public void testMapDifferenceEmptyEmpty() {
287 MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, EMPTY);
288 assertTrue(diff.areEqual());
289 assertEquals(EMPTY, diff.entriesOnlyOnLeft());
290 assertEquals(EMPTY, diff.entriesOnlyOnRight());
291 assertEquals(EMPTY, diff.entriesInCommon());
292 assertEquals(EMPTY, diff.entriesDiffering());
293 assertEquals("equal", diff.toString());
294 }
295
296 public void testMapDifferenceEmptySingleton() {
297 MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, SINGLETON);
298 assertFalse(diff.areEqual());
299 assertEquals(EMPTY, diff.entriesOnlyOnLeft());
300 assertEquals(SINGLETON, diff.entriesOnlyOnRight());
301 assertEquals(EMPTY, diff.entriesInCommon());
302 assertEquals(EMPTY, diff.entriesDiffering());
303 assertEquals("not equal: only on right={1=2}", diff.toString());
304 }
305
306 public void testMapDifferenceSingletonEmpty() {
307 MapDifference<Integer, Integer> diff = Maps.difference(SINGLETON, EMPTY);
308 assertFalse(diff.areEqual());
309 assertEquals(SINGLETON, diff.entriesOnlyOnLeft());
310 assertEquals(EMPTY, diff.entriesOnlyOnRight());
311 assertEquals(EMPTY, diff.entriesInCommon());
312 assertEquals(EMPTY, diff.entriesDiffering());
313 assertEquals("not equal: only on left={1=2}", diff.toString());
314 }
315
316 public void testMapDifferenceTypical() {
317 Map<Integer, String> left = ImmutableMap.of(
318 1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
319 Map<Integer, String> right = ImmutableMap.of(
320 1, "a", 3, "f", 5, "g", 6, "z");
321
322 MapDifference<Integer, String> diff1 = Maps.difference(left, right);
323 assertFalse(diff1.areEqual());
324 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft());
325 assertEquals(ImmutableMap.of(6, "z"), diff1.entriesOnlyOnRight());
326 assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon());
327 assertEquals(ImmutableMap.of(3,
328 ValueDifferenceImpl.create("c", "f"), 5,
329 ValueDifferenceImpl.create("e", "g")),
330 diff1.entriesDiffering());
331 assertEquals("not equal: only on left={2=b, 4=d}: only on right={6=z}: "
332 + "value differences={3=(c, f), 5=(e, g)}", diff1.toString());
333
334 MapDifference<Integer, String> diff2 = Maps.difference(right, left);
335 assertFalse(diff2.areEqual());
336 assertEquals(ImmutableMap.of(6, "z"), diff2.entriesOnlyOnLeft());
337 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight());
338 assertEquals(ImmutableMap.of(1, "a"), diff2.entriesInCommon());
339 assertEquals(ImmutableMap.of(3,
340 ValueDifferenceImpl.create("f", "c"), 5,
341 ValueDifferenceImpl.create("g", "e")),
342 diff2.entriesDiffering());
343 assertEquals("not equal: only on left={6=z}: only on right={2=b, 4=d}: "
344 + "value differences={3=(f, c), 5=(g, e)}", diff2.toString());
345 }
346
347 public void testMapDifferenceEquals() {
348 Map<Integer, String> left = ImmutableMap.of(
349 1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
350 Map<Integer, String> right = ImmutableMap.of(
351 1, "a", 3, "f", 5, "g", 6, "z");
352 Map<Integer, String> right2 = ImmutableMap.of(
353 1, "a", 3, "h", 5, "g", 6, "z");
354 MapDifference<Integer, String> original = Maps.difference(left, right);
355 MapDifference<Integer, String> same = Maps.difference(left, right);
356 MapDifference<Integer, String> reverse = Maps.difference(right, left);
357 MapDifference<Integer, String> diff2 = Maps.difference(left, right2);
358
359 new EqualsTester()
360 .addEqualityGroup(original, same)
361 .addEqualityGroup(reverse)
362 .addEqualityGroup(diff2)
363 .testEquals();
364 }
365
366 public void testMapDifferencePredicateTypical() {
367 Map<Integer, String> left = ImmutableMap.of(
368 1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
369 Map<Integer, String> right = ImmutableMap.of(
370 1, "A", 3, "F", 5, "G", 6, "Z");
371
372
373
374 Equivalence<String> caseInsensitiveEquivalence = Equivalence.equals().onResultOf(
375 new Function<String, String>() {
376 @Override public String apply(String input) {
377 return input.toLowerCase();
378 }
379 });
380
381 MapDifference<Integer, String> diff1 = Maps.difference(left, right,
382 caseInsensitiveEquivalence);
383 assertFalse(diff1.areEqual());
384 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft());
385 assertEquals(ImmutableMap.of(6, "Z"), diff1.entriesOnlyOnRight());
386 assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon());
387 assertEquals(ImmutableMap.of(3,
388 ValueDifferenceImpl.create("c", "F"), 5,
389 ValueDifferenceImpl.create("e", "G")),
390 diff1.entriesDiffering());
391 assertEquals("not equal: only on left={2=b, 4=d}: only on right={6=Z}: "
392 + "value differences={3=(c, F), 5=(e, G)}", diff1.toString());
393
394 MapDifference<Integer, String> diff2 = Maps.difference(right, left,
395 caseInsensitiveEquivalence);
396 assertFalse(diff2.areEqual());
397 assertEquals(ImmutableMap.of(6, "Z"), diff2.entriesOnlyOnLeft());
398 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight());
399 assertEquals(ImmutableMap.of(1, "A"), diff2.entriesInCommon());
400 assertEquals(ImmutableMap.of(3,
401 ValueDifferenceImpl.create("F", "c"), 5,
402 ValueDifferenceImpl.create("G", "e")),
403 diff2.entriesDiffering());
404 assertEquals("not equal: only on left={6=Z}: only on right={2=b, 4=d}: "
405 + "value differences={3=(F, c), 5=(G, e)}", diff2.toString());
406 }
407
408 private static final SortedMap<Integer, Integer> SORTED_EMPTY = Maps.newTreeMap();
409 private static final SortedMap<Integer, Integer> SORTED_SINGLETON =
410 ImmutableSortedMap.of(1, 2);
411
412 public void testMapDifferenceOfSortedMapIsSorted() {
413 Map<Integer, Integer> map = SORTED_SINGLETON;
414 MapDifference<Integer, Integer> difference = Maps.difference(map, EMPTY);
415 assertTrue(difference instanceof SortedMapDifference);
416 }
417
418 public void testSortedMapDifferenceEmptyEmpty() {
419 SortedMapDifference<Integer, Integer> diff =
420 Maps.difference(SORTED_EMPTY, SORTED_EMPTY);
421 assertTrue(diff.areEqual());
422 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft());
423 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight());
424 assertEquals(SORTED_EMPTY, diff.entriesInCommon());
425 assertEquals(SORTED_EMPTY, diff.entriesDiffering());
426 assertEquals("equal", diff.toString());
427 }
428
429 public void testSortedMapDifferenceEmptySingleton() {
430 SortedMapDifference<Integer, Integer> diff =
431 Maps.difference(SORTED_EMPTY, SORTED_SINGLETON);
432 assertFalse(diff.areEqual());
433 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft());
434 assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnRight());
435 assertEquals(SORTED_EMPTY, diff.entriesInCommon());
436 assertEquals(SORTED_EMPTY, diff.entriesDiffering());
437 assertEquals("not equal: only on right={1=2}", diff.toString());
438 }
439
440 public void testSortedMapDifferenceSingletonEmpty() {
441 SortedMapDifference<Integer, Integer> diff =
442 Maps.difference(SORTED_SINGLETON, SORTED_EMPTY);
443 assertFalse(diff.areEqual());
444 assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnLeft());
445 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight());
446 assertEquals(SORTED_EMPTY, diff.entriesInCommon());
447 assertEquals(SORTED_EMPTY, diff.entriesDiffering());
448 assertEquals("not equal: only on left={1=2}", diff.toString());
449 }
450
451 public void testSortedMapDifferenceTypical() {
452 SortedMap<Integer, String> left =
453 ImmutableSortedMap.<Integer, String>reverseOrder()
454 .put(1, "a").put(2, "b").put(3, "c").put(4, "d").put(5, "e")
455 .build();
456
457 SortedMap<Integer, String> right =
458 ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z");
459
460 SortedMapDifference<Integer, String> diff1 =
461 Maps.difference(left, right);
462 assertFalse(diff1.areEqual());
463 assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
464 Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder();
465 assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
466 Maps.immutableEntry(6, "z"));
467 assertThat(diff1.entriesInCommon().entrySet()).has().item(
468 Maps.immutableEntry(1, "a"));
469 assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
470 Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")),
471 Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder();
472 assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: "
473 + "value differences={5=(e, g), 3=(c, f)}", diff1.toString());
474
475 SortedMapDifference<Integer, String> diff2 =
476 Maps.difference(right, left);
477 assertFalse(diff2.areEqual());
478 assertThat(diff2.entriesOnlyOnLeft().entrySet()).has().item(
479 Maps.immutableEntry(6, "z"));
480 assertThat(diff2.entriesOnlyOnRight().entrySet()).has().exactly(
481 Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
482 assertThat(diff1.entriesInCommon().entrySet()).has().item(
483 Maps.immutableEntry(1, "a"));
484 assertEquals(ImmutableMap.of(
485 3, ValueDifferenceImpl.create("f", "c"),
486 5, ValueDifferenceImpl.create("g", "e")),
487 diff2.entriesDiffering());
488 assertEquals("not equal: only on left={6=z}: only on right={2=b, 4=d}: "
489 + "value differences={3=(f, c), 5=(g, e)}", diff2.toString());
490 }
491
492 public void testSortedMapDifferenceImmutable() {
493 SortedMap<Integer, String> left = Maps.newTreeMap(
494 ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"));
495 SortedMap<Integer, String> right =
496 Maps.newTreeMap(ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z"));
497
498 SortedMapDifference<Integer, String> diff1 =
499 Maps.difference(left, right);
500 left.put(6, "z");
501 assertFalse(diff1.areEqual());
502 assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly(
503 Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
504 assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item(
505 Maps.immutableEntry(6, "z"));
506 assertThat(diff1.entriesInCommon().entrySet()).has().item(
507 Maps.immutableEntry(1, "a"));
508 assertThat(diff1.entriesDiffering().entrySet()).has().exactly(
509 Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")),
510 Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder();
511 try {
512 diff1.entriesInCommon().put(7, "x");
513 fail();
514 } catch (UnsupportedOperationException expected) {
515 }
516 try {
517 diff1.entriesOnlyOnLeft().put(7, "x");
518 fail();
519 } catch (UnsupportedOperationException expected) {
520 }
521 try {
522 diff1.entriesOnlyOnRight().put(7, "x");
523 fail();
524 } catch (UnsupportedOperationException expected) {
525 }
526 }
527
528 public void testSortedMapDifferenceEquals() {
529 SortedMap<Integer, String> left =
530 ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
531 SortedMap<Integer, String> right =
532 ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z");
533 SortedMap<Integer, String> right2 =
534 ImmutableSortedMap.of(1, "a", 3, "h", 5, "g", 6, "z");
535 SortedMapDifference<Integer, String> original =
536 Maps.difference(left, right);
537 SortedMapDifference<Integer, String> same =
538 Maps.difference(left, right);
539 SortedMapDifference<Integer, String> reverse =
540 Maps.difference(right, left);
541 SortedMapDifference<Integer, String> diff2 =
542 Maps.difference(left, right2);
543
544 new EqualsTester()
545 .addEqualityGroup(original, same)
546 .addEqualityGroup(reverse)
547 .addEqualityGroup(diff2)
548 .testEquals();
549 }
550
551 private static final Function<String, Integer> LENGTH_FUNCTION =
552 new Function<String, Integer>() {
553 @Override
554 public Integer apply(String input) {
555 return input.length();
556 }
557 };
558
559 public void testAsMap() {
560 Set<String> strings = ImmutableSet.of("one", "two", "three");
561 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
562 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
563 assertEquals(Integer.valueOf(5), map.get("three"));
564 assertNull(map.get("five"));
565 assertThat(map.entrySet()).has().exactly(
566 mapEntry("one", 3),
567 mapEntry("two", 3),
568 mapEntry("three", 5)).inOrder();
569 }
570
571 public void testAsMapReadsThrough() {
572 Set<String> strings = Sets.newLinkedHashSet();
573 Collections.addAll(strings, "one", "two", "three");
574 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
575 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
576 assertNull(map.get("four"));
577 strings.add("four");
578 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5, "four", 4), map);
579 assertEquals(Integer.valueOf(4), map.get("four"));
580 }
581
582 public void testAsMapWritesThrough() {
583 Set<String> strings = Sets.newLinkedHashSet();
584 Collections.addAll(strings, "one", "two", "three");
585 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
586 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
587 assertEquals(Integer.valueOf(3), map.remove("two"));
588 assertThat(strings).has().exactly("one", "three").inOrder();
589 }
590
591 public void testAsMapEmpty() {
592 Set<String> strings = ImmutableSet.of();
593 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
594 assertThat(map.entrySet()).isEmpty();
595 assertTrue(map.isEmpty());
596 assertNull(map.get("five"));
597 }
598
599 private static class NonNavigableSortedSet
600 extends ForwardingSortedSet<String> {
601 private final SortedSet<String> delegate = Sets.newTreeSet();
602
603 @Override
604 protected SortedSet<String> delegate() {
605 return delegate;
606 }
607 }
608
609 public void testAsMapReturnsSortedMapForSortedSetInput() {
610 Set<String> set = new NonNavigableSortedSet();
611 assertTrue(Maps.asMap(set, Functions.identity()) instanceof SortedMap);
612 }
613
614 public void testAsMapSorted() {
615 SortedSet<String> strings = new NonNavigableSortedSet();
616 Collections.addAll(strings, "one", "two", "three");
617 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
618 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
619 assertEquals(Integer.valueOf(5), map.get("three"));
620 assertNull(map.get("five"));
621 assertThat(map.entrySet()).has().exactly(
622 mapEntry("one", 3),
623 mapEntry("three", 5),
624 mapEntry("two", 3)).inOrder();
625 assertThat(map.tailMap("onea").entrySet()).has().exactly(
626 mapEntry("three", 5),
627 mapEntry("two", 3)).inOrder();
628 assertThat(map.subMap("one", "two").entrySet()).has().exactly(
629 mapEntry("one", 3),
630 mapEntry("three", 5)).inOrder();
631 }
632
633 public void testAsMapSortedReadsThrough() {
634 SortedSet<String> strings = new NonNavigableSortedSet();
635 Collections.addAll(strings, "one", "two", "three");
636 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
637 assertNull(map.comparator());
638 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map);
639 assertNull(map.get("four"));
640 strings.add("four");
641 assertEquals(
642 ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4),
643 map);
644 assertEquals(Integer.valueOf(4), map.get("four"));
645 SortedMap<String, Integer> headMap = map.headMap("two");
646 assertEquals(
647 ImmutableSortedMap.of("four", 4, "one", 3, "three", 5),
648 headMap);
649 strings.add("five");
650 strings.remove("one");
651 assertEquals(
652 ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
653 headMap);
654 assertThat(map.entrySet()).has().exactly(
655 mapEntry("five", 4),
656 mapEntry("four", 4),
657 mapEntry("three", 5),
658 mapEntry("two", 3)).inOrder();
659 }
660
661 public void testAsMapSortedWritesThrough() {
662 SortedSet<String> strings = new NonNavigableSortedSet();
663 Collections.addAll(strings, "one", "two", "three");
664 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
665 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
666 assertEquals(Integer.valueOf(3), map.remove("two"));
667 assertThat(strings).has().exactly("one", "three").inOrder();
668 }
669
670 public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() {
671 SortedMap<String, Integer> map = Maps.asMap(
672 new NonNavigableSortedSet(), LENGTH_FUNCTION);
673 try {
674 map.subMap("a", "z").keySet().add("a");
675 fail();
676 } catch (UnsupportedOperationException expected) {
677 }
678 try {
679 map.tailMap("a").keySet().add("a");
680 fail();
681 } catch (UnsupportedOperationException expected) {
682 }
683 try {
684 map.headMap("r").keySet().add("a");
685 fail();
686 } catch (UnsupportedOperationException expected) {
687 }
688 try {
689 map.headMap("r").tailMap("m").keySet().add("a");
690 fail();
691 } catch (UnsupportedOperationException expected) {
692 }
693 }
694
695 public void testAsMapSortedEmpty() {
696 SortedSet<String> strings = new NonNavigableSortedSet();
697 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
698 assertThat(map.entrySet()).isEmpty();
699 assertTrue(map.isEmpty());
700 assertNull(map.get("five"));
701 }
702
703 public void testToMap() {
704 Iterable<String> strings = ImmutableList.of("one", "two", "three");
705 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
706 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
707 assertThat(map.entrySet()).has().exactly(
708 mapEntry("one", 3),
709 mapEntry("two", 3),
710 mapEntry("three", 5)).inOrder();
711 }
712
713 public void testToMapIterator() {
714 Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator();
715 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
716 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
717 assertThat(map.entrySet()).has().exactly(
718 mapEntry("one", 3),
719 mapEntry("two", 3),
720 mapEntry("three", 5)).inOrder();
721 }
722
723 public void testToMapWithDuplicateKeys() {
724 Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one");
725 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
726 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
727 assertThat(map.entrySet()).has().exactly(
728 mapEntry("one", 3),
729 mapEntry("two", 3),
730 mapEntry("three", 5)).inOrder();
731 }
732
733 public void testToMapWithNullKeys() {
734 Iterable<String> strings = Arrays.asList("one", null, "three");
735 try {
736 Maps.toMap(strings, Functions.constant("foo"));
737 fail();
738 } catch (NullPointerException expected) {
739 }
740 }
741
742 public void testToMapWithNullValues() {
743 Iterable<String> strings = ImmutableList.of("one", "two", "three");
744 try {
745 Maps.toMap(strings, Functions.constant(null));
746 fail();
747 } catch (NullPointerException expected) {
748 }
749 }
750
751 private static final BiMap<Integer, String> INT_TO_STRING_MAP =
752 new ImmutableBiMap.Builder<Integer, String>()
753 .put(1, "one")
754 .put(2, "two")
755 .put(3, "three")
756 .build();
757
758 public void testUniqueIndexCollection() {
759 ImmutableMap<Integer, String> outputMap =
760 Maps.uniqueIndex(INT_TO_STRING_MAP.values(),
761 Functions.forMap(INT_TO_STRING_MAP.inverse()));
762 assertEquals(INT_TO_STRING_MAP, outputMap);
763 }
764
765 public void testUniqueIndexIterable() {
766 ImmutableMap<Integer, String> outputMap =
767 Maps.uniqueIndex(new Iterable<String>() {
768 @Override
769 public Iterator<String> iterator() {
770 return INT_TO_STRING_MAP.values().iterator();
771 }
772 },
773 Functions.forMap(INT_TO_STRING_MAP.inverse()));
774 assertEquals(INT_TO_STRING_MAP, outputMap);
775 }
776
777 public void testUniqueIndexIterator() {
778 ImmutableMap<Integer, String> outputMap =
779 Maps.uniqueIndex(INT_TO_STRING_MAP.values().iterator(),
780 Functions.forMap(INT_TO_STRING_MAP.inverse()));
781 assertEquals(INT_TO_STRING_MAP, outputMap);
782 }
783
784
785 public void testUniqueIndexDuplicates() {
786 try {
787 Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1));
788 fail();
789 } catch (IllegalArgumentException expected) {
790 }
791 }
792
793
794 public void testUniqueIndexNullValue() {
795 List<String> listWithNull = Lists.newArrayList((String) null);
796 try {
797 Maps.uniqueIndex(listWithNull, Functions.constant(1));
798 fail();
799 } catch (NullPointerException expected) {
800 }
801 }
802
803
804 public void testUniqueIndexNullKey() {
805 List<String> oneStringList = Lists.newArrayList("foo");
806 try {
807 Maps.uniqueIndex(oneStringList, Functions.constant(null));
808 fail();
809 } catch (NullPointerException expected) {
810 }
811 }
812
813 public void testAsConverter_nominal() throws Exception {
814 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
815 "one", 1,
816 "two", 2);
817 Converter<String, Integer> converter = Maps.asConverter(biMap);
818 for (Entry<String, Integer> entry : biMap.entrySet()) {
819 assertSame(entry.getValue(), converter.convert(entry.getKey()));
820 }
821 }
822
823 public void testAsConverter_inverse() throws Exception {
824 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
825 "one", 1,
826 "two", 2);
827 Converter<String, Integer> converter = Maps.asConverter(biMap);
828 for (Entry<String, Integer> entry : biMap.entrySet()) {
829 assertSame(entry.getKey(), converter.reverse().convert(entry.getValue()));
830 }
831 }
832
833 public void testAsConverter_noMapping() throws Exception {
834 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
835 "one", 1,
836 "two", 2);
837 Converter<String, Integer> converter = Maps.asConverter(biMap);
838 try {
839 converter.convert("three");
840 fail();
841 } catch (IllegalArgumentException expected) {
842 }
843 }
844
845 public void testAsConverter_nullConversions() throws Exception {
846 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
847 "one", 1,
848 "two", 2);
849 Converter<String, Integer> converter = Maps.asConverter(biMap);
850 assertNull(converter.convert(null));
851 assertNull(converter.reverse().convert(null));
852 }
853
854 public void testAsConverter_isAView() throws Exception {
855 BiMap<String, Integer> biMap = HashBiMap.create();
856 biMap.put("one", 1);
857 biMap.put("two", 2);
858 Converter<String, Integer> converter = Maps.asConverter(biMap);
859
860 assertSame(1, converter.convert("one"));
861 assertSame(2, converter.convert("two"));
862 try {
863 converter.convert("three");
864 fail();
865 } catch (IllegalArgumentException expected) {
866 }
867
868 biMap.put("three", 3);
869
870 assertSame(1, converter.convert("one"));
871 assertSame(2, converter.convert("two"));
872 assertSame(3, converter.convert("three"));
873 }
874
875 public void testAsConverter_withNullMapping() throws Exception {
876 BiMap<String, Integer> biMap = HashBiMap.create();
877 biMap.put("one", 1);
878 biMap.put("two", 2);
879 biMap.put("three", null);
880 try {
881 Maps.asConverter(biMap).convert("three");
882 fail();
883 } catch (IllegalArgumentException expected) {
884 }
885 }
886
887 public void testAsConverter_toString() {
888 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
889 "one", 1,
890 "two", 2);
891 Converter<String, Integer> converter = Maps.asConverter(biMap);
892 assertEquals("Maps.asConverter({one=1, two=2})", converter.toString());
893 }
894
895 public void testAsConverter_serialization() {
896 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
897 "one", 1,
898 "two", 2);
899 Converter<String, Integer> converter = Maps.asConverter(biMap);
900 SerializableTester.reserializeAndAssert(converter);
901 }
902
903 public void testUnmodifiableBiMap() {
904 BiMap<Integer, String> mod = HashBiMap.create();
905 mod.put(1, "one");
906 mod.put(2, "two");
907 mod.put(3, "three");
908
909 BiMap<Number, String> unmod = Maps.<Number, String>unmodifiableBiMap(mod);
910
911
912 assertSame(unmod.inverse(), unmod.inverse());
913 assertSame(unmod, unmod.inverse().inverse());
914
915
916 mod.put(4, "four");
917 assertEquals(true, unmod.get(4).equals("four"));
918 assertEquals(true, unmod.inverse().get("four").equals(4));
919
920
921 try {
922 unmod.put(4, "four");
923 fail("UnsupportedOperationException expected");
924 } catch (UnsupportedOperationException expected) {}
925 try {
926 unmod.forcePut(4, "four");
927 fail("UnsupportedOperationException expected");
928 } catch (UnsupportedOperationException expected) {}
929 try {
930 unmod.putAll(Collections.singletonMap(4, "four"));
931 fail("UnsupportedOperationException expected");
932 } catch (UnsupportedOperationException expected) {}
933
934
935 BiMap<String, Number> inverse = unmod.inverse();
936 try {
937 inverse.put("four", 4);
938 fail("UnsupportedOperationException expected");
939 } catch (UnsupportedOperationException expected) {}
940 try {
941 inverse.forcePut("four", 4);
942 fail("UnsupportedOperationException expected");
943 } catch (UnsupportedOperationException expected) {}
944 try {
945 inverse.putAll(Collections.singletonMap("four", 4));
946 fail("UnsupportedOperationException expected");
947 } catch (UnsupportedOperationException expected) {}
948 Set<String> values = unmod.values();
949 try {
950 values.remove("four");
951 fail("UnsupportedOperationException expected");
952 } catch (UnsupportedOperationException expected) {}
953 Set<Map.Entry<Number, String>> entries = unmod.entrySet();
954 Map.Entry<Number, String> entry = entries.iterator().next();
955 try {
956 entry.setValue("four");
957 fail("UnsupportedOperationException expected");
958 } catch (UnsupportedOperationException expected) {}
959 @SuppressWarnings("unchecked")
960 Map.Entry<Integer, String> entry2
961 = (Map.Entry<Integer, String>) entries.toArray()[0];
962 try {
963 entry2.setValue("four");
964 fail("UnsupportedOperationException expected");
965 } catch (UnsupportedOperationException expected) {}
966 }
967
968 public void testImmutableEntry() {
969 Map.Entry<String, Integer> e = Maps.immutableEntry("foo", 1);
970 assertEquals("foo", e.getKey());
971 assertEquals(1, (int) e.getValue());
972 try {
973 e.setValue(2);
974 fail("UnsupportedOperationException expected");
975 } catch (UnsupportedOperationException expected) {}
976 assertEquals("foo=1", e.toString());
977 assertEquals(101575, e.hashCode());
978 }
979
980 public void testImmutableEntryNull() {
981 Map.Entry<String, Integer> e
982 = Maps.immutableEntry((String) null, (Integer) null);
983 assertNull(e.getKey());
984 assertNull(e.getValue());
985 try {
986 e.setValue(null);
987 fail("UnsupportedOperationException expected");
988 } catch (UnsupportedOperationException expected) {}
989 assertEquals("null=null", e.toString());
990 assertEquals(0, e.hashCode());
991 }
992
993
994 public void testSynchronizedBiMap() {
995 BiMap<String, Integer> bimap = HashBiMap.create();
996 bimap.put("one", 1);
997 BiMap<String, Integer> sync = Maps.synchronizedBiMap(bimap);
998 bimap.put("two", 2);
999 sync.put("three", 3);
1000 assertEquals(ImmutableSet.of(1, 2, 3), bimap.inverse().keySet());
1001 assertEquals(ImmutableSet.of(1, 2, 3), sync.inverse().keySet());
1002 }
1003
1004 private static final Predicate<String> NOT_LENGTH_3
1005 = new Predicate<String>() {
1006 @Override
1007 public boolean apply(String input) {
1008 return input == null || input.length() != 3;
1009 }
1010 };
1011
1012 private static final Predicate<Integer> EVEN
1013 = new Predicate<Integer>() {
1014 @Override
1015 public boolean apply(Integer input) {
1016 return input == null || input % 2 == 0;
1017 }
1018 };
1019
1020 private static final Predicate<Entry<String, Integer>> CORRECT_LENGTH
1021 = new Predicate<Entry<String, Integer>>() {
1022 @Override
1023 public boolean apply(Entry<String, Integer> input) {
1024 return input.getKey().length() == input.getValue();
1025 }
1026 };
1027
1028 private static final Function<Integer, Double> SQRT_FUNCTION = new Function<Integer, Double>() {
1029 @Override
1030 public Double apply(Integer in) {
1031 return Math.sqrt(in);
1032 }
1033 };
1034
1035 public static class FilteredMapTest extends TestCase {
1036 Map<String, Integer> createUnfiltered() {
1037 return Maps.newHashMap();
1038 }
1039
1040 public void testFilteredKeysIllegalPut() {
1041 Map<String, Integer> unfiltered = createUnfiltered();
1042 Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3);
1043 filtered.put("a", 1);
1044 filtered.put("b", 2);
1045 assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered);
1046
1047 try {
1048 filtered.put("yyy", 3);
1049 fail();
1050 } catch (IllegalArgumentException expected) {}
1051 }
1052
1053 public void testFilteredKeysIllegalPutAll() {
1054 Map<String, Integer> unfiltered = createUnfiltered();
1055 Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3);
1056 filtered.put("a", 1);
1057 filtered.put("b", 2);
1058 assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered);
1059
1060 try {
1061 filtered.putAll(ImmutableMap.of("c", 3, "zzz", 4, "b", 5));
1062 fail();
1063 } catch (IllegalArgumentException expected) {}
1064
1065 assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered);
1066 }
1067
1068 public void testFilteredKeysFilteredReflectsBackingChanges() {
1069 Map<String, Integer> unfiltered = createUnfiltered();
1070 Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3);
1071 unfiltered.put("two", 2);
1072 unfiltered.put("three", 3);
1073 unfiltered.put("four", 4);
1074 assertEquals(ImmutableMap.of("two", 2, "three", 3, "four", 4), unfiltered);
1075 assertEquals(ImmutableMap.of("three", 3, "four", 4), filtered);
1076
1077 unfiltered.remove("three");
1078 assertEquals(ImmutableMap.of("two", 2, "four", 4), unfiltered);
1079 assertEquals(ImmutableMap.of("four", 4), filtered);
1080
1081 unfiltered.clear();
1082 assertEquals(ImmutableMap.of(), unfiltered);
1083 assertEquals(ImmutableMap.of(), filtered);
1084 }
1085
1086 public void testFilteredValuesIllegalPut() {
1087 Map<String, Integer> unfiltered = createUnfiltered();
1088 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
1089 filtered.put("a", 2);
1090 unfiltered.put("b", 4);
1091 unfiltered.put("c", 5);
1092 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
1093
1094 try {
1095 filtered.put("yyy", 3);
1096 fail();
1097 } catch (IllegalArgumentException expected) {}
1098 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
1099 }
1100
1101 public void testFilteredValuesIllegalPutAll() {
1102 Map<String, Integer> unfiltered = createUnfiltered();
1103 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
1104 filtered.put("a", 2);
1105 unfiltered.put("b", 4);
1106 unfiltered.put("c", 5);
1107 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
1108
1109 try {
1110 filtered.putAll(ImmutableMap.of("c", 4, "zzz", 5, "b", 6));
1111 fail();
1112 } catch (IllegalArgumentException expected) {}
1113 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
1114 }
1115
1116 public void testFilteredValuesIllegalSetValue() {
1117 Map<String, Integer> unfiltered = createUnfiltered();
1118 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
1119 filtered.put("a", 2);
1120 filtered.put("b", 4);
1121 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
1122
1123 Entry<String, Integer> entry = filtered.entrySet().iterator().next();
1124 try {
1125 entry.setValue(5);
1126 fail();
1127 } catch (IllegalArgumentException expected) {}
1128
1129 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
1130 }
1131
1132 public void testFilteredValuesClear() {
1133 Map<String, Integer> unfiltered = createUnfiltered();
1134 unfiltered.put("one", 1);
1135 unfiltered.put("two", 2);
1136 unfiltered.put("three", 3);
1137 unfiltered.put("four", 4);
1138 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
1139 assertEquals(ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4),
1140 unfiltered);
1141 assertEquals(ImmutableMap.of("two", 2, "four", 4), filtered);
1142
1143 filtered.clear();
1144 assertEquals(ImmutableMap.of("one", 1, "three", 3), unfiltered);
1145 assertTrue(filtered.isEmpty());
1146 }
1147
1148 public void testFilteredEntriesIllegalPut() {
1149 Map<String, Integer> unfiltered = createUnfiltered();
1150 unfiltered.put("cat", 3);
1151 unfiltered.put("dog", 2);
1152 unfiltered.put("horse", 5);
1153 Map<String, Integer> filtered
1154 = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
1155 assertEquals(ImmutableMap.of("cat", 3, "horse", 5), filtered);
1156
1157 filtered.put("chicken", 7);
1158 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);
1159
1160 try {
1161 filtered.put("cow", 7);
1162 fail();
1163 } catch (IllegalArgumentException expected) {}
1164 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);
1165 }
1166
1167 public void testFilteredEntriesIllegalPutAll() {
1168 Map<String, Integer> unfiltered = createUnfiltered();
1169 unfiltered.put("cat", 3);
1170 unfiltered.put("dog", 2);
1171 unfiltered.put("horse", 5);
1172 Map<String, Integer> filtered
1173 = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
1174 assertEquals(ImmutableMap.of("cat", 3, "horse", 5), filtered);
1175
1176 filtered.put("chicken", 7);
1177 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);
1178
1179 try {
1180 filtered.putAll(ImmutableMap.of("sheep", 5, "cow", 7));
1181 fail();
1182 } catch (IllegalArgumentException expected) {}
1183 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);
1184 }
1185
1186 public void testFilteredEntriesObjectPredicate() {
1187 Map<String, Integer> unfiltered = createUnfiltered();
1188 unfiltered.put("cat", 3);
1189 unfiltered.put("dog", 2);
1190 unfiltered.put("horse", 5);
1191 Predicate<Object> predicate = Predicates.alwaysFalse();
1192 Map<String, Integer> filtered
1193 = Maps.filterEntries(unfiltered, predicate);
1194 assertTrue(filtered.isEmpty());
1195 }
1196
1197 public void testFilteredEntriesWildCardEntryPredicate() {
1198 Map<String, Integer> unfiltered = createUnfiltered();
1199 unfiltered.put("cat", 3);
1200 unfiltered.put("dog", 2);
1201 unfiltered.put("horse", 5);
1202 Predicate<Entry<?, ?>> predicate = new Predicate<Entry<?, ?>>() {
1203 @Override
1204 public boolean apply(Entry<?, ?> input) {
1205 return "cat".equals(input.getKey())
1206 || Integer.valueOf(2) == input.getValue();
1207 }
1208 };
1209 Map<String, Integer> filtered
1210 = Maps.filterEntries(unfiltered, predicate);
1211 assertEquals(ImmutableMap.of("cat", 3, "dog", 2), filtered);
1212 }
1213 }
1214
1215 public static class FilteredSortedMapTest extends FilteredMapTest {
1216 @Override
1217 SortedMap<String, Integer> createUnfiltered() {
1218 return Maps.newTreeMap();
1219 }
1220
1221 public void testFilterKeysIdentifiesSortedMap() {
1222 SortedMap<String, Integer> map = createUnfiltered();
1223 assertTrue(Maps.filterKeys((Map<String, Integer>) map, NOT_LENGTH_3)
1224 instanceof SortedMap);
1225 }
1226
1227 public void testFilterValuesIdentifiesSortedMap() {
1228 SortedMap<String, Integer> map = createUnfiltered();
1229 assertTrue(Maps.filterValues((Map<String, Integer>) map, EVEN)
1230 instanceof SortedMap);
1231 }
1232
1233 public void testFilterEntriesIdentifiesSortedMap() {
1234 SortedMap<String, Integer> map = createUnfiltered();
1235 assertTrue(Maps.filterEntries((Map<String, Integer>) map, CORRECT_LENGTH)
1236 instanceof SortedMap);
1237 }
1238
1239 public void testFirstAndLastKeyFilteredMap() {
1240 SortedMap<String, Integer> unfiltered = createUnfiltered();
1241 unfiltered.put("apple", 2);
1242 unfiltered.put("banana", 6);
1243 unfiltered.put("cat", 3);
1244 unfiltered.put("dog", 5);
1245
1246 SortedMap<String, Integer> filtered = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
1247 assertEquals("banana", filtered.firstKey());
1248 assertEquals("cat", filtered.lastKey());
1249 }
1250
1251 public void testHeadSubTailMap_FilteredMap() {
1252 SortedMap<String, Integer> unfiltered = createUnfiltered();
1253 unfiltered.put("apple", 2);
1254 unfiltered.put("banana", 6);
1255 unfiltered.put("cat", 4);
1256 unfiltered.put("dog", 3);
1257 SortedMap<String, Integer> filtered = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
1258
1259 assertEquals(ImmutableMap.of("banana", 6), filtered.headMap("dog"));
1260 assertEquals(ImmutableMap.of(), filtered.headMap("banana"));
1261 assertEquals(ImmutableMap.of("banana", 6, "dog", 3), filtered.headMap("emu"));
1262
1263 assertEquals(ImmutableMap.of("banana", 6), filtered.subMap("banana", "dog"));
1264 assertEquals(ImmutableMap.of("dog", 3), filtered.subMap("cat", "emu"));
1265
1266 assertEquals(ImmutableMap.of("dog", 3), filtered.tailMap("cat"));
1267 assertEquals(ImmutableMap.of("banana", 6, "dog", 3), filtered.tailMap("banana"));
1268 }
1269 }
1270
1271 public static class FilteredBiMapTest extends FilteredMapTest {
1272 @Override
1273 BiMap<String, Integer> createUnfiltered() {
1274 return HashBiMap.create();
1275 }
1276
1277 public void testFilterKeysIdentifiesBiMap() {
1278 BiMap<String, Integer> map = createUnfiltered();
1279 assertTrue(Maps.filterKeys((Map<String, Integer>) map, NOT_LENGTH_3)
1280 instanceof BiMap);
1281 }
1282
1283 public void testFilterValuesIdentifiesBiMap() {
1284 BiMap<String, Integer> map = createUnfiltered();
1285 assertTrue(Maps.filterValues((Map<String, Integer>) map, EVEN)
1286 instanceof BiMap);
1287 }
1288
1289 public void testFilterEntriesIdentifiesBiMap() {
1290 BiMap<String, Integer> map = createUnfiltered();
1291 assertTrue(Maps.filterEntries((Map<String, Integer>) map, CORRECT_LENGTH)
1292 instanceof BiMap);
1293 }
1294 }
1295
1296 public void testTransformValues() {
1297 Map<String, Integer> map = ImmutableMap.of("a", 4, "b", 9);
1298 Map<String, Double> transformed = transformValues(map, SQRT_FUNCTION);
1299
1300 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed);
1301 }
1302
1303 public void testTransformValuesSecretlySorted() {
1304 Map<String, Integer> map =
1305 sortedNotNavigable(ImmutableSortedMap.of("a", 4, "b", 9));
1306 Map<String, Double> transformed = transformValues(map, SQRT_FUNCTION);
1307
1308 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed);
1309 assertTrue(transformed instanceof SortedMap);
1310 }
1311
1312 public void testTransformEntries() {
1313 Map<String, String> map = ImmutableMap.of("a", "4", "b", "9");
1314 EntryTransformer<String, String, String> concat =
1315 new EntryTransformer<String, String, String>() {
1316 @Override
1317 public String transformEntry(String key, String value) {
1318 return key + value;
1319 }
1320 };
1321 Map<String, String> transformed = transformEntries(map, concat);
1322
1323 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed);
1324 }
1325
1326 public void testTransformEntriesSecretlySorted() {
1327 Map<String, String> map = ImmutableSortedMap.of("a", "4", "b", "9");
1328 EntryTransformer<String, String, String> concat =
1329 new EntryTransformer<String, String, String>() {
1330 @Override
1331 public String transformEntry(String key, String value) {
1332 return key + value;
1333 }
1334 };
1335 Map<String, String> transformed = transformEntries(map, concat);
1336
1337 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed);
1338 assertTrue(transformed instanceof SortedMap);
1339 }
1340
1341 @SuppressWarnings("unused")
1342 public void testTransformEntriesGenerics() {
1343 Map<Object, Object> map1 = ImmutableMap.<Object, Object>of(1, 2);
1344 Map<Object, Number> map2 = ImmutableMap.<Object, Number>of(1, 2);
1345 Map<Object, Integer> map3 = ImmutableMap.<Object, Integer>of(1, 2);
1346 Map<Number, Object> map4 = ImmutableMap.<Number, Object>of(1, 2);
1347 Map<Number, Number> map5 = ImmutableMap.<Number, Number>of(1, 2);
1348 Map<Number, Integer> map6 = ImmutableMap.<Number, Integer>of(1, 2);
1349 Map<Integer, Object> map7 = ImmutableMap.<Integer, Object>of(1, 2);
1350 Map<Integer, Number> map8 = ImmutableMap.<Integer, Number>of(1, 2);
1351 Map<Integer, Integer> map9 = ImmutableMap.<Integer, Integer>of(1, 2);
1352 Map<? extends Number, ? extends Number> map0 = ImmutableMap.of(1, 2);
1353
1354 EntryTransformer<Number, Number, Double> transformer =
1355 new EntryTransformer<Number, Number, Double>() {
1356 @Override
1357 public Double transformEntry(Number key, Number value) {
1358 return key.doubleValue() + value.doubleValue();
1359 }
1360 };
1361
1362 Map<Object, Double> objectKeyed;
1363 Map<Number, Double> numberKeyed;
1364 Map<Integer, Double> integerKeyed;
1365
1366 numberKeyed = transformEntries(map5, transformer);
1367 numberKeyed = transformEntries(map6, transformer);
1368 integerKeyed = transformEntries(map8, transformer);
1369 integerKeyed = transformEntries(map9, transformer);
1370
1371 Map<? extends Number, Double> wildcarded = transformEntries(map0, transformer);
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396 }
1397
1398 public void testTransformEntriesExample() {
1399 Map<String, Boolean> options =
1400 ImmutableMap.of("verbose", true, "sort", false);
1401 EntryTransformer<String, Boolean, String> flagPrefixer =
1402 new EntryTransformer<String, Boolean, String>() {
1403 @Override
1404 public String transformEntry(String key, Boolean value) {
1405 return value ? key : "no" + key;
1406 }
1407 };
1408 Map<String, String> transformed = transformEntries(options, flagPrefixer);
1409 assertEquals("{verbose=verbose, sort=nosort}", transformed.toString());
1410 }
1411
1412
1413 private static <K, V> SortedMap<K, V> sortedNotNavigable(
1414 final SortedMap<K, V> map) {
1415 return new ForwardingSortedMap<K, V>() {
1416 @Override protected SortedMap<K, V> delegate() {
1417 return map;
1418 }
1419 };
1420 }
1421
1422 public void testSortedMapTransformValues() {
1423 SortedMap<String, Integer> map =
1424 sortedNotNavigable(ImmutableSortedMap.of("a", 4, "b", 9));
1425 SortedMap<String, Double> transformed =
1426 transformValues(map, SQRT_FUNCTION);
1427
1428
1429
1430
1431
1432 assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed);
1433 }
1434
1435 public void testSortedMapTransformEntries() {
1436 SortedMap<String, String> map =
1437 sortedNotNavigable(ImmutableSortedMap.of("a", "4", "b", "9"));
1438 EntryTransformer<String, String, String> concat =
1439 new EntryTransformer<String, String, String>() {
1440 @Override
1441 public String transformEntry(String key, String value) {
1442 return key + value;
1443 }
1444 };
1445 SortedMap<String, String> transformed = transformEntries(map, concat);
1446
1447
1448
1449
1450
1451 assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed);
1452 }
1453 }
1454