22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @bug 7126277 |
26 * @bug 7126277 |
|
27 * @run main Collisions -shortrun |
|
28 * @run main Collisions -Djdk.map.althashing.threshold=0 -shortrun |
27 * @summary Ensure Maps behave well with lots of hashCode() collisions. |
29 * @summary Ensure Maps behave well with lots of hashCode() collisions. |
28 * @author Mike Duigou |
30 * @author Mike Duigou |
29 */ |
31 */ |
30 import java.util.*; |
32 import java.util.*; |
31 import java.util.concurrent.ConcurrentHashMap; |
33 import java.util.concurrent.ConcurrentHashMap; |
32 import java.util.concurrent.ConcurrentSkipListMap; |
34 import java.util.concurrent.ConcurrentSkipListMap; |
33 |
35 |
34 public class Collisions { |
36 public class Collisions { |
35 |
37 |
|
38 /** |
|
39 * Number of elements per map. |
|
40 */ |
|
41 private static final int TEST_SIZE = 5000; |
|
42 |
36 final static class HashableInteger implements Comparable<HashableInteger> { |
43 final static class HashableInteger implements Comparable<HashableInteger> { |
37 |
44 |
38 final int value; |
45 final int value; |
39 final int hashmask; //yes duplication |
46 final int hashmask; //yes duplication |
40 |
47 |
62 @Override |
69 @Override |
63 public int compareTo(HashableInteger o) { |
70 public int compareTo(HashableInteger o) { |
64 return value - o.value; |
71 return value - o.value; |
65 } |
72 } |
66 |
73 |
|
74 @Override |
67 public String toString() { |
75 public String toString() { |
68 return Integer.toString(value); |
76 return Integer.toString(value); |
69 } |
77 } |
70 } |
78 } |
71 private static final int ITEMS = 5000; |
79 |
72 private static final Object KEYS[][]; |
80 private static Object[][] makeTestData(int size) { |
73 |
81 HashableInteger UNIQUE_OBJECTS[] = new HashableInteger[size]; |
74 static { |
82 HashableInteger COLLIDING_OBJECTS[] = new HashableInteger[size]; |
75 HashableInteger UNIQUE_OBJECTS[] = new HashableInteger[ITEMS]; |
83 String UNIQUE_STRINGS[] = new String[size]; |
76 HashableInteger COLLIDING_OBJECTS[] = new HashableInteger[ITEMS]; |
84 String COLLIDING_STRINGS[] = new String[size]; |
77 String UNIQUE_STRINGS[] = new String[ITEMS]; |
85 |
78 String COLLIDING_STRINGS[] = new String[ITEMS]; |
86 for (int i = 0; i < size; i++) { |
79 |
|
80 for (int i = 0; i < ITEMS; i++) { |
|
81 UNIQUE_OBJECTS[i] = new HashableInteger(i, Integer.MAX_VALUE); |
87 UNIQUE_OBJECTS[i] = new HashableInteger(i, Integer.MAX_VALUE); |
82 COLLIDING_OBJECTS[i] = new HashableInteger(i, 10); |
88 COLLIDING_OBJECTS[i] = new HashableInteger(i, 10); |
83 UNIQUE_STRINGS[i] = unhash(i); |
89 UNIQUE_STRINGS[i] = unhash(i); |
84 COLLIDING_STRINGS[i] = (0 == i % 2) |
90 COLLIDING_STRINGS[i] = (0 == i % 2) |
85 ? UNIQUE_STRINGS[i / 2] |
91 ? UNIQUE_STRINGS[i / 2] |
86 : "\u0000\u0000\u0000\u0000\u0000" + COLLIDING_STRINGS[i - 1]; |
92 : "\u0000\u0000\u0000\u0000\u0000" + COLLIDING_STRINGS[i - 1]; |
87 } |
93 } |
88 |
94 |
89 KEYS = new Object[][] { |
95 return new Object[][] { |
90 new Object[]{"Unique Objects", UNIQUE_OBJECTS}, |
96 new Object[]{"Unique Objects", UNIQUE_OBJECTS}, |
91 new Object[]{"Colliding Objects", COLLIDING_OBJECTS}, |
97 new Object[]{"Colliding Objects", COLLIDING_OBJECTS}, |
92 new Object[]{"Unique Strings", UNIQUE_STRINGS}, |
98 new Object[]{"Unique Strings", UNIQUE_STRINGS}, |
93 new Object[]{"Colliding Strings", COLLIDING_STRINGS} |
99 new Object[]{"Colliding Strings", COLLIDING_STRINGS} |
94 }; |
100 }; |
130 partial.append((char) rem); |
136 partial.append((char) rem); |
131 } |
137 } |
132 } |
138 } |
133 |
139 |
134 private static void realMain(String[] args) throws Throwable { |
140 private static void realMain(String[] args) throws Throwable { |
135 for (Object[] keys_desc : KEYS) { |
141 boolean shortRun = args.length > 0 && args[0].equals("-shortrun"); |
136 Map<Object, Object>[] MAPS = (Map<Object, Object>[]) new Map[]{ |
142 |
|
143 Object[][] mapKeys = makeTestData(shortRun ? (TEST_SIZE / 2) : TEST_SIZE); |
|
144 |
|
145 // loop through data sets |
|
146 for (Object[] keys_desc : mapKeys) { |
|
147 Map<Object, Object>[] maps = (Map<Object, Object>[]) new Map[]{ |
|
148 new HashMap<>(), |
137 new Hashtable<>(), |
149 new Hashtable<>(), |
138 new HashMap<>(), |
|
139 new IdentityHashMap<>(), |
150 new IdentityHashMap<>(), |
140 new LinkedHashMap<>(), |
151 new LinkedHashMap<>(), |
|
152 new TreeMap<>(), |
|
153 new WeakHashMap<>(), |
141 new ConcurrentHashMap<>(), |
154 new ConcurrentHashMap<>(), |
142 new WeakHashMap<>(), |
|
143 new TreeMap<>(), |
|
144 new ConcurrentSkipListMap<>() |
155 new ConcurrentSkipListMap<>() |
145 }; |
156 }; |
146 |
157 |
147 for (Map<Object, Object> map : MAPS) { |
158 // for each map type. |
|
159 for (Map<Object, Object> map : maps) { |
148 String desc = (String) keys_desc[0]; |
160 String desc = (String) keys_desc[0]; |
149 Object[] keys = (Object[]) keys_desc[1]; |
161 Object[] keys = (Object[]) keys_desc[1]; |
150 try { |
162 try { |
151 testMap(map, desc, keys); |
163 testMap(map, desc, keys); |
152 } catch(Exception all) { |
164 } catch(Exception all) { |
153 unexpected("Failed for " + map.getClass().getName() + " with " + desc, all); |
165 unexpected("Failed for " + map.getClass().getName() + " with " + desc, all); |
154 } |
166 } |
155 } |
167 } |
156 } |
168 } |