1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 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.Maps.unmodifiableNavigableMap; 22 import static com.google.common.collect.testing.Helpers.mapEntry; 23 import static com.google.common.truth.Truth.assertThat; 24 import static com.google.common.truth.Truth.assertWithMessage; 25 import static java.util.Arrays.asList; 26 27 import com.google.common.annotations.GwtCompatible; 28 import com.google.common.annotations.GwtIncompatible; 29 import com.google.common.base.Converter; 30 import com.google.common.base.Equivalence; 31 import com.google.common.base.Function; 32 import com.google.common.base.Functions; 33 import com.google.common.collect.Maps.EntryTransformer; 34 import com.google.common.collect.Maps.ValueDifferenceImpl; 35 import com.google.common.testing.EqualsTester; 36 import com.google.common.testing.NullPointerTester; 37 import com.google.common.testing.SerializableTester; 38 import java.io.IOException; 39 import java.io.StringReader; 40 import java.lang.reflect.Field; 41 import java.util.Arrays; 42 import java.util.Collection; 43 import java.util.Collections; 44 import java.util.Comparator; 45 import java.util.EnumMap; 46 import java.util.Enumeration; 47 import java.util.HashMap; 48 import java.util.IdentityHashMap; 49 import java.util.Iterator; 50 import java.util.LinkedHashMap; 51 import java.util.List; 52 import java.util.Map; 53 import java.util.Map.Entry; 54 import java.util.NavigableMap; 55 import java.util.NavigableSet; 56 import java.util.Properties; 57 import java.util.Set; 58 import java.util.SortedMap; 59 import java.util.SortedSet; 60 import java.util.TreeMap; 61 import java.util.concurrent.ConcurrentMap; 62 import junit.framework.TestCase; 63 64 /** 65 * Unit test for {@code Maps}. 66 * 67 * @author Kevin Bourrillion 68 * @author Mike Bostock 69 * @author Jared Levy 70 */ 71 @GwtCompatible(emulated = true) 72 public class MapsTest extends TestCase { 73 74 private static final Comparator<Integer> SOME_COMPARATOR = Collections.reverseOrder(); 75 testHashMap()76 public void testHashMap() { 77 HashMap<Integer, Integer> map = Maps.newHashMap(); 78 assertEquals(Collections.emptyMap(), map); 79 } 80 testHashMapWithInitialMap()81 public void testHashMapWithInitialMap() { 82 Map<String, Integer> original = new TreeMap<>(); 83 original.put("a", 1); 84 original.put("b", 2); 85 original.put("c", 3); 86 HashMap<String, Integer> map = Maps.newHashMap(original); 87 assertEquals(original, map); 88 } 89 testHashMapGeneralizesTypes()90 public void testHashMapGeneralizesTypes() { 91 Map<String, Integer> original = new TreeMap<>(); 92 original.put("a", 1); 93 original.put("b", 2); 94 original.put("c", 3); 95 HashMap<Object, Object> map = 96 Maps.newHashMap((Map<? extends Object, ? extends Object>) original); 97 assertEquals(original, map); 98 } 99 testCapacityForNegativeSizeFails()100 public void testCapacityForNegativeSizeFails() { 101 try { 102 Maps.capacity(-1); 103 fail("Negative expected size must result in IllegalArgumentException"); 104 } catch (IllegalArgumentException expected) { 105 } 106 } 107 108 /** 109 * Tests that nHMWES makes hash maps large enough that adding the expected number of elements 110 * won't cause a rehash. 111 * 112 * <p>As of jdk7u40, HashMap has an empty-map optimization. The argument to new HashMap(int) is 113 * noted, but the initial table is a zero-length array. 114 * 115 * <p>This test may fail miserably on non-OpenJDK environments... 116 */ 117 @GwtIncompatible // reflection 118 @AndroidIncompatible // relies on assumptions about OpenJDK testNewHashMapWithExpectedSize_wontGrow()119 public void testNewHashMapWithExpectedSize_wontGrow() throws Exception { 120 // before jdk7u40: creates one-bucket table 121 // after jdk7u40: creates empty table 122 assertTrue(bucketsOf(Maps.newHashMapWithExpectedSize(0)) <= 1); 123 124 for (int size = 1; size < 200; size++) { 125 assertWontGrow( 126 size, 127 new HashMap<>(), 128 Maps.newHashMapWithExpectedSize(size), 129 Maps.newHashMapWithExpectedSize(size)); 130 } 131 } 132 133 /** Same test as above but for newLinkedHashMapWithExpectedSize */ 134 @GwtIncompatible // reflection 135 @AndroidIncompatible // relies on assumptions about OpenJDK testNewLinkedHashMapWithExpectedSize_wontGrow()136 public void testNewLinkedHashMapWithExpectedSize_wontGrow() throws Exception { 137 assertTrue(bucketsOf(Maps.newLinkedHashMapWithExpectedSize(0)) <= 1); 138 139 for (int size = 1; size < 200; size++) { 140 assertWontGrow( 141 size, 142 new LinkedHashMap<>(), 143 Maps.newLinkedHashMapWithExpectedSize(size), 144 Maps.newLinkedHashMapWithExpectedSize(size)); 145 } 146 } 147 148 @GwtIncompatible // reflection assertWontGrow( int size, HashMap<Object, Object> referenceMap, HashMap<Object, Object> map1, HashMap<Object, Object> map2)149 private static void assertWontGrow( 150 int size, 151 HashMap<Object, Object> referenceMap, 152 HashMap<Object, Object> map1, 153 HashMap<Object, Object> map2) 154 throws Exception { 155 // Only start measuring table size after the first element inserted, to 156 // deal with empty-map optimization. 157 map1.put(0, null); 158 159 int initialBuckets = bucketsOf(map1); 160 161 for (int i = 1; i < size; i++) { 162 map1.put(i, null); 163 } 164 assertWithMessage("table size after adding " + size + " elements") 165 .that(bucketsOf(map1)) 166 .isEqualTo(initialBuckets); 167 168 /* 169 * Something slightly different happens when the entries are added all at 170 * once; make sure that passes too. 171 */ 172 map2.putAll(map1); 173 assertWithMessage("table size after adding " + size + " elements") 174 .that(bucketsOf(map1)) 175 .isEqualTo(initialBuckets); 176 177 // Ensure that referenceMap, which doesn't use WithExpectedSize, ends up with the same table 178 // size as the other two maps. If it ended up with a smaller size that would imply that we 179 // computed the wrong initial capacity. 180 for (int i = 0; i < size; i++) { 181 referenceMap.put(i, null); 182 } 183 assertWithMessage("table size after adding " + size + " elements") 184 .that(initialBuckets) 185 .isAtMost(bucketsOf(referenceMap)); 186 } 187 188 @GwtIncompatible // reflection bucketsOf(HashMap<?, ?> hashMap)189 private static int bucketsOf(HashMap<?, ?> hashMap) throws Exception { 190 Field tableField = HashMap.class.getDeclaredField("table"); 191 tableField.setAccessible(true); 192 Object[] table = (Object[]) tableField.get(hashMap); 193 // In JDK8, table is set lazily, so it may be null. 194 return table == null ? 0 : table.length; 195 } 196 testCapacityForLargeSizes()197 public void testCapacityForLargeSizes() { 198 int[] largeExpectedSizes = 199 new int[] { 200 Integer.MAX_VALUE / 2 - 1, 201 Integer.MAX_VALUE / 2, 202 Integer.MAX_VALUE / 2 + 1, 203 Integer.MAX_VALUE - 1, 204 Integer.MAX_VALUE 205 }; 206 for (int expectedSize : largeExpectedSizes) { 207 int capacity = Maps.capacity(expectedSize); 208 assertTrue( 209 "capacity (" + capacity + ") must be >= expectedSize (" + expectedSize + ")", 210 capacity >= expectedSize); 211 } 212 } 213 testLinkedHashMap()214 public void testLinkedHashMap() { 215 LinkedHashMap<Integer, Integer> map = Maps.newLinkedHashMap(); 216 assertEquals(Collections.emptyMap(), map); 217 } 218 219 @SuppressWarnings("serial") testLinkedHashMapWithInitialMap()220 public void testLinkedHashMapWithInitialMap() { 221 Map<String, String> map = 222 new LinkedHashMap<String, String>( 223 ImmutableMap.of( 224 "Hello", "World", 225 "first", "second", 226 "polygene", "lubricants", 227 "alpha", "betical")); 228 229 LinkedHashMap<String, String> copy = Maps.newLinkedHashMap(map); 230 231 Iterator<Entry<String, String>> iter = copy.entrySet().iterator(); 232 assertTrue(iter.hasNext()); 233 Entry<String, String> entry = iter.next(); 234 assertEquals("Hello", entry.getKey()); 235 assertEquals("World", entry.getValue()); 236 assertTrue(iter.hasNext()); 237 238 entry = iter.next(); 239 assertEquals("first", entry.getKey()); 240 assertEquals("second", entry.getValue()); 241 assertTrue(iter.hasNext()); 242 243 entry = iter.next(); 244 assertEquals("polygene", entry.getKey()); 245 assertEquals("lubricants", entry.getValue()); 246 assertTrue(iter.hasNext()); 247 248 entry = iter.next(); 249 assertEquals("alpha", entry.getKey()); 250 assertEquals("betical", entry.getValue()); 251 assertFalse(iter.hasNext()); 252 } 253 testLinkedHashMapGeneralizesTypes()254 public void testLinkedHashMapGeneralizesTypes() { 255 Map<String, Integer> original = new LinkedHashMap<>(); 256 original.put("a", 1); 257 original.put("b", 2); 258 original.put("c", 3); 259 HashMap<Object, Object> map = Maps.<Object, Object>newLinkedHashMap(original); 260 assertEquals(original, map); 261 } 262 263 // Intentionally using IdentityHashMap to test creation. 264 @SuppressWarnings("IdentityHashMapBoxing") testIdentityHashMap()265 public void testIdentityHashMap() { 266 IdentityHashMap<Integer, Integer> map = Maps.newIdentityHashMap(); 267 assertEquals(Collections.emptyMap(), map); 268 } 269 testConcurrentMap()270 public void testConcurrentMap() { 271 ConcurrentMap<Integer, Integer> map = Maps.newConcurrentMap(); 272 assertEquals(Collections.emptyMap(), map); 273 } 274 testTreeMap()275 public void testTreeMap() { 276 TreeMap<Integer, Integer> map = Maps.newTreeMap(); 277 assertEquals(Collections.emptyMap(), map); 278 assertNull(map.comparator()); 279 } 280 testTreeMapDerived()281 public void testTreeMapDerived() { 282 TreeMap<Derived, Integer> map = Maps.newTreeMap(); 283 assertEquals(Collections.emptyMap(), map); 284 map.put(new Derived("foo"), 1); 285 map.put(new Derived("bar"), 2); 286 assertThat(map.keySet()).containsExactly(new Derived("bar"), new Derived("foo")).inOrder(); 287 assertThat(map.values()).containsExactly(2, 1).inOrder(); 288 assertNull(map.comparator()); 289 } 290 testTreeMapNonGeneric()291 public void testTreeMapNonGeneric() { 292 TreeMap<LegacyComparable, Integer> map = Maps.newTreeMap(); 293 assertEquals(Collections.emptyMap(), map); 294 map.put(new LegacyComparable("foo"), 1); 295 map.put(new LegacyComparable("bar"), 2); 296 assertThat(map.keySet()) 297 .containsExactly(new LegacyComparable("bar"), new LegacyComparable("foo")) 298 .inOrder(); 299 assertThat(map.values()).containsExactly(2, 1).inOrder(); 300 assertNull(map.comparator()); 301 } 302 testTreeMapWithComparator()303 public void testTreeMapWithComparator() { 304 TreeMap<Integer, Integer> map = Maps.newTreeMap(SOME_COMPARATOR); 305 assertEquals(Collections.emptyMap(), map); 306 assertSame(SOME_COMPARATOR, map.comparator()); 307 } 308 testTreeMapWithInitialMap()309 public void testTreeMapWithInitialMap() { 310 SortedMap<Integer, Integer> map = Maps.newTreeMap(); 311 map.put(5, 10); 312 map.put(3, 20); 313 map.put(1, 30); 314 TreeMap<Integer, Integer> copy = Maps.newTreeMap(map); 315 assertEquals(copy, map); 316 assertSame(copy.comparator(), map.comparator()); 317 } 318 319 public enum SomeEnum { 320 SOME_INSTANCE 321 } 322 testEnumMap()323 public void testEnumMap() { 324 EnumMap<SomeEnum, Integer> map = Maps.newEnumMap(SomeEnum.class); 325 assertEquals(Collections.emptyMap(), map); 326 map.put(SomeEnum.SOME_INSTANCE, 0); 327 assertEquals(Collections.singletonMap(SomeEnum.SOME_INSTANCE, 0), map); 328 } 329 testEnumMapNullClass()330 public void testEnumMapNullClass() { 331 try { 332 Maps.<SomeEnum, Long>newEnumMap((Class<MapsTest.SomeEnum>) null); 333 fail("no exception thrown"); 334 } catch (NullPointerException expected) { 335 } 336 } 337 testEnumMapWithInitialEnumMap()338 public void testEnumMapWithInitialEnumMap() { 339 EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class); 340 original.put(SomeEnum.SOME_INSTANCE, 0); 341 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original); 342 assertEquals(original, copy); 343 } 344 testEnumMapWithInitialEmptyEnumMap()345 public void testEnumMapWithInitialEmptyEnumMap() { 346 EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class); 347 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original); 348 assertEquals(original, copy); 349 assertNotSame(original, copy); 350 } 351 testEnumMapWithInitialMap()352 public void testEnumMapWithInitialMap() { 353 HashMap<SomeEnum, Integer> original = Maps.newHashMap(); 354 original.put(SomeEnum.SOME_INSTANCE, 0); 355 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original); 356 assertEquals(original, copy); 357 } 358 testEnumMapWithInitialEmptyMap()359 public void testEnumMapWithInitialEmptyMap() { 360 Map<SomeEnum, Integer> original = Maps.newHashMap(); 361 try { 362 Maps.newEnumMap(original); 363 fail("Empty map must result in an IllegalArgumentException"); 364 } catch (IllegalArgumentException expected) { 365 } 366 } 367 testToStringImplWithNullKeys()368 public void testToStringImplWithNullKeys() throws Exception { 369 Map<String, String> hashmap = Maps.newHashMap(); 370 hashmap.put("foo", "bar"); 371 hashmap.put(null, "baz"); 372 373 assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap)); 374 } 375 testToStringImplWithNullValues()376 public void testToStringImplWithNullValues() throws Exception { 377 Map<String, String> hashmap = Maps.newHashMap(); 378 hashmap.put("foo", "bar"); 379 hashmap.put("baz", null); 380 381 assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap)); 382 } 383 384 @GwtIncompatible // NullPointerTester 385 @AndroidIncompatible // see ImmutableTableTest.testNullPointerInstance testNullPointerExceptions()386 public void testNullPointerExceptions() { 387 new NullPointerTester().testAllPublicStaticMethods(Maps.class); 388 } 389 390 private static final Map<Integer, Integer> EMPTY = Collections.emptyMap(); 391 private static final Map<Integer, Integer> SINGLETON = Collections.singletonMap(1, 2); 392 testMapDifferenceEmptyEmpty()393 public void testMapDifferenceEmptyEmpty() { 394 MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, EMPTY); 395 assertTrue(diff.areEqual()); 396 assertEquals(EMPTY, diff.entriesOnlyOnLeft()); 397 assertEquals(EMPTY, diff.entriesOnlyOnRight()); 398 assertEquals(EMPTY, diff.entriesInCommon()); 399 assertEquals(EMPTY, diff.entriesDiffering()); 400 assertEquals("equal", diff.toString()); 401 } 402 testMapDifferenceEmptySingleton()403 public void testMapDifferenceEmptySingleton() { 404 MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, SINGLETON); 405 assertFalse(diff.areEqual()); 406 assertEquals(EMPTY, diff.entriesOnlyOnLeft()); 407 assertEquals(SINGLETON, diff.entriesOnlyOnRight()); 408 assertEquals(EMPTY, diff.entriesInCommon()); 409 assertEquals(EMPTY, diff.entriesDiffering()); 410 assertEquals("not equal: only on right={1=2}", diff.toString()); 411 } 412 testMapDifferenceSingletonEmpty()413 public void testMapDifferenceSingletonEmpty() { 414 MapDifference<Integer, Integer> diff = Maps.difference(SINGLETON, EMPTY); 415 assertFalse(diff.areEqual()); 416 assertEquals(SINGLETON, diff.entriesOnlyOnLeft()); 417 assertEquals(EMPTY, diff.entriesOnlyOnRight()); 418 assertEquals(EMPTY, diff.entriesInCommon()); 419 assertEquals(EMPTY, diff.entriesDiffering()); 420 assertEquals("not equal: only on left={1=2}", diff.toString()); 421 } 422 testMapDifferenceTypical()423 public void testMapDifferenceTypical() { 424 Map<Integer, String> left = ImmutableMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 425 Map<Integer, String> right = ImmutableMap.of(1, "a", 3, "f", 5, "g", 6, "z"); 426 427 MapDifference<Integer, String> diff1 = Maps.difference(left, right); 428 assertFalse(diff1.areEqual()); 429 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft()); 430 assertEquals(ImmutableMap.of(6, "z"), diff1.entriesOnlyOnRight()); 431 assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon()); 432 assertEquals( 433 ImmutableMap.of( 434 3, ValueDifferenceImpl.create("c", "f"), 5, ValueDifferenceImpl.create("e", "g")), 435 diff1.entriesDiffering()); 436 assertEquals( 437 "not equal: only on left={2=b, 4=d}: only on right={6=z}: " 438 + "value differences={3=(c, f), 5=(e, g)}", 439 diff1.toString()); 440 441 MapDifference<Integer, String> diff2 = Maps.difference(right, left); 442 assertFalse(diff2.areEqual()); 443 assertEquals(ImmutableMap.of(6, "z"), diff2.entriesOnlyOnLeft()); 444 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight()); 445 assertEquals(ImmutableMap.of(1, "a"), diff2.entriesInCommon()); 446 assertEquals( 447 ImmutableMap.of( 448 3, ValueDifferenceImpl.create("f", "c"), 5, ValueDifferenceImpl.create("g", "e")), 449 diff2.entriesDiffering()); 450 assertEquals( 451 "not equal: only on left={6=z}: only on right={2=b, 4=d}: " 452 + "value differences={3=(f, c), 5=(g, e)}", 453 diff2.toString()); 454 } 455 testMapDifferenceEquals()456 public void testMapDifferenceEquals() { 457 Map<Integer, String> left = ImmutableMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 458 Map<Integer, String> right = ImmutableMap.of(1, "a", 3, "f", 5, "g", 6, "z"); 459 Map<Integer, String> right2 = ImmutableMap.of(1, "a", 3, "h", 5, "g", 6, "z"); 460 MapDifference<Integer, String> original = Maps.difference(left, right); 461 MapDifference<Integer, String> same = Maps.difference(left, right); 462 MapDifference<Integer, String> reverse = Maps.difference(right, left); 463 MapDifference<Integer, String> diff2 = Maps.difference(left, right2); 464 465 new EqualsTester() 466 .addEqualityGroup(original, same) 467 .addEqualityGroup(reverse) 468 .addEqualityGroup(diff2) 469 .testEquals(); 470 } 471 testMapDifferencePredicateTypical()472 public void testMapDifferencePredicateTypical() { 473 Map<Integer, String> left = ImmutableMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 474 Map<Integer, String> right = ImmutableMap.of(1, "A", 3, "F", 5, "G", 6, "Z"); 475 476 // TODO(kevinb): replace with Ascii.caseInsensitiveEquivalence() when it 477 // exists 478 Equivalence<String> caseInsensitiveEquivalence = 479 Equivalence.equals() 480 .onResultOf( 481 new Function<String, String>() { 482 @Override 483 public String apply(String input) { 484 return input.toLowerCase(); 485 } 486 }); 487 488 MapDifference<Integer, String> diff1 = Maps.difference(left, right, caseInsensitiveEquivalence); 489 assertFalse(diff1.areEqual()); 490 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft()); 491 assertEquals(ImmutableMap.of(6, "Z"), diff1.entriesOnlyOnRight()); 492 assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon()); 493 assertEquals( 494 ImmutableMap.of( 495 3, ValueDifferenceImpl.create("c", "F"), 5, ValueDifferenceImpl.create("e", "G")), 496 diff1.entriesDiffering()); 497 assertEquals( 498 "not equal: only on left={2=b, 4=d}: only on right={6=Z}: " 499 + "value differences={3=(c, F), 5=(e, G)}", 500 diff1.toString()); 501 502 MapDifference<Integer, String> diff2 = Maps.difference(right, left, caseInsensitiveEquivalence); 503 assertFalse(diff2.areEqual()); 504 assertEquals(ImmutableMap.of(6, "Z"), diff2.entriesOnlyOnLeft()); 505 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight()); 506 assertEquals(ImmutableMap.of(1, "A"), diff2.entriesInCommon()); 507 assertEquals( 508 ImmutableMap.of( 509 3, ValueDifferenceImpl.create("F", "c"), 5, ValueDifferenceImpl.create("G", "e")), 510 diff2.entriesDiffering()); 511 assertEquals( 512 "not equal: only on left={6=Z}: only on right={2=b, 4=d}: " 513 + "value differences={3=(F, c), 5=(G, e)}", 514 diff2.toString()); 515 } 516 517 private static final SortedMap<Integer, Integer> SORTED_EMPTY = Maps.newTreeMap(); 518 private static final ImmutableSortedMap<Integer, Integer> SORTED_SINGLETON = 519 ImmutableSortedMap.of(1, 2); 520 testMapDifferenceOfSortedMapIsSorted()521 public void testMapDifferenceOfSortedMapIsSorted() { 522 Map<Integer, Integer> map = SORTED_SINGLETON; 523 MapDifference<Integer, Integer> difference = Maps.difference(map, EMPTY); 524 assertTrue(difference instanceof SortedMapDifference); 525 } 526 testSortedMapDifferenceEmptyEmpty()527 public void testSortedMapDifferenceEmptyEmpty() { 528 SortedMapDifference<Integer, Integer> diff = Maps.difference(SORTED_EMPTY, SORTED_EMPTY); 529 assertTrue(diff.areEqual()); 530 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft()); 531 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight()); 532 assertEquals(SORTED_EMPTY, diff.entriesInCommon()); 533 assertEquals(SORTED_EMPTY, diff.entriesDiffering()); 534 assertEquals("equal", diff.toString()); 535 } 536 testSortedMapDifferenceEmptySingleton()537 public void testSortedMapDifferenceEmptySingleton() { 538 SortedMapDifference<Integer, Integer> diff = Maps.difference(SORTED_EMPTY, SORTED_SINGLETON); 539 assertFalse(diff.areEqual()); 540 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft()); 541 assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnRight()); 542 assertEquals(SORTED_EMPTY, diff.entriesInCommon()); 543 assertEquals(SORTED_EMPTY, diff.entriesDiffering()); 544 assertEquals("not equal: only on right={1=2}", diff.toString()); 545 } 546 testSortedMapDifferenceSingletonEmpty()547 public void testSortedMapDifferenceSingletonEmpty() { 548 SortedMapDifference<Integer, Integer> diff = Maps.difference(SORTED_SINGLETON, SORTED_EMPTY); 549 assertFalse(diff.areEqual()); 550 assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnLeft()); 551 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight()); 552 assertEquals(SORTED_EMPTY, diff.entriesInCommon()); 553 assertEquals(SORTED_EMPTY, diff.entriesDiffering()); 554 assertEquals("not equal: only on left={1=2}", diff.toString()); 555 } 556 testSortedMapDifferenceTypical()557 public void testSortedMapDifferenceTypical() { 558 SortedMap<Integer, String> left = 559 ImmutableSortedMap.<Integer, String>reverseOrder() 560 .put(1, "a") 561 .put(2, "b") 562 .put(3, "c") 563 .put(4, "d") 564 .put(5, "e") 565 .build(); 566 567 SortedMap<Integer, String> right = ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z"); 568 569 SortedMapDifference<Integer, String> diff1 = Maps.difference(left, right); 570 assertFalse(diff1.areEqual()); 571 assertThat(diff1.entriesOnlyOnLeft().entrySet()) 572 .containsExactly(Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")) 573 .inOrder(); 574 assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(Maps.immutableEntry(6, "z")); 575 assertThat(diff1.entriesInCommon().entrySet()).contains(Maps.immutableEntry(1, "a")); 576 assertThat(diff1.entriesDiffering().entrySet()) 577 .containsExactly( 578 Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")), 579 Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))) 580 .inOrder(); 581 assertEquals( 582 "not equal: only on left={4=d, 2=b}: only on right={6=z}: " 583 + "value differences={5=(e, g), 3=(c, f)}", 584 diff1.toString()); 585 586 SortedMapDifference<Integer, String> diff2 = Maps.difference(right, left); 587 assertFalse(diff2.areEqual()); 588 assertThat(diff2.entriesOnlyOnLeft().entrySet()).contains(Maps.immutableEntry(6, "z")); 589 assertThat(diff2.entriesOnlyOnRight().entrySet()) 590 .containsExactly(Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")) 591 .inOrder(); 592 assertThat(diff1.entriesInCommon().entrySet()).contains(Maps.immutableEntry(1, "a")); 593 assertEquals( 594 ImmutableMap.of( 595 3, ValueDifferenceImpl.create("f", "c"), 596 5, ValueDifferenceImpl.create("g", "e")), 597 diff2.entriesDiffering()); 598 assertEquals( 599 "not equal: only on left={6=z}: only on right={2=b, 4=d}: " 600 + "value differences={3=(f, c), 5=(g, e)}", 601 diff2.toString()); 602 } 603 testSortedMapDifferenceImmutable()604 public void testSortedMapDifferenceImmutable() { 605 SortedMap<Integer, String> left = 606 Maps.newTreeMap(ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e")); 607 SortedMap<Integer, String> right = 608 Maps.newTreeMap(ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z")); 609 610 SortedMapDifference<Integer, String> diff1 = Maps.difference(left, right); 611 left.put(6, "z"); 612 assertFalse(diff1.areEqual()); 613 assertThat(diff1.entriesOnlyOnLeft().entrySet()) 614 .containsExactly(Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")) 615 .inOrder(); 616 assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(Maps.immutableEntry(6, "z")); 617 assertThat(diff1.entriesInCommon().entrySet()).contains(Maps.immutableEntry(1, "a")); 618 assertThat(diff1.entriesDiffering().entrySet()) 619 .containsExactly( 620 Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")), 621 Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))) 622 .inOrder(); 623 try { 624 diff1.entriesInCommon().put(7, "x"); 625 fail(); 626 } catch (UnsupportedOperationException expected) { 627 } 628 try { 629 diff1.entriesOnlyOnLeft().put(7, "x"); 630 fail(); 631 } catch (UnsupportedOperationException expected) { 632 } 633 try { 634 diff1.entriesOnlyOnRight().put(7, "x"); 635 fail(); 636 } catch (UnsupportedOperationException expected) { 637 } 638 } 639 testSortedMapDifferenceEquals()640 public void testSortedMapDifferenceEquals() { 641 SortedMap<Integer, String> left = ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 642 SortedMap<Integer, String> right = ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z"); 643 SortedMap<Integer, String> right2 = ImmutableSortedMap.of(1, "a", 3, "h", 5, "g", 6, "z"); 644 SortedMapDifference<Integer, String> original = Maps.difference(left, right); 645 SortedMapDifference<Integer, String> same = Maps.difference(left, right); 646 SortedMapDifference<Integer, String> reverse = Maps.difference(right, left); 647 SortedMapDifference<Integer, String> diff2 = Maps.difference(left, right2); 648 649 new EqualsTester() 650 .addEqualityGroup(original, same) 651 .addEqualityGroup(reverse) 652 .addEqualityGroup(diff2) 653 .testEquals(); 654 } 655 656 private static final Function<String, Integer> LENGTH_FUNCTION = 657 new Function<String, Integer>() { 658 @Override 659 public Integer apply(String input) { 660 return input.length(); 661 } 662 }; 663 testAsMap()664 public void testAsMap() { 665 Set<String> strings = ImmutableSet.of("one", "two", "three"); 666 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 667 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 668 assertEquals(Integer.valueOf(5), map.get("three")); 669 assertNull(map.get("five")); 670 assertThat(map.entrySet()) 671 .containsExactly(mapEntry("one", 3), mapEntry("two", 3), mapEntry("three", 5)) 672 .inOrder(); 673 } 674 testAsMapReadsThrough()675 public void testAsMapReadsThrough() { 676 Set<String> strings = Sets.newLinkedHashSet(); 677 Collections.addAll(strings, "one", "two", "three"); 678 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 679 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 680 assertNull(map.get("four")); 681 strings.add("four"); 682 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5, "four", 4), map); 683 assertEquals(Integer.valueOf(4), map.get("four")); 684 } 685 testAsMapWritesThrough()686 public void testAsMapWritesThrough() { 687 Set<String> strings = Sets.newLinkedHashSet(); 688 Collections.addAll(strings, "one", "two", "three"); 689 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 690 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 691 assertEquals(Integer.valueOf(3), map.remove("two")); 692 assertThat(strings).containsExactly("one", "three").inOrder(); 693 } 694 testAsMapEmpty()695 public void testAsMapEmpty() { 696 Set<String> strings = ImmutableSet.of(); 697 Map<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 private static class NonNavigableSortedSet extends ForwardingSortedSet<String> { 704 private final SortedSet<String> delegate = Sets.newTreeSet(); 705 706 @Override delegate()707 protected SortedSet<String> delegate() { 708 return delegate; 709 } 710 } 711 testAsMapSorted()712 public void testAsMapSorted() { 713 SortedSet<String> strings = new NonNavigableSortedSet(); 714 Collections.addAll(strings, "one", "two", "three"); 715 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 716 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 717 assertEquals(Integer.valueOf(5), map.get("three")); 718 assertNull(map.get("five")); 719 assertThat(map.entrySet()) 720 .containsExactly(mapEntry("one", 3), mapEntry("three", 5), mapEntry("two", 3)) 721 .inOrder(); 722 assertThat(map.tailMap("onea").entrySet()) 723 .containsExactly(mapEntry("three", 5), mapEntry("two", 3)) 724 .inOrder(); 725 assertThat(map.subMap("one", "two").entrySet()) 726 .containsExactly(mapEntry("one", 3), mapEntry("three", 5)) 727 .inOrder(); 728 } 729 testAsMapSortedReadsThrough()730 public void testAsMapSortedReadsThrough() { 731 SortedSet<String> strings = new NonNavigableSortedSet(); 732 Collections.addAll(strings, "one", "two", "three"); 733 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 734 assertNull(map.comparator()); 735 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map); 736 assertNull(map.get("four")); 737 strings.add("four"); 738 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4), map); 739 assertEquals(Integer.valueOf(4), map.get("four")); 740 SortedMap<String, Integer> headMap = map.headMap("two"); 741 assertEquals(ImmutableSortedMap.of("four", 4, "one", 3, "three", 5), headMap); 742 strings.add("five"); 743 strings.remove("one"); 744 assertEquals(ImmutableSortedMap.of("five", 4, "four", 4, "three", 5), headMap); 745 assertThat(map.entrySet()) 746 .containsExactly( 747 mapEntry("five", 4), mapEntry("four", 4), mapEntry("three", 5), mapEntry("two", 3)) 748 .inOrder(); 749 } 750 testAsMapSortedWritesThrough()751 public void testAsMapSortedWritesThrough() { 752 SortedSet<String> strings = new NonNavigableSortedSet(); 753 Collections.addAll(strings, "one", "two", "three"); 754 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 755 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 756 assertEquals(Integer.valueOf(3), map.remove("two")); 757 assertThat(strings).containsExactly("one", "three").inOrder(); 758 } 759 testAsMapSortedSubViewKeySetsDoNotSupportAdd()760 public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() { 761 SortedMap<String, Integer> map = Maps.asMap(new NonNavigableSortedSet(), LENGTH_FUNCTION); 762 try { 763 map.subMap("a", "z").keySet().add("a"); 764 fail(); 765 } catch (UnsupportedOperationException expected) { 766 } 767 try { 768 map.tailMap("a").keySet().add("a"); 769 fail(); 770 } catch (UnsupportedOperationException expected) { 771 } 772 try { 773 map.headMap("r").keySet().add("a"); 774 fail(); 775 } catch (UnsupportedOperationException expected) { 776 } 777 try { 778 map.headMap("r").tailMap("m").keySet().add("a"); 779 fail(); 780 } catch (UnsupportedOperationException expected) { 781 } 782 } 783 testAsMapSortedEmpty()784 public void testAsMapSortedEmpty() { 785 SortedSet<String> strings = new NonNavigableSortedSet(); 786 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 787 assertThat(map.entrySet()).isEmpty(); 788 assertTrue(map.isEmpty()); 789 assertNull(map.get("five")); 790 } 791 792 @GwtIncompatible // NavigableMap testAsMapNavigable()793 public void testAsMapNavigable() { 794 NavigableSet<String> strings = Sets.newTreeSet(asList("one", "two", "three")); 795 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 796 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 797 assertEquals(Integer.valueOf(5), map.get("three")); 798 assertNull(map.get("five")); 799 assertThat(map.entrySet()) 800 .containsExactly(mapEntry("one", 3), mapEntry("three", 5), mapEntry("two", 3)) 801 .inOrder(); 802 assertThat(map.tailMap("onea").entrySet()) 803 .containsExactly(mapEntry("three", 5), mapEntry("two", 3)) 804 .inOrder(); 805 assertThat(map.subMap("one", "two").entrySet()) 806 .containsExactly(mapEntry("one", 3), mapEntry("three", 5)) 807 .inOrder(); 808 809 assertEquals(ImmutableSortedMap.of("two", 3, "three", 5), map.tailMap("three", true)); 810 assertEquals(ImmutableSortedMap.of("one", 3, "three", 5), map.headMap("two", false)); 811 assertEquals(ImmutableSortedMap.of("three", 5), map.subMap("one", false, "tr", true)); 812 813 assertEquals("three", map.higherKey("one")); 814 assertEquals("three", map.higherKey("r")); 815 assertEquals("three", map.ceilingKey("r")); 816 assertEquals("one", map.ceilingKey("one")); 817 assertEquals(mapEntry("three", 5), map.higherEntry("one")); 818 assertEquals(mapEntry("one", 3), map.ceilingEntry("one")); 819 assertEquals("one", map.lowerKey("three")); 820 assertEquals("one", map.lowerKey("r")); 821 assertEquals("one", map.floorKey("r")); 822 assertEquals("three", map.floorKey("three")); 823 824 assertThat(map.descendingMap().entrySet()) 825 .containsExactly(mapEntry("two", 3), mapEntry("three", 5), mapEntry("one", 3)) 826 .inOrder(); 827 assertEquals(map.headMap("three", true), map.descendingMap().tailMap("three", true)); 828 assertThat(map.tailMap("three", false).entrySet()).contains(mapEntry("two", 3)); 829 assertNull(map.tailMap("three", true).lowerEntry("three")); 830 assertThat(map.headMap("two", false).values()).containsExactly(3, 5).inOrder(); 831 assertThat(map.headMap("two", false).descendingMap().values()).containsExactly(5, 3).inOrder(); 832 assertThat(map.descendingKeySet()).containsExactly("two", "three", "one").inOrder(); 833 834 assertEquals(mapEntry("one", 3), map.pollFirstEntry()); 835 assertEquals(mapEntry("two", 3), map.pollLastEntry()); 836 assertEquals(1, map.size()); 837 } 838 839 @GwtIncompatible // NavigableMap testAsMapNavigableReadsThrough()840 public void testAsMapNavigableReadsThrough() { 841 NavigableSet<String> strings = Sets.newTreeSet(); 842 Collections.addAll(strings, "one", "two", "three"); 843 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 844 assertNull(map.comparator()); 845 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map); 846 assertNull(map.get("four")); 847 strings.add("four"); 848 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4), map); 849 assertEquals(Integer.valueOf(4), map.get("four")); 850 SortedMap<String, Integer> headMap = map.headMap("two"); 851 assertEquals(ImmutableSortedMap.of("four", 4, "one", 3, "three", 5), headMap); 852 strings.add("five"); 853 strings.remove("one"); 854 assertEquals(ImmutableSortedMap.of("five", 4, "four", 4, "three", 5), headMap); 855 assertThat(map.entrySet()) 856 .containsExactly( 857 mapEntry("five", 4), mapEntry("four", 4), mapEntry("three", 5), mapEntry("two", 3)) 858 .inOrder(); 859 860 NavigableMap<String, Integer> tailMap = map.tailMap("s", true); 861 NavigableMap<String, Integer> subMap = map.subMap("a", true, "t", false); 862 863 strings.add("six"); 864 strings.remove("two"); 865 assertThat(tailMap.entrySet()) 866 .containsExactly(mapEntry("six", 3), mapEntry("three", 5)) 867 .inOrder(); 868 assertThat(subMap.entrySet()) 869 .containsExactly(mapEntry("five", 4), mapEntry("four", 4), mapEntry("six", 3)) 870 .inOrder(); 871 } 872 873 @GwtIncompatible // NavigableMap testAsMapNavigableWritesThrough()874 public void testAsMapNavigableWritesThrough() { 875 NavigableSet<String> strings = Sets.newTreeSet(); 876 Collections.addAll(strings, "one", "two", "three"); 877 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 878 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 879 assertEquals(Integer.valueOf(3), map.remove("two")); 880 assertThat(strings).containsExactly("one", "three").inOrder(); 881 assertEquals(mapEntry("three", 5), map.subMap("one", false, "zzz", true).pollLastEntry()); 882 assertThat(strings).contains("one"); 883 } 884 885 @GwtIncompatible // NavigableMap testAsMapNavigableSubViewKeySetsDoNotSupportAdd()886 public void testAsMapNavigableSubViewKeySetsDoNotSupportAdd() { 887 NavigableMap<String, Integer> map = Maps.asMap(Sets.<String>newTreeSet(), LENGTH_FUNCTION); 888 try { 889 map.descendingKeySet().add("a"); 890 fail(); 891 } catch (UnsupportedOperationException expected) { 892 } 893 try { 894 map.subMap("a", true, "z", false).keySet().add("a"); 895 fail(); 896 } catch (UnsupportedOperationException expected) { 897 } 898 try { 899 map.tailMap("a", true).keySet().add("a"); 900 fail(); 901 } catch (UnsupportedOperationException expected) { 902 } 903 try { 904 map.headMap("r", true).keySet().add("a"); 905 fail(); 906 } catch (UnsupportedOperationException expected) { 907 } 908 try { 909 map.headMap("r", false).tailMap("m", true).keySet().add("a"); 910 fail(); 911 } catch (UnsupportedOperationException expected) { 912 } 913 } 914 915 @GwtIncompatible // NavigableMap testAsMapNavigableEmpty()916 public void testAsMapNavigableEmpty() { 917 NavigableSet<String> strings = ImmutableSortedSet.of(); 918 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 919 assertThat(map.entrySet()).isEmpty(); 920 assertTrue(map.isEmpty()); 921 assertNull(map.get("five")); 922 } 923 testToMap()924 public void testToMap() { 925 Iterable<String> strings = ImmutableList.of("one", "two", "three"); 926 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION); 927 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 928 assertThat(map.entrySet()) 929 .containsExactly(mapEntry("one", 3), mapEntry("two", 3), mapEntry("three", 5)) 930 .inOrder(); 931 } 932 testToMapIterator()933 public void testToMapIterator() { 934 Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator(); 935 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION); 936 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 937 assertThat(map.entrySet()) 938 .containsExactly(mapEntry("one", 3), mapEntry("two", 3), mapEntry("three", 5)) 939 .inOrder(); 940 } 941 testToMapWithDuplicateKeys()942 public void testToMapWithDuplicateKeys() { 943 Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one"); 944 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION); 945 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 946 assertThat(map.entrySet()) 947 .containsExactly(mapEntry("one", 3), mapEntry("two", 3), mapEntry("three", 5)) 948 .inOrder(); 949 } 950 testToMapWithNullKeys()951 public void testToMapWithNullKeys() { 952 Iterable<String> strings = Arrays.asList("one", null, "three"); 953 try { 954 Maps.toMap(strings, Functions.constant("foo")); 955 fail(); 956 } catch (NullPointerException expected) { 957 } 958 } 959 testToMapWithNullValues()960 public void testToMapWithNullValues() { 961 Iterable<String> strings = ImmutableList.of("one", "two", "three"); 962 try { 963 Maps.toMap(strings, Functions.constant(null)); 964 fail(); 965 } catch (NullPointerException expected) { 966 } 967 } 968 969 private static final ImmutableBiMap<Integer, String> INT_TO_STRING_MAP = 970 new ImmutableBiMap.Builder<Integer, String>() 971 .put(1, "one") 972 .put(2, "two") 973 .put(3, "three") 974 .build(); 975 testUniqueIndexCollection()976 public void testUniqueIndexCollection() { 977 ImmutableMap<Integer, String> outputMap = 978 Maps.uniqueIndex(INT_TO_STRING_MAP.values(), Functions.forMap(INT_TO_STRING_MAP.inverse())); 979 assertEquals(INT_TO_STRING_MAP, outputMap); 980 } 981 testUniqueIndexIterable()982 public void testUniqueIndexIterable() { 983 ImmutableMap<Integer, String> outputMap = 984 Maps.uniqueIndex( 985 new Iterable<String>() { 986 @Override 987 public Iterator<String> iterator() { 988 return INT_TO_STRING_MAP.values().iterator(); 989 } 990 }, 991 Functions.forMap(INT_TO_STRING_MAP.inverse())); 992 assertEquals(INT_TO_STRING_MAP, outputMap); 993 } 994 testUniqueIndexIterator()995 public void testUniqueIndexIterator() { 996 ImmutableMap<Integer, String> outputMap = 997 Maps.uniqueIndex( 998 INT_TO_STRING_MAP.values().iterator(), Functions.forMap(INT_TO_STRING_MAP.inverse())); 999 assertEquals(INT_TO_STRING_MAP, outputMap); 1000 } 1001 1002 /** Can't create the map if more than one value maps to the same key. */ testUniqueIndexDuplicates()1003 public void testUniqueIndexDuplicates() { 1004 try { 1005 Map<Integer, String> unused = 1006 Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1)); 1007 fail(); 1008 } catch (IllegalArgumentException expected) { 1009 assertThat(expected.getMessage()).contains("Multimaps.index"); 1010 } 1011 } 1012 1013 /** Null values are not allowed. */ testUniqueIndexNullValue()1014 public void testUniqueIndexNullValue() { 1015 List<String> listWithNull = Lists.newArrayList((String) null); 1016 try { 1017 Maps.uniqueIndex(listWithNull, Functions.constant(1)); 1018 fail(); 1019 } catch (NullPointerException expected) { 1020 } 1021 } 1022 1023 /** Null keys aren't allowed either. */ testUniqueIndexNullKey()1024 public void testUniqueIndexNullKey() { 1025 List<String> oneStringList = Lists.newArrayList("foo"); 1026 try { 1027 Maps.uniqueIndex(oneStringList, Functions.constant(null)); 1028 fail(); 1029 } catch (NullPointerException expected) { 1030 } 1031 } 1032 1033 @GwtIncompatible // Maps.fromProperties 1034 @SuppressWarnings("deprecation") // StringBufferInputStream testFromProperties()1035 public void testFromProperties() throws IOException { 1036 Properties testProp = new Properties(); 1037 1038 Map<String, String> result = Maps.fromProperties(testProp); 1039 assertTrue(result.isEmpty()); 1040 testProp.setProperty("first", "true"); 1041 1042 result = Maps.fromProperties(testProp); 1043 assertEquals("true", result.get("first")); 1044 assertEquals(1, result.size()); 1045 testProp.setProperty("second", "null"); 1046 1047 result = Maps.fromProperties(testProp); 1048 assertEquals("true", result.get("first")); 1049 assertEquals("null", result.get("second")); 1050 assertEquals(2, result.size()); 1051 1052 // Now test values loaded from a stream. 1053 String props = "test\n second = 2\n Third item : a short phrase "; 1054 1055 testProp.load(new StringReader(props)); 1056 1057 result = Maps.fromProperties(testProp); 1058 assertEquals(4, result.size()); 1059 assertEquals("true", result.get("first")); 1060 assertEquals("", result.get("test")); 1061 assertEquals("2", result.get("second")); 1062 assertEquals("item : a short phrase ", result.get("Third")); 1063 assertFalse(result.containsKey("not here")); 1064 1065 // Test loading system properties 1066 result = Maps.fromProperties(System.getProperties()); 1067 assertTrue(result.containsKey("java.version")); 1068 1069 // Test that defaults work, too. 1070 testProp = new Properties(System.getProperties()); 1071 String override = "test\njava.version : hidden"; 1072 1073 testProp.load(new StringReader(override)); 1074 1075 result = Maps.fromProperties(testProp); 1076 assertTrue(result.size() > 2); 1077 assertEquals("", result.get("test")); 1078 assertEquals("hidden", result.get("java.version")); 1079 assertNotSame(System.getProperty("java.version"), result.get("java.version")); 1080 } 1081 1082 @GwtIncompatible // Maps.fromProperties 1083 @SuppressWarnings("serial") // never serialized testFromPropertiesNullKey()1084 public void testFromPropertiesNullKey() { 1085 Properties properties = 1086 new Properties() { 1087 @Override 1088 public Enumeration<?> propertyNames() { 1089 return Iterators.asEnumeration(Arrays.asList(null, "first", "second").iterator()); 1090 } 1091 }; 1092 properties.setProperty("first", "true"); 1093 properties.setProperty("second", "null"); 1094 1095 try { 1096 Maps.fromProperties(properties); 1097 fail(); 1098 } catch (NullPointerException expected) { 1099 } 1100 } 1101 1102 @GwtIncompatible // Maps.fromProperties 1103 @SuppressWarnings("serial") // never serialized testFromPropertiesNonStringKeys()1104 public void testFromPropertiesNonStringKeys() { 1105 Properties properties = 1106 new Properties() { 1107 @Override 1108 public Enumeration<?> propertyNames() { 1109 return Iterators.asEnumeration( 1110 Arrays.<Object>asList(Integer.valueOf(123), "first").iterator()); 1111 } 1112 }; 1113 1114 try { 1115 Maps.fromProperties(properties); 1116 fail(); 1117 } catch (ClassCastException expected) { 1118 } 1119 } 1120 testAsConverter_nominal()1121 public void testAsConverter_nominal() throws Exception { 1122 ImmutableBiMap<String, Integer> biMap = 1123 ImmutableBiMap.of( 1124 "one", 1, 1125 "two", 2); 1126 Converter<String, Integer> converter = Maps.asConverter(biMap); 1127 for (Entry<String, Integer> entry : biMap.entrySet()) { 1128 assertSame(entry.getValue(), converter.convert(entry.getKey())); 1129 } 1130 } 1131 testAsConverter_inverse()1132 public void testAsConverter_inverse() throws Exception { 1133 ImmutableBiMap<String, Integer> biMap = 1134 ImmutableBiMap.of( 1135 "one", 1, 1136 "two", 2); 1137 Converter<String, Integer> converter = Maps.asConverter(biMap); 1138 for (Entry<String, Integer> entry : biMap.entrySet()) { 1139 assertSame(entry.getKey(), converter.reverse().convert(entry.getValue())); 1140 } 1141 } 1142 testAsConverter_noMapping()1143 public void testAsConverter_noMapping() throws Exception { 1144 ImmutableBiMap<String, Integer> biMap = 1145 ImmutableBiMap.of( 1146 "one", 1, 1147 "two", 2); 1148 Converter<String, Integer> converter = Maps.asConverter(biMap); 1149 try { 1150 converter.convert("three"); 1151 fail(); 1152 } catch (IllegalArgumentException expected) { 1153 } 1154 } 1155 testAsConverter_nullConversions()1156 public void testAsConverter_nullConversions() throws Exception { 1157 ImmutableBiMap<String, Integer> biMap = 1158 ImmutableBiMap.of( 1159 "one", 1, 1160 "two", 2); 1161 Converter<String, Integer> converter = Maps.asConverter(biMap); 1162 assertNull(converter.convert(null)); 1163 assertNull(converter.reverse().convert(null)); 1164 } 1165 testAsConverter_isAView()1166 public void testAsConverter_isAView() throws Exception { 1167 BiMap<String, Integer> biMap = HashBiMap.create(); 1168 biMap.put("one", 1); 1169 biMap.put("two", 2); 1170 Converter<String, Integer> converter = Maps.asConverter(biMap); 1171 1172 assertEquals((Integer) 1, converter.convert("one")); 1173 assertEquals((Integer) 2, converter.convert("two")); 1174 try { 1175 converter.convert("three"); 1176 fail(); 1177 } catch (IllegalArgumentException expected) { 1178 } 1179 1180 biMap.put("three", 3); 1181 1182 assertEquals((Integer) 1, converter.convert("one")); 1183 assertEquals((Integer) 2, converter.convert("two")); 1184 assertEquals((Integer) 3, converter.convert("three")); 1185 } 1186 testAsConverter_withNullMapping()1187 public void testAsConverter_withNullMapping() throws Exception { 1188 BiMap<String, Integer> biMap = HashBiMap.create(); 1189 biMap.put("one", 1); 1190 biMap.put("two", 2); 1191 biMap.put("three", null); 1192 try { 1193 Maps.asConverter(biMap).convert("three"); 1194 fail(); 1195 } catch (IllegalArgumentException expected) { 1196 } 1197 } 1198 testAsConverter_toString()1199 public void testAsConverter_toString() { 1200 ImmutableBiMap<String, Integer> biMap = 1201 ImmutableBiMap.of( 1202 "one", 1, 1203 "two", 2); 1204 Converter<String, Integer> converter = Maps.asConverter(biMap); 1205 assertEquals("Maps.asConverter({one=1, two=2})", converter.toString()); 1206 } 1207 testAsConverter_serialization()1208 public void testAsConverter_serialization() { 1209 ImmutableBiMap<String, Integer> biMap = 1210 ImmutableBiMap.of( 1211 "one", 1, 1212 "two", 2); 1213 Converter<String, Integer> converter = Maps.asConverter(biMap); 1214 SerializableTester.reserializeAndAssert(converter); 1215 } 1216 testUnmodifiableBiMap()1217 public void testUnmodifiableBiMap() { 1218 BiMap<Integer, String> mod = HashBiMap.create(); 1219 mod.put(1, "one"); 1220 mod.put(2, "two"); 1221 mod.put(3, "three"); 1222 1223 BiMap<Number, String> unmod = Maps.<Number, String>unmodifiableBiMap(mod); 1224 1225 /* No aliasing on inverse operations. */ 1226 assertSame(unmod.inverse(), unmod.inverse()); 1227 assertSame(unmod, unmod.inverse().inverse()); 1228 1229 /* Unmodifiable is a view. */ 1230 mod.put(4, "four"); 1231 assertEquals(true, unmod.get(4).equals("four")); 1232 assertEquals(true, unmod.inverse().get("four").equals(4)); 1233 1234 /* UnsupportedOperationException on direct modifications. */ 1235 try { 1236 unmod.put(4, "four"); 1237 fail("UnsupportedOperationException expected"); 1238 } catch (UnsupportedOperationException expected) { 1239 } 1240 try { 1241 unmod.forcePut(4, "four"); 1242 fail("UnsupportedOperationException expected"); 1243 } catch (UnsupportedOperationException expected) { 1244 } 1245 try { 1246 unmod.putAll(Collections.singletonMap(4, "four")); 1247 fail("UnsupportedOperationException expected"); 1248 } catch (UnsupportedOperationException expected) { 1249 } 1250 1251 /* UnsupportedOperationException on indirect modifications. */ 1252 BiMap<String, Number> inverse = unmod.inverse(); 1253 try { 1254 inverse.put("four", 4); 1255 fail("UnsupportedOperationException expected"); 1256 } catch (UnsupportedOperationException expected) { 1257 } 1258 try { 1259 inverse.forcePut("four", 4); 1260 fail("UnsupportedOperationException expected"); 1261 } catch (UnsupportedOperationException expected) { 1262 } 1263 try { 1264 inverse.putAll(Collections.singletonMap("four", 4)); 1265 fail("UnsupportedOperationException expected"); 1266 } catch (UnsupportedOperationException expected) { 1267 } 1268 Set<String> values = unmod.values(); 1269 try { 1270 values.remove("four"); 1271 fail("UnsupportedOperationException expected"); 1272 } catch (UnsupportedOperationException expected) { 1273 } 1274 Set<Entry<Number, String>> entries = unmod.entrySet(); 1275 Entry<Number, String> entry = entries.iterator().next(); 1276 try { 1277 entry.setValue("four"); 1278 fail("UnsupportedOperationException expected"); 1279 } catch (UnsupportedOperationException expected) { 1280 } 1281 @SuppressWarnings("unchecked") 1282 Entry<Integer, String> entry2 = (Entry<Integer, String>) entries.toArray()[0]; 1283 try { 1284 entry2.setValue("four"); 1285 fail("UnsupportedOperationException expected"); 1286 } catch (UnsupportedOperationException expected) { 1287 } 1288 } 1289 testImmutableEntry()1290 public void testImmutableEntry() { 1291 Entry<String, Integer> e = Maps.immutableEntry("foo", 1); 1292 assertEquals("foo", e.getKey()); 1293 assertEquals(1, (int) e.getValue()); 1294 try { 1295 e.setValue(2); 1296 fail("UnsupportedOperationException expected"); 1297 } catch (UnsupportedOperationException expected) { 1298 } 1299 assertEquals("foo=1", e.toString()); 1300 assertEquals(101575, e.hashCode()); 1301 } 1302 testImmutableEntryNull()1303 public void testImmutableEntryNull() { 1304 Entry<String, Integer> e = Maps.immutableEntry((String) null, (Integer) null); 1305 assertNull(e.getKey()); 1306 assertNull(e.getValue()); 1307 try { 1308 e.setValue(null); 1309 fail("UnsupportedOperationException expected"); 1310 } catch (UnsupportedOperationException expected) { 1311 } 1312 assertEquals("null=null", e.toString()); 1313 assertEquals(0, e.hashCode()); 1314 } 1315 1316 /** See {@link SynchronizedBiMapTest} for more tests. */ testSynchronizedBiMap()1317 public void testSynchronizedBiMap() { 1318 BiMap<String, Integer> bimap = HashBiMap.create(); 1319 bimap.put("one", 1); 1320 BiMap<String, Integer> sync = Maps.synchronizedBiMap(bimap); 1321 bimap.put("two", 2); 1322 sync.put("three", 3); 1323 assertEquals(ImmutableSet.of(1, 2, 3), bimap.inverse().keySet()); 1324 assertEquals(ImmutableSet.of(1, 2, 3), sync.inverse().keySet()); 1325 } 1326 1327 private static final Function<Integer, Double> SQRT_FUNCTION = in -> Math.sqrt(in); 1328 testTransformValues()1329 public void testTransformValues() { 1330 Map<String, Integer> map = ImmutableMap.of("a", 4, "b", 9); 1331 Map<String, Double> transformed = transformValues(map, SQRT_FUNCTION); 1332 1333 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed); 1334 } 1335 testTransformEntries()1336 public void testTransformEntries() { 1337 Map<String, String> map = ImmutableMap.of("a", "4", "b", "9"); 1338 EntryTransformer<String, String, String> concat = 1339 new EntryTransformer<String, String, String>() { 1340 @Override 1341 public String transformEntry(String key, String value) { 1342 return key + value; 1343 } 1344 }; 1345 Map<String, String> transformed = transformEntries(map, concat); 1346 1347 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed); 1348 } 1349 1350 @SuppressWarnings("unused") testTransformEntriesGenerics()1351 public void testTransformEntriesGenerics() { 1352 Map<Object, Object> map1 = ImmutableMap.<Object, Object>of(1, 2); 1353 Map<Object, Number> map2 = ImmutableMap.<Object, Number>of(1, 2); 1354 Map<Object, Integer> map3 = ImmutableMap.<Object, Integer>of(1, 2); 1355 Map<Number, Object> map4 = ImmutableMap.<Number, Object>of(1, 2); 1356 Map<Number, Number> map5 = ImmutableMap.<Number, Number>of(1, 2); 1357 Map<Number, Integer> map6 = ImmutableMap.<Number, Integer>of(1, 2); 1358 Map<Integer, Object> map7 = ImmutableMap.<Integer, Object>of(1, 2); 1359 Map<Integer, Number> map8 = ImmutableMap.<Integer, Number>of(1, 2); 1360 Map<Integer, Integer> map9 = ImmutableMap.<Integer, Integer>of(1, 2); 1361 Map<? extends Number, ? extends Number> map0 = ImmutableMap.of(1, 2); 1362 1363 EntryTransformer<Number, Number, Double> transformer = 1364 new EntryTransformer<Number, Number, Double>() { 1365 @Override 1366 public Double transformEntry(Number key, Number value) { 1367 return key.doubleValue() + value.doubleValue(); 1368 } 1369 }; 1370 1371 Map<Object, Double> objectKeyed; 1372 Map<Number, Double> numberKeyed; 1373 Map<Integer, Double> integerKeyed; 1374 1375 numberKeyed = transformEntries(map5, transformer); 1376 numberKeyed = transformEntries(map6, transformer); 1377 integerKeyed = transformEntries(map8, transformer); 1378 integerKeyed = transformEntries(map9, transformer); 1379 1380 Map<? extends Number, Double> wildcarded = transformEntries(map0, transformer); 1381 1382 // Can't loosen the key type: 1383 // objectKeyed = transformEntries(map5, transformer); 1384 // objectKeyed = transformEntries(map6, transformer); 1385 // objectKeyed = transformEntries(map8, transformer); 1386 // objectKeyed = transformEntries(map9, transformer); 1387 // numberKeyed = transformEntries(map8, transformer); 1388 // numberKeyed = transformEntries(map9, transformer); 1389 1390 // Can't loosen the value type: 1391 // Map<Number, Number> looseValued1 = transformEntries(map5, transformer); 1392 // Map<Number, Number> looseValued2 = transformEntries(map6, transformer); 1393 // Map<Integer, Number> looseValued3 = transformEntries(map8, transformer); 1394 // Map<Integer, Number> looseValued4 = transformEntries(map9, transformer); 1395 1396 // Can't call with too loose a key: 1397 // transformEntries(map1, transformer); 1398 // transformEntries(map2, transformer); 1399 // transformEntries(map3, transformer); 1400 1401 // Can't call with too loose a value: 1402 // transformEntries(map1, transformer); 1403 // transformEntries(map4, transformer); 1404 // transformEntries(map7, transformer); 1405 } 1406 testTransformEntriesExample()1407 public void testTransformEntriesExample() { 1408 Map<String, Boolean> options = ImmutableMap.of("verbose", true, "sort", false); 1409 EntryTransformer<String, Boolean, String> flagPrefixer = 1410 new EntryTransformer<String, Boolean, String>() { 1411 @Override 1412 public String transformEntry(String key, Boolean value) { 1413 return value ? key : "no" + key; 1414 } 1415 }; 1416 Map<String, String> transformed = transformEntries(options, flagPrefixer); 1417 assertEquals("{verbose=verbose, sort=nosort}", transformed.toString()); 1418 } 1419 1420 // Logically this would accept a NavigableMap, but that won't work under GWT. sortedNotNavigable(final SortedMap<K, V> map)1421 private static <K, V> SortedMap<K, V> sortedNotNavigable(final SortedMap<K, V> map) { 1422 return new ForwardingSortedMap<K, V>() { 1423 @Override 1424 protected SortedMap<K, V> delegate() { 1425 return map; 1426 } 1427 }; 1428 } 1429 1430 public void testSortedMapTransformValues() { 1431 SortedMap<String, Integer> map = sortedNotNavigable(ImmutableSortedMap.of("a", 4, "b", 9)); 1432 SortedMap<String, Double> transformed = transformValues(map, SQRT_FUNCTION); 1433 1434 /* 1435 * We'd like to sanity check that we didn't get a NavigableMap out, but we 1436 * can't easily do so while maintaining GWT compatibility. 1437 */ 1438 assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed); 1439 } 1440 1441 @GwtIncompatible // NavigableMap 1442 public void testNavigableMapTransformValues() { 1443 NavigableMap<String, Integer> map = ImmutableSortedMap.of("a", 4, "b", 9); 1444 NavigableMap<String, Double> transformed = transformValues(map, SQRT_FUNCTION); 1445 1446 assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed); 1447 } 1448 1449 public void testSortedMapTransformEntries() { 1450 SortedMap<String, String> map = sortedNotNavigable(ImmutableSortedMap.of("a", "4", "b", "9")); 1451 EntryTransformer<String, String, String> concat = 1452 new EntryTransformer<String, String, String>() { 1453 @Override 1454 public String transformEntry(String key, String value) { 1455 return key + value; 1456 } 1457 }; 1458 SortedMap<String, String> transformed = transformEntries(map, concat); 1459 1460 /* 1461 * We'd like to sanity check that we didn't get a NavigableMap out, but we 1462 * can't easily do so while maintaining GWT compatibility. 1463 */ 1464 assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed); 1465 } 1466 1467 @GwtIncompatible // NavigableMap 1468 public void testNavigableMapTransformEntries() { 1469 NavigableMap<String, String> map = ImmutableSortedMap.of("a", "4", "b", "9"); 1470 EntryTransformer<String, String, String> concat = 1471 new EntryTransformer<String, String, String>() { 1472 @Override 1473 public String transformEntry(String key, String value) { 1474 return key + value; 1475 } 1476 }; 1477 NavigableMap<String, String> transformed = transformEntries(map, concat); 1478 1479 assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed); 1480 } 1481 1482 @GwtIncompatible // NavigableMap 1483 public void testUnmodifiableNavigableMap() { 1484 TreeMap<Integer, String> mod = Maps.newTreeMap(); 1485 mod.put(1, "one"); 1486 mod.put(2, "two"); 1487 mod.put(3, "three"); 1488 1489 NavigableMap<Integer, String> unmod = unmodifiableNavigableMap(mod); 1490 1491 /* unmod is a view. */ 1492 mod.put(4, "four"); 1493 assertEquals("four", unmod.get(4)); 1494 assertEquals("four", unmod.descendingMap().get(4)); 1495 1496 ensureNotDirectlyModifiable(unmod); 1497 ensureNotDirectlyModifiable(unmod.descendingMap()); 1498 ensureNotDirectlyModifiable(unmod.headMap(2, true)); 1499 ensureNotDirectlyModifiable(unmod.subMap(1, true, 3, true)); 1500 ensureNotDirectlyModifiable(unmod.tailMap(2, true)); 1501 1502 Collection<String> values = unmod.values(); 1503 try { 1504 values.add("4"); 1505 fail("UnsupportedOperationException expected"); 1506 } catch (UnsupportedOperationException expected) { 1507 } 1508 try { 1509 values.remove("four"); 1510 fail("UnsupportedOperationException expected"); 1511 } catch (UnsupportedOperationException expected) { 1512 } 1513 try { 1514 values.removeAll(Collections.singleton("four")); 1515 fail("UnsupportedOperationException expected"); 1516 } catch (UnsupportedOperationException expected) { 1517 } 1518 try { 1519 values.retainAll(Collections.singleton("four")); 1520 fail("UnsupportedOperationException expected"); 1521 } catch (UnsupportedOperationException expected) { 1522 } 1523 try { 1524 Iterator<String> iterator = values.iterator(); 1525 iterator.next(); 1526 iterator.remove(); 1527 fail("UnsupportedOperationException expected"); 1528 } catch (UnsupportedOperationException expected) { 1529 } 1530 1531 Set<Entry<Integer, String>> entries = unmod.entrySet(); 1532 try { 1533 Iterator<Entry<Integer, String>> iterator = entries.iterator(); 1534 iterator.next(); 1535 iterator.remove(); 1536 fail("UnsupportedOperationException expected"); 1537 } catch (UnsupportedOperationException expected) { 1538 } 1539 Entry<Integer, String> entry = entries.iterator().next(); 1540 try { 1541 entry.setValue("four"); 1542 fail("UnsupportedOperationException expected"); 1543 } catch (UnsupportedOperationException expected) { 1544 } 1545 entry = unmod.lowerEntry(1); 1546 assertNull(entry); 1547 entry = unmod.floorEntry(2); 1548 try { 1549 entry.setValue("four"); 1550 fail("UnsupportedOperationException expected"); 1551 } catch (UnsupportedOperationException expected) { 1552 } 1553 entry = unmod.ceilingEntry(2); 1554 try { 1555 entry.setValue("four"); 1556 fail("UnsupportedOperationException expected"); 1557 } catch (UnsupportedOperationException expected) { 1558 } 1559 entry = unmod.lowerEntry(2); 1560 try { 1561 entry.setValue("four"); 1562 fail("UnsupportedOperationException expected"); 1563 } catch (UnsupportedOperationException expected) { 1564 } 1565 entry = unmod.higherEntry(2); 1566 try { 1567 entry.setValue("four"); 1568 fail("UnsupportedOperationException expected"); 1569 } catch (UnsupportedOperationException expected) { 1570 } 1571 entry = unmod.firstEntry(); 1572 try { 1573 entry.setValue("four"); 1574 fail("UnsupportedOperationException expected"); 1575 } catch (UnsupportedOperationException expected) { 1576 } 1577 entry = unmod.lastEntry(); 1578 try { 1579 entry.setValue("four"); 1580 fail("UnsupportedOperationException expected"); 1581 } catch (UnsupportedOperationException expected) { 1582 } 1583 @SuppressWarnings("unchecked") 1584 Entry<Integer, String> entry2 = (Entry<Integer, String>) entries.toArray()[0]; 1585 try { 1586 entry2.setValue("four"); 1587 fail("UnsupportedOperationException expected"); 1588 } catch (UnsupportedOperationException expected) { 1589 } 1590 } 1591 1592 @GwtIncompatible // NavigableMap 1593 void ensureNotDirectlyModifiable(NavigableMap<Integer, String> unmod) { 1594 try { 1595 unmod.put(4, "four"); 1596 fail("UnsupportedOperationException expected"); 1597 } catch (UnsupportedOperationException expected) { 1598 } 1599 try { 1600 unmod.putAll(Collections.singletonMap(4, "four")); 1601 fail("UnsupportedOperationException expected"); 1602 } catch (UnsupportedOperationException expected) { 1603 } 1604 try { 1605 unmod.remove(4); 1606 fail("UnsupportedOperationException expected"); 1607 } catch (UnsupportedOperationException expected) { 1608 } 1609 try { 1610 unmod.pollFirstEntry(); 1611 fail("UnsupportedOperationException expected"); 1612 } catch (UnsupportedOperationException expected) { 1613 } 1614 try { 1615 unmod.pollLastEntry(); 1616 fail("UnsupportedOperationException expected"); 1617 } catch (UnsupportedOperationException expected) { 1618 } 1619 } 1620 1621 @GwtIncompatible // NavigableMap 1622 public void testSubMap_boundedRange() { 1623 ImmutableSortedMap<Integer, Integer> map = ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0); 1624 ImmutableSortedMap<Integer, Integer> empty = ImmutableSortedMap.of(); 1625 1626 assertEquals(map, Maps.subMap(map, Range.closed(0, 12))); 1627 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.closed(0, 4))); 1628 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0), Maps.subMap(map, Range.closed(2, 6))); 1629 assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.closed(3, 7))); 1630 assertEquals(empty, Maps.subMap(map, Range.closed(20, 30))); 1631 1632 assertEquals(map, Maps.subMap(map, Range.open(0, 12))); 1633 assertEquals(ImmutableSortedMap.of(2, 0), Maps.subMap(map, Range.open(0, 4))); 1634 assertEquals(ImmutableSortedMap.of(4, 0), Maps.subMap(map, Range.open(2, 6))); 1635 assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.open(3, 7))); 1636 assertEquals(empty, Maps.subMap(map, Range.open(20, 30))); 1637 1638 assertEquals(map, Maps.subMap(map, Range.openClosed(0, 12))); 1639 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.openClosed(0, 4))); 1640 assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.openClosed(2, 6))); 1641 assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.openClosed(3, 7))); 1642 assertEquals(empty, Maps.subMap(map, Range.openClosed(20, 30))); 1643 1644 assertEquals(map, Maps.subMap(map, Range.closedOpen(0, 12))); 1645 assertEquals(ImmutableSortedMap.of(2, 0), Maps.subMap(map, Range.closedOpen(0, 4))); 1646 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.closedOpen(2, 6))); 1647 assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.closedOpen(3, 7))); 1648 assertEquals(empty, Maps.subMap(map, Range.closedOpen(20, 30))); 1649 } 1650 1651 @GwtIncompatible // NavigableMap 1652 public void testSubMap_halfBoundedRange() { 1653 ImmutableSortedMap<Integer, Integer> map = ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0); 1654 ImmutableSortedMap<Integer, Integer> empty = ImmutableSortedMap.of(); 1655 1656 assertEquals(map, Maps.subMap(map, Range.atLeast(0))); 1657 assertEquals( 1658 ImmutableSortedMap.of(4, 0, 6, 0, 8, 0, 10, 0), Maps.subMap(map, Range.atLeast(4))); 1659 assertEquals(ImmutableSortedMap.of(8, 0, 10, 0), Maps.subMap(map, Range.atLeast(7))); 1660 assertEquals(empty, Maps.subMap(map, Range.atLeast(20))); 1661 1662 assertEquals(map, Maps.subMap(map, Range.greaterThan(0))); 1663 assertEquals(ImmutableSortedMap.of(6, 0, 8, 0, 10, 0), Maps.subMap(map, Range.greaterThan(4))); 1664 assertEquals(ImmutableSortedMap.of(8, 0, 10, 0), Maps.subMap(map, Range.greaterThan(7))); 1665 assertEquals(empty, Maps.subMap(map, Range.greaterThan(20))); 1666 1667 assertEquals(empty, Maps.subMap(map, Range.lessThan(0))); 1668 assertEquals(ImmutableSortedMap.of(2, 0), Maps.subMap(map, Range.lessThan(4))); 1669 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0), Maps.subMap(map, Range.lessThan(7))); 1670 assertEquals(map, Maps.subMap(map, Range.lessThan(20))); 1671 1672 assertEquals(empty, Maps.subMap(map, Range.atMost(0))); 1673 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.atMost(4))); 1674 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0), Maps.subMap(map, Range.atMost(7))); 1675 assertEquals(map, Maps.subMap(map, Range.atMost(20))); 1676 } 1677 1678 @GwtIncompatible // NavigableMap 1679 public void testSubMap_unboundedRange() { 1680 ImmutableSortedMap<Integer, Integer> map = ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0); 1681 1682 assertEquals(map, Maps.subMap(map, Range.<Integer>all())); 1683 } 1684 1685 @GwtIncompatible // NavigableMap 1686 public void testSubMap_unnaturalOrdering() { 1687 ImmutableSortedMap<Integer, Integer> map = 1688 ImmutableSortedMap.<Integer, Integer>reverseOrder() 1689 .put(2, 0) 1690 .put(4, 0) 1691 .put(6, 0) 1692 .put(8, 0) 1693 .put(10, 0) 1694 .build(); 1695 1696 try { 1697 Maps.subMap(map, Range.closed(4, 8)); 1698 fail("IllegalArgumentException expected"); 1699 } catch (IllegalArgumentException expected) { 1700 } 1701 1702 // These results are all incorrect, but there's no way (short of iterating over the result) 1703 // to verify that with an arbitrary ordering or comparator. 1704 assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.atLeast(4))); 1705 assertEquals(ImmutableSortedMap.of(8, 0, 10, 0), Maps.subMap(map, Range.atMost(8))); 1706 assertEquals( 1707 ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0), 1708 Maps.subMap(map, Range.<Integer>all())); 1709 } 1710 } 1711