1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 * Other contributors include Andrew Wright, Jeffrey Hayes, 6 * Pat Fisher, Mike Judd. 7 */ 8 9 package jsr166; 10 11 import java.util.ArrayList; 12 import java.util.Arrays; 13 import java.util.Collection; 14 import java.util.Collections; 15 import java.util.Enumeration; 16 import java.util.Iterator; 17 import java.util.Map; 18 import java.util.Random; 19 import java.util.Set; 20 import java.util.concurrent.ConcurrentHashMap; 21 22 import junit.framework.Test; 23 import junit.framework.TestSuite; 24 25 public class ConcurrentHashMapTest extends JSR166TestCase { 26 // android-note: Removed because the CTS runner does a bad job of 27 // retrying tests that have suite() declarations. 28 // 29 // public static void main(String[] args) { 30 // main(suite(), args); 31 // } 32 // public static Test suite() { 33 // return new TestSuite(...); 34 // } 35 36 /** 37 * Returns a new map from Integers 1-5 to Strings "A"-"E". 38 */ 39 private static ConcurrentHashMap<Integer, String> map5() { 40 ConcurrentHashMap map = new ConcurrentHashMap<Integer, String>(5); 41 assertTrue(map.isEmpty()); 42 map.put(one, "A"); 43 map.put(two, "B"); 44 map.put(three, "C"); 45 map.put(four, "D"); 46 map.put(five, "E"); 47 assertFalse(map.isEmpty()); 48 assertEquals(5, map.size()); 49 return map; 50 } 51 52 /** Re-implement Integer.compare for old java versions */ 53 static int compare(int x, int y) { return x < y ? -1 : x > y ? 1 : 0; } 54 55 // classes for testing Comparable fallbacks 56 static class BI implements Comparable<BI> { 57 private final int value; 58 BI(int value) { this.value = value; } 59 public int compareTo(BI other) { 60 return compare(value, other.value); 61 } 62 public boolean equals(Object x) { 63 return (x instanceof BI) && ((BI)x).value == value; 64 } 65 public int hashCode() { return 42; } 66 } 67 static class CI extends BI { CI(int value) { super(value); } } 68 static class DI extends BI { DI(int value) { super(value); } } 69 70 static class BS implements Comparable<BS> { 71 private final String value; 72 BS(String value) { this.value = value; } 73 public int compareTo(BS other) { 74 return value.compareTo(other.value); 75 } 76 public boolean equals(Object x) { 77 return (x instanceof BS) && value.equals(((BS)x).value); 78 } 79 public int hashCode() { return 42; } 80 } 81 82 static class LexicographicList<E extends Comparable<E>> extends ArrayList<E> 83 implements Comparable<LexicographicList<E>> { 84 LexicographicList(Collection<E> c) { super(c); } 85 LexicographicList(E e) { super(Collections.singleton(e)); } 86 public int compareTo(LexicographicList<E> other) { 87 int common = Math.min(size(), other.size()); 88 int r = 0; 89 for (int i = 0; i < common; i++) { 90 if ((r = get(i).compareTo(other.get(i))) != 0) 91 break; 92 } 93 if (r == 0) 94 r = compare(size(), other.size()); 95 return r; 96 } 97 private static final long serialVersionUID = 0; 98 } 99 100 static class CollidingObject { 101 final String value; 102 CollidingObject(final String value) { this.value = value; } 103 public int hashCode() { return this.value.hashCode() & 1; } 104 public boolean equals(final Object obj) { 105 return (obj instanceof CollidingObject) && ((CollidingObject)obj).value.equals(value); 106 } 107 } 108 109 static class ComparableCollidingObject extends CollidingObject implements Comparable<ComparableCollidingObject> { 110 ComparableCollidingObject(final String value) { super(value); } 111 public int compareTo(final ComparableCollidingObject o) { 112 return value.compareTo(o.value); 113 } 114 } 115 116 /** 117 * Inserted elements that are subclasses of the same Comparable 118 * class are found. 119 */ 120 public void testComparableFamily() { 121 int size = 500; // makes measured test run time -> 60ms 122 ConcurrentHashMap<BI, Boolean> m = 123 new ConcurrentHashMap<BI, Boolean>(); 124 for (int i = 0; i < size; i++) { 125 assertTrue(m.put(new CI(i), true) == null); 126 } 127 for (int i = 0; i < size; i++) { 128 assertTrue(m.containsKey(new CI(i))); 129 assertTrue(m.containsKey(new DI(i))); 130 } 131 } 132 133 /** 134 * Elements of classes with erased generic type parameters based 135 * on Comparable can be inserted and found. 136 */ 137 public void testGenericComparable() { 138 int size = 120; // makes measured test run time -> 60ms 139 ConcurrentHashMap<Object, Boolean> m = 140 new ConcurrentHashMap<Object, Boolean>(); 141 for (int i = 0; i < size; i++) { 142 BI bi = new BI(i); 143 BS bs = new BS(String.valueOf(i)); 144 LexicographicList<BI> bis = new LexicographicList<BI>(bi); 145 LexicographicList<BS> bss = new LexicographicList<BS>(bs); 146 assertTrue(m.putIfAbsent(bis, true) == null); 147 assertTrue(m.containsKey(bis)); 148 if (m.putIfAbsent(bss, true) == null) 149 assertTrue(m.containsKey(bss)); 150 assertTrue(m.containsKey(bis)); 151 } 152 for (int i = 0; i < size; i++) { 153 assertTrue(m.containsKey(Collections.singletonList(new BI(i)))); 154 } 155 } 156 157 /** 158 * Elements of non-comparable classes equal to those of classes 159 * with erased generic type parameters based on Comparable can be 160 * inserted and found. 161 */ 162 public void testGenericComparable2() { 163 int size = 500; // makes measured test run time -> 60ms 164 ConcurrentHashMap<Object, Boolean> m = 165 new ConcurrentHashMap<Object, Boolean>(); 166 for (int i = 0; i < size; i++) { 167 m.put(Collections.singletonList(new BI(i)), true); 168 } 169 170 for (int i = 0; i < size; i++) { 171 LexicographicList<BI> bis = new LexicographicList<BI>(new BI(i)); 172 assertTrue(m.containsKey(bis)); 173 } 174 } 175 176 /** 177 * Mixtures of instances of comparable and non-comparable classes 178 * can be inserted and found. 179 */ 180 public void testMixedComparable() { 181 int size = 1200; // makes measured test run time -> 35ms 182 ConcurrentHashMap<Object, Object> map = 183 new ConcurrentHashMap<Object, Object>(); 184 Random rng = new Random(); 185 for (int i = 0; i < size; i++) { 186 Object x; 187 switch (rng.nextInt(4)) { 188 case 0: 189 x = new Object(); 190 break; 191 case 1: 192 x = new CollidingObject(Integer.toString(i)); 193 break; 194 default: 195 x = new ComparableCollidingObject(Integer.toString(i)); 196 } 197 assertNull(map.put(x, x)); 198 } 199 int count = 0; 200 for (Object k : map.keySet()) { 201 assertEquals(map.get(k), k); 202 ++count; 203 } 204 assertEquals(count, size); 205 assertEquals(map.size(), size); 206 for (Object k : map.keySet()) { 207 assertEquals(map.put(k, k), k); 208 } 209 } 210 211 /** 212 * clear removes all pairs 213 */ 214 public void testClear() { 215 ConcurrentHashMap map = map5(); 216 map.clear(); 217 assertEquals(0, map.size()); 218 } 219 220 /** 221 * Maps with same contents are equal 222 */ 223 public void testEquals() { 224 ConcurrentHashMap map1 = map5(); 225 ConcurrentHashMap map2 = map5(); 226 assertEquals(map1, map2); 227 assertEquals(map2, map1); 228 map1.clear(); 229 assertFalse(map1.equals(map2)); 230 assertFalse(map2.equals(map1)); 231 } 232 233 /** 234 * hashCode() equals sum of each key.hashCode ^ value.hashCode 235 */ 236 public void testHashCode() { 237 ConcurrentHashMap<Integer,String> map = map5(); 238 int sum = 0; 239 for (Map.Entry<Integer,String> e : map.entrySet()) 240 sum += e.getKey().hashCode() ^ e.getValue().hashCode(); 241 assertEquals(sum, map.hashCode()); 242 } 243 244 /** 245 * contains returns true for contained value 246 */ 247 public void testContains() { 248 ConcurrentHashMap map = map5(); 249 assertTrue(map.contains("A")); 250 assertFalse(map.contains("Z")); 251 } 252 253 /** 254 * containsKey returns true for contained key 255 */ 256 public void testContainsKey() { 257 ConcurrentHashMap map = map5(); 258 assertTrue(map.containsKey(one)); 259 assertFalse(map.containsKey(zero)); 260 } 261 262 /** 263 * containsValue returns true for held values 264 */ 265 public void testContainsValue() { 266 ConcurrentHashMap map = map5(); 267 assertTrue(map.containsValue("A")); 268 assertFalse(map.containsValue("Z")); 269 } 270 271 /** 272 * enumeration returns an enumeration containing the correct 273 * elements 274 */ 275 public void testEnumeration() { 276 ConcurrentHashMap map = map5(); 277 Enumeration e = map.elements(); 278 int count = 0; 279 while (e.hasMoreElements()) { 280 count++; 281 e.nextElement(); 282 } 283 assertEquals(5, count); 284 } 285 286 /** 287 * get returns the correct element at the given key, 288 * or null if not present 289 */ 290 public void testGet() { 291 ConcurrentHashMap map = map5(); 292 assertEquals("A", (String)map.get(one)); 293 ConcurrentHashMap empty = new ConcurrentHashMap(); 294 assertNull(map.get("anything")); 295 assertNull(empty.get("anything")); 296 } 297 298 /** 299 * isEmpty is true of empty map and false for non-empty 300 */ 301 public void testIsEmpty() { 302 ConcurrentHashMap empty = new ConcurrentHashMap(); 303 ConcurrentHashMap map = map5(); 304 assertTrue(empty.isEmpty()); 305 assertFalse(map.isEmpty()); 306 } 307 308 /** 309 * keys returns an enumeration containing all the keys from the map 310 */ 311 public void testKeys() { 312 ConcurrentHashMap map = map5(); 313 Enumeration e = map.keys(); 314 int count = 0; 315 while (e.hasMoreElements()) { 316 count++; 317 e.nextElement(); 318 } 319 assertEquals(5, count); 320 } 321 322 /** 323 * keySet returns a Set containing all the keys 324 */ 325 public void testKeySet() { 326 ConcurrentHashMap map = map5(); 327 Set s = map.keySet(); 328 assertEquals(5, s.size()); 329 assertTrue(s.contains(one)); 330 assertTrue(s.contains(two)); 331 assertTrue(s.contains(three)); 332 assertTrue(s.contains(four)); 333 assertTrue(s.contains(five)); 334 } 335 336 /** 337 * keySet.toArray returns contains all keys 338 */ 339 public void testKeySetToArray() { 340 ConcurrentHashMap map = map5(); 341 Set s = map.keySet(); 342 Object[] ar = s.toArray(); 343 assertTrue(s.containsAll(Arrays.asList(ar))); 344 assertEquals(5, ar.length); 345 ar[0] = m10; 346 assertFalse(s.containsAll(Arrays.asList(ar))); 347 } 348 349 /** 350 * Values.toArray contains all values 351 */ 352 public void testValuesToArray() { 353 ConcurrentHashMap map = map5(); 354 Collection v = map.values(); 355 Object[] ar = v.toArray(); 356 ArrayList s = new ArrayList(Arrays.asList(ar)); 357 assertEquals(5, ar.length); 358 assertTrue(s.contains("A")); 359 assertTrue(s.contains("B")); 360 assertTrue(s.contains("C")); 361 assertTrue(s.contains("D")); 362 assertTrue(s.contains("E")); 363 } 364 365 /** 366 * entrySet.toArray contains all entries 367 */ 368 public void testEntrySetToArray() { 369 ConcurrentHashMap map = map5(); 370 Set s = map.entrySet(); 371 Object[] ar = s.toArray(); 372 assertEquals(5, ar.length); 373 for (int i = 0; i < 5; ++i) { 374 assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); 375 assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); 376 } 377 } 378 379 /** 380 * values collection contains all values 381 */ 382 public void testValues() { 383 ConcurrentHashMap map = map5(); 384 Collection s = map.values(); 385 assertEquals(5, s.size()); 386 assertTrue(s.contains("A")); 387 assertTrue(s.contains("B")); 388 assertTrue(s.contains("C")); 389 assertTrue(s.contains("D")); 390 assertTrue(s.contains("E")); 391 } 392 393 /** 394 * entrySet contains all pairs 395 */ 396 public void testEntrySet() { 397 ConcurrentHashMap map = map5(); 398 Set s = map.entrySet(); 399 assertEquals(5, s.size()); 400 Iterator it = s.iterator(); 401 while (it.hasNext()) { 402 Map.Entry e = (Map.Entry) it.next(); 403 assertTrue( 404 (e.getKey().equals(one) && e.getValue().equals("A")) || 405 (e.getKey().equals(two) && e.getValue().equals("B")) || 406 (e.getKey().equals(three) && e.getValue().equals("C")) || 407 (e.getKey().equals(four) && e.getValue().equals("D")) || 408 (e.getKey().equals(five) && e.getValue().equals("E"))); 409 } 410 } 411 412 /** 413 * putAll adds all key-value pairs from the given map 414 */ 415 public void testPutAll() { 416 ConcurrentHashMap empty = new ConcurrentHashMap(); 417 ConcurrentHashMap map = map5(); 418 empty.putAll(map); 419 assertEquals(5, empty.size()); 420 assertTrue(empty.containsKey(one)); 421 assertTrue(empty.containsKey(two)); 422 assertTrue(empty.containsKey(three)); 423 assertTrue(empty.containsKey(four)); 424 assertTrue(empty.containsKey(five)); 425 } 426 427 /** 428 * putIfAbsent works when the given key is not present 429 */ 430 public void testPutIfAbsent() { 431 ConcurrentHashMap map = map5(); 432 map.putIfAbsent(six, "Z"); 433 assertTrue(map.containsKey(six)); 434 } 435 436 /** 437 * putIfAbsent does not add the pair if the key is already present 438 */ 439 public void testPutIfAbsent2() { 440 ConcurrentHashMap map = map5(); 441 assertEquals("A", map.putIfAbsent(one, "Z")); 442 } 443 444 /** 445 * replace fails when the given key is not present 446 */ 447 public void testReplace() { 448 ConcurrentHashMap map = map5(); 449 assertNull(map.replace(six, "Z")); 450 assertFalse(map.containsKey(six)); 451 } 452 453 /** 454 * replace succeeds if the key is already present 455 */ 456 public void testReplace2() { 457 ConcurrentHashMap map = map5(); 458 assertNotNull(map.replace(one, "Z")); 459 assertEquals("Z", map.get(one)); 460 } 461 462 /** 463 * replace value fails when the given key not mapped to expected value 464 */ 465 public void testReplaceValue() { 466 ConcurrentHashMap map = map5(); 467 assertEquals("A", map.get(one)); 468 assertFalse(map.replace(one, "Z", "Z")); 469 assertEquals("A", map.get(one)); 470 } 471 472 /** 473 * replace value succeeds when the given key mapped to expected value 474 */ 475 public void testReplaceValue2() { 476 ConcurrentHashMap map = map5(); 477 assertEquals("A", map.get(one)); 478 assertTrue(map.replace(one, "A", "Z")); 479 assertEquals("Z", map.get(one)); 480 } 481 482 /** 483 * remove removes the correct key-value pair from the map 484 */ 485 public void testRemove() { 486 ConcurrentHashMap map = map5(); 487 map.remove(five); 488 assertEquals(4, map.size()); 489 assertFalse(map.containsKey(five)); 490 } 491 492 /** 493 * remove(key,value) removes only if pair present 494 */ 495 public void testRemove2() { 496 ConcurrentHashMap map = map5(); 497 map.remove(five, "E"); 498 assertEquals(4, map.size()); 499 assertFalse(map.containsKey(five)); 500 map.remove(four, "A"); 501 assertEquals(4, map.size()); 502 assertTrue(map.containsKey(four)); 503 } 504 505 /** 506 * size returns the correct values 507 */ 508 public void testSize() { 509 ConcurrentHashMap map = map5(); 510 ConcurrentHashMap empty = new ConcurrentHashMap(); 511 assertEquals(0, empty.size()); 512 assertEquals(5, map.size()); 513 } 514 515 /** 516 * toString contains toString of elements 517 */ 518 public void testToString() { 519 ConcurrentHashMap map = map5(); 520 String s = map.toString(); 521 for (int i = 1; i <= 5; ++i) { 522 assertTrue(s.contains(String.valueOf(i))); 523 } 524 } 525 526 // Exception tests 527 528 /** 529 * Cannot create with only negative capacity 530 */ 531 public void testConstructor1() { 532 try { 533 new ConcurrentHashMap(-1); 534 shouldThrow(); 535 } catch (IllegalArgumentException success) {} 536 } 537 538 /** 539 * Constructor (initialCapacity, loadFactor) throws 540 * IllegalArgumentException if either argument is negative 541 */ 542 public void testConstructor2() { 543 try { 544 new ConcurrentHashMap(-1, .75f); 545 shouldThrow(); 546 } catch (IllegalArgumentException success) {} 547 548 try { 549 new ConcurrentHashMap(16, -1); 550 shouldThrow(); 551 } catch (IllegalArgumentException success) {} 552 } 553 554 /** 555 * Constructor (initialCapacity, loadFactor, concurrencyLevel) 556 * throws IllegalArgumentException if any argument is negative 557 */ 558 public void testConstructor3() { 559 try { 560 new ConcurrentHashMap(-1, .75f, 1); 561 shouldThrow(); 562 } catch (IllegalArgumentException success) {} 563 564 try { 565 new ConcurrentHashMap(16, -1, 1); 566 shouldThrow(); 567 } catch (IllegalArgumentException success) {} 568 569 try { 570 new ConcurrentHashMap(16, .75f, -1); 571 shouldThrow(); 572 } catch (IllegalArgumentException success) {} 573 } 574 575 /** 576 * ConcurrentHashMap(map) throws NullPointerException if the given 577 * map is null 578 */ 579 public void testConstructor4() { 580 try { 581 new ConcurrentHashMap(null); 582 shouldThrow(); 583 } catch (NullPointerException success) {} 584 } 585 586 /** 587 * ConcurrentHashMap(map) creates a new map with the same mappings 588 * as the given map 589 */ 590 public void testConstructor5() { 591 ConcurrentHashMap map1 = map5(); 592 ConcurrentHashMap map2 = new ConcurrentHashMap(map5()); 593 assertTrue(map2.equals(map1)); 594 map2.put(one, "F"); 595 assertFalse(map2.equals(map1)); 596 } 597 598 /** 599 * get(null) throws NPE 600 */ 601 public void testGet_NullPointerException() { 602 ConcurrentHashMap c = new ConcurrentHashMap(5); 603 try { 604 c.get(null); 605 shouldThrow(); 606 } catch (NullPointerException success) {} 607 } 608 609 /** 610 * containsKey(null) throws NPE 611 */ 612 public void testContainsKey_NullPointerException() { 613 ConcurrentHashMap c = new ConcurrentHashMap(5); 614 try { 615 c.containsKey(null); 616 shouldThrow(); 617 } catch (NullPointerException success) {} 618 } 619 620 /** 621 * containsValue(null) throws NPE 622 */ 623 public void testContainsValue_NullPointerException() { 624 ConcurrentHashMap c = new ConcurrentHashMap(5); 625 try { 626 c.containsValue(null); 627 shouldThrow(); 628 } catch (NullPointerException success) {} 629 } 630 631 /** 632 * contains(null) throws NPE 633 */ 634 public void testContains_NullPointerException() { 635 ConcurrentHashMap c = new ConcurrentHashMap(5); 636 try { 637 c.contains(null); 638 shouldThrow(); 639 } catch (NullPointerException success) {} 640 } 641 642 /** 643 * put(null,x) throws NPE 644 */ 645 public void testPut1_NullPointerException() { 646 ConcurrentHashMap c = new ConcurrentHashMap(5); 647 try { 648 c.put(null, "whatever"); 649 shouldThrow(); 650 } catch (NullPointerException success) {} 651 } 652 653 /** 654 * put(x, null) throws NPE 655 */ 656 public void testPut2_NullPointerException() { 657 ConcurrentHashMap c = new ConcurrentHashMap(5); 658 try { 659 c.put("whatever", null); 660 shouldThrow(); 661 } catch (NullPointerException success) {} 662 } 663 664 /** 665 * putIfAbsent(null, x) throws NPE 666 */ 667 public void testPutIfAbsent1_NullPointerException() { 668 ConcurrentHashMap c = new ConcurrentHashMap(5); 669 try { 670 c.putIfAbsent(null, "whatever"); 671 shouldThrow(); 672 } catch (NullPointerException success) {} 673 } 674 675 /** 676 * replace(null, x) throws NPE 677 */ 678 public void testReplace_NullPointerException() { 679 ConcurrentHashMap c = new ConcurrentHashMap(5); 680 try { 681 c.replace(null, "whatever"); 682 shouldThrow(); 683 } catch (NullPointerException success) {} 684 } 685 686 /** 687 * replace(null, x, y) throws NPE 688 */ 689 public void testReplaceValue_NullPointerException() { 690 ConcurrentHashMap c = new ConcurrentHashMap(5); 691 try { 692 c.replace(null, one, "whatever"); 693 shouldThrow(); 694 } catch (NullPointerException success) {} 695 } 696 697 /** 698 * putIfAbsent(x, null) throws NPE 699 */ 700 public void testPutIfAbsent2_NullPointerException() { 701 ConcurrentHashMap c = new ConcurrentHashMap(5); 702 try { 703 c.putIfAbsent("whatever", null); 704 shouldThrow(); 705 } catch (NullPointerException success) {} 706 } 707 708 /** 709 * replace(x, null) throws NPE 710 */ 711 public void testReplace2_NullPointerException() { 712 ConcurrentHashMap c = new ConcurrentHashMap(5); 713 try { 714 c.replace("whatever", null); 715 shouldThrow(); 716 } catch (NullPointerException success) {} 717 } 718 719 /** 720 * replace(x, null, y) throws NPE 721 */ 722 public void testReplaceValue2_NullPointerException() { 723 ConcurrentHashMap c = new ConcurrentHashMap(5); 724 try { 725 c.replace("whatever", null, "A"); 726 shouldThrow(); 727 } catch (NullPointerException success) {} 728 } 729 730 /** 731 * replace(x, y, null) throws NPE 732 */ 733 public void testReplaceValue3_NullPointerException() { 734 ConcurrentHashMap c = new ConcurrentHashMap(5); 735 try { 736 c.replace("whatever", one, null); 737 shouldThrow(); 738 } catch (NullPointerException success) {} 739 } 740 741 /** 742 * remove(null) throws NPE 743 */ 744 public void testRemove1_NullPointerException() { 745 ConcurrentHashMap c = new ConcurrentHashMap(5); 746 c.put("sadsdf", "asdads"); 747 try { 748 c.remove(null); 749 shouldThrow(); 750 } catch (NullPointerException success) {} 751 } 752 753 /** 754 * remove(null, x) throws NPE 755 */ 756 public void testRemove2_NullPointerException() { 757 ConcurrentHashMap c = new ConcurrentHashMap(5); 758 c.put("sadsdf", "asdads"); 759 try { 760 c.remove(null, "whatever"); 761 shouldThrow(); 762 } catch (NullPointerException success) {} 763 } 764 765 /** 766 * remove(x, null) returns false 767 */ 768 public void testRemove3() { 769 ConcurrentHashMap c = new ConcurrentHashMap(5); 770 c.put("sadsdf", "asdads"); 771 assertFalse(c.remove("sadsdf", null)); 772 } 773 774 /** 775 * A deserialized map equals original 776 */ 777 public void testSerialization() throws Exception { 778 Map x = map5(); 779 Map y = serialClone(x); 780 781 assertNotSame(x, y); 782 assertEquals(x.size(), y.size()); 783 assertEquals(x, y); 784 assertEquals(y, x); 785 } 786 787 /** 788 * SetValue of an EntrySet entry sets value in the map. 789 */ 790 public void testSetValueWriteThrough() { 791 // Adapted from a bug report by Eric Zoerner 792 ConcurrentHashMap map = new ConcurrentHashMap(2, 5.0f, 1); 793 assertTrue(map.isEmpty()); 794 for (int i = 0; i < 20; i++) 795 map.put(new Integer(i), new Integer(i)); 796 assertFalse(map.isEmpty()); 797 Map.Entry entry1 = (Map.Entry)map.entrySet().iterator().next(); 798 // Unless it happens to be first (in which case remainder of 799 // test is skipped), remove a possibly-colliding key from map 800 // which, under some implementations, may cause entry1 to be 801 // cloned in map 802 if (!entry1.getKey().equals(new Integer(16))) { 803 map.remove(new Integer(16)); 804 entry1.setValue("XYZ"); 805 assertTrue(map.containsValue("XYZ")); // fails if write-through broken 806 } 807 } 808 809 } 810