Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/util/Map/InPlaceOpsCollisions.java
41149 views
1
/*
2
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 8005698
27
* @run testng/othervm -Dtest.map.collisions.shortrun=true InPlaceOpsCollisions
28
* @summary Ensure overrides of in-place operations in Maps behave well with lots of collisions.
29
*/
30
31
import java.util.Arrays;
32
import java.util.Comparator;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.LinkedHashMap;
36
import java.util.Map;
37
import java.util.TreeMap;
38
import java.util.function.BiFunction;
39
import java.util.function.Function;
40
import java.util.function.Supplier;
41
42
import org.testng.annotations.DataProvider;
43
import org.testng.annotations.Test;
44
import static org.testng.Assert.assertTrue;
45
import static org.testng.Assert.assertFalse;
46
import static org.testng.Assert.assertEquals;
47
import static org.testng.Assert.assertNull;
48
49
public class InPlaceOpsCollisions extends MapWithCollisionsProviders {
50
51
@Test(dataProvider = "mapsWithObjectsAndStrings")
52
void testPutIfAbsent(String desc, Supplier<Map<Object, Object>> ms, Object val) {
53
Map<Object, Object> map = ms.get();
54
Object[] keys = map.keySet().toArray();
55
Object retVal;
56
removeOddKeys(map, keys);
57
for (int i = 0; i < keys.length; i++) {
58
retVal = map.putIfAbsent(keys[i], val);
59
if (i % 2 == 0) { // even: not absent, not put
60
61
assertEquals(retVal, keys[i],
62
String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
63
assertEquals(keys[i], map.get(keys[i]),
64
String.format("putIfAbsent: get(%s[%d])", desc, i));
65
assertTrue(map.containsValue(keys[i]),
66
String.format("putIfAbsent: containsValue(%s[%d])", desc, i));
67
} else { // odd: absent, was put
68
assertNull(retVal,
69
String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
70
assertEquals(val, map.get(keys[i]),
71
String.format("putIfAbsent: get(%s[%d])", desc, i));
72
assertFalse(map.containsValue(keys[i]),
73
String.format("putIfAbsent: !containsValue(%s[%d])", desc, i));
74
}
75
assertTrue(map.containsKey(keys[i]),
76
String.format("insertion: containsKey(%s[%d])", desc, i));
77
}
78
assertEquals(map.size(), keys.length,
79
String.format("map expected size m%d != k%d", map.size(), keys.length));
80
}
81
82
@Test(dataProvider = "nullValueFriendlyMaps")
83
void testPutIfAbsentOverwriteNull(String desc, Supplier<Map<Object, Object>> ms) {
84
Map<Object, Object> map = ms.get();
85
map.put("key", null);
86
assertEquals(map.size(), 1, desc + ": size != 1");
87
assertTrue(map.containsKey("key"), desc + ": does not have key");
88
assertNull(map.get("key"), desc + ": value is not null");
89
map.putIfAbsent("key", "value"); // must rewrite
90
assertEquals(map.size(), 1, desc + ": size != 1");
91
assertTrue(map.containsKey("key"), desc + ": does not have key");
92
assertEquals(map.get("key"), "value", desc + ": value is not 'value'");
93
}
94
95
@Test(dataProvider = "mapsWithObjectsAndStrings")
96
void testRemoveMapping(String desc, Supplier<Map<Object, Object>> ms, Object val) {
97
Map<Object, Object> map = ms.get();
98
Object[] keys = map.keySet().toArray();
99
boolean removed;
100
int removes = 0;
101
remapOddKeys(map, keys, val);
102
for (int i = 0; i < keys.length; i++) {
103
removed = map.remove(keys[i], keys[i]);
104
if (i % 2 == 0) { // even: original mapping, should be removed
105
assertTrue(removed,
106
String.format("removeMapping: retVal(%s[%d])", desc, i));
107
assertNull(map.get(keys[i]),
108
String.format("removeMapping: get(%s[%d])", desc, i));
109
assertFalse(map.containsKey(keys[i]),
110
String.format("removeMapping: !containsKey(%s[%d])", desc, i));
111
assertFalse(map.containsValue(keys[i]),
112
String.format("removeMapping: !containsValue(%s[%d])", desc, i));
113
removes++;
114
} else { // odd: new mapping, not removed
115
assertFalse(removed,
116
String.format("removeMapping: retVal(%s[%d])", desc, i));
117
assertEquals(val, map.get(keys[i]),
118
String.format("removeMapping: get(%s[%d])", desc, i));
119
assertTrue(map.containsKey(keys[i]),
120
String.format("removeMapping: containsKey(%s[%d])", desc, i));
121
assertTrue(map.containsValue(val),
122
String.format("removeMapping: containsValue(%s[%d])", desc, i));
123
}
124
}
125
assertEquals(map.size(), keys.length - removes,
126
String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
127
}
128
129
@Test(dataProvider = "mapsWithObjectsAndStrings")
130
void testReplaceOldValue(String desc, Supplier<Map<Object, Object>> ms, Object val) {
131
// remap odds to val
132
// call replace to replace for val, for all keys
133
// check that all keys map to value from keys array
134
Map<Object, Object> map = ms.get();
135
Object[] keys = map.keySet().toArray();
136
boolean replaced;
137
remapOddKeys(map, keys, val);
138
139
for (int i = 0; i < keys.length; i++) {
140
replaced = map.replace(keys[i], val, keys[i]);
141
if (i % 2 == 0) { // even: original mapping, should not be replaced
142
assertFalse(replaced,
143
String.format("replaceOldValue: retVal(%s[%d])", desc, i));
144
} else { // odd: new mapping, should be replaced
145
assertTrue(replaced,
146
String.format("replaceOldValue: get(%s[%d])", desc, i));
147
}
148
assertEquals(keys[i], map.get(keys[i]),
149
String.format("replaceOldValue: get(%s[%d])", desc, i));
150
assertTrue(map.containsKey(keys[i]),
151
String.format("replaceOldValue: containsKey(%s[%d])", desc, i));
152
assertTrue(map.containsValue(keys[i]),
153
String.format("replaceOldValue: containsValue(%s[%d])", desc, i));
154
}
155
assertFalse(map.containsValue(val),
156
String.format("replaceOldValue: !containsValue(%s[%s])", desc, val));
157
assertEquals(map.size(), keys.length,
158
String.format("map expected size m%d != k%d", map.size(), keys.length));
159
}
160
161
@Test(dataProvider = "mapsWithObjectsAndStrings")
162
void testReplaceIfMapped(String desc, Supplier<Map<Object, Object>> ms, Object val) {
163
// remove odd keys
164
// call replace for all keys[]
165
// odd keys should remain absent, even keys should be mapped to EXTRA, no value from keys[] should be in map
166
Map<Object, Object> map = ms.get();
167
Object[] keys = map.keySet().toArray();
168
int expectedSize1 = 0;
169
removeOddKeys(map, keys);
170
int expectedSize2 = map.size();
171
172
for (int i = 0; i < keys.length; i++) {
173
Object retVal = map.replace(keys[i], val);
174
if (i % 2 == 0) { // even: still in map, should be replaced
175
assertEquals(retVal, keys[i],
176
String.format("replaceIfMapped: retVal(%s[%d])", desc, i));
177
assertEquals(val, map.get(keys[i]),
178
String.format("replaceIfMapped: get(%s[%d])", desc, i));
179
assertTrue(map.containsKey(keys[i]),
180
String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
181
expectedSize1++;
182
} else { // odd: was removed, should not be replaced
183
assertNull(retVal,
184
String.format("replaceIfMapped: retVal(%s[%d])", desc, i));
185
assertNull(map.get(keys[i]),
186
String.format("replaceIfMapped: get(%s[%d])", desc, i));
187
assertFalse(map.containsKey(keys[i]),
188
String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
189
}
190
assertFalse(map.containsValue(keys[i]),
191
String.format("replaceIfMapped: !containsValue(%s[%d])", desc, i));
192
}
193
assertTrue(map.containsValue(val),
194
String.format("replaceIfMapped: containsValue(%s[%s])", desc, val));
195
assertEquals(map.size(), expectedSize1,
196
String.format("map expected size#1 m%d != k%d", map.size(), expectedSize1));
197
assertEquals(map.size(), expectedSize2,
198
String.format("map expected size#2 m%d != k%d", map.size(), expectedSize2));
199
200
}
201
202
private static <T> void testComputeIfAbsent(Map<T, T> map, String desc, T[] keys,
203
Function<T, T> mappingFunction) {
204
// remove a third of the keys
205
// call computeIfAbsent for all keys, func returns EXTRA
206
// check that removed keys now -> EXTRA, other keys -> original val
207
T expectedVal = mappingFunction.apply(keys[0]);
208
T retVal;
209
int expectedSize = 0;
210
removeThirdKeys(map, keys);
211
for (int i = 0; i < keys.length; i++) {
212
retVal = map.computeIfAbsent(keys[i], mappingFunction);
213
if (i % 3 != 2) { // key present, not computed
214
assertEquals(retVal, keys[i],
215
String.format("computeIfAbsent: (%s[%d]) retVal", desc, i));
216
assertEquals(keys[i], map.get(keys[i]),
217
String.format("computeIfAbsent: get(%s[%d])", desc, i));
218
assertTrue(map.containsValue(keys[i]),
219
String.format("computeIfAbsent: containsValue(%s[%d])", desc, i));
220
assertTrue(map.containsKey(keys[i]),
221
String.format("insertion: containsKey(%s[%d])", desc, i));
222
expectedSize++;
223
} else { // key absent, computed unless function return null
224
assertEquals(retVal, expectedVal,
225
String.format("computeIfAbsent: (%s[%d]) retVal", desc, i));
226
assertEquals(expectedVal, map.get(keys[i]),
227
String.format("computeIfAbsent: get(%s[%d])", desc, i));
228
assertFalse(map.containsValue(keys[i]),
229
String.format("computeIfAbsent: !containsValue(%s[%d])", desc, i));
230
// mapping should not be added if function returns null
231
assertTrue(map.containsKey(keys[i]) != (expectedVal == null),
232
String.format("insertion: containsKey(%s[%d])", desc, i));
233
if (expectedVal != null) {
234
expectedSize++;
235
}
236
}
237
}
238
if (expectedVal != null) {
239
assertTrue(map.containsValue(expectedVal),
240
String.format("computeIfAbsent: containsValue(%s[%s])", desc, expectedVal));
241
}
242
assertEquals(map.size(), expectedSize,
243
String.format("map expected size m%d != k%d", map.size(), expectedSize));
244
}
245
246
@Test(dataProvider = "mapsWithObjectsAndStrings")
247
void testComputeIfAbsentNonNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
248
Map<Object, Object> map = ms.get();
249
Object[] keys = map.keySet().toArray();
250
testComputeIfAbsent(map, desc, keys, (k) -> val);
251
}
252
253
@Test(dataProvider = "mapsWithObjectsAndStrings")
254
void testComputeIfAbsentNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
255
Map<Object, Object> map = ms.get();
256
Object[] keys = map.keySet().toArray();
257
testComputeIfAbsent(map, desc, keys, (k) -> null);
258
}
259
260
@Test(dataProvider = "nullValueFriendlyMaps")
261
void testComputeIfAbsentOverwriteNull(String desc, Supplier<Map<Object, Object>> ms) {
262
Map<Object, Object> map = ms.get();
263
map.put("key", null);
264
assertEquals(map.size(), 1, desc + ": size != 1");
265
assertTrue(map.containsKey("key"), desc + ": does not have key");
266
assertNull(map.get("key"), desc + ": value is not null");
267
Object result = map.computeIfAbsent("key", k -> "value"); // must rewrite
268
assertEquals(result, "value", desc + ": computeIfAbsent result is not 'value'");
269
assertEquals(map.size(), 1, desc + ": size != 1");
270
assertTrue(map.containsKey("key"), desc + ": does not have key");
271
assertEquals(map.get("key"), "value", desc + ": value is not 'value'");
272
}
273
274
private static <T> void testComputeIfPresent(Map<T, T> map, String desc, T[] keys,
275
BiFunction<T, T, T> mappingFunction) {
276
// remove a third of the keys
277
// call testComputeIfPresent for all keys[]
278
// removed keys should remain absent, even keys should be mapped to $RESULT
279
// no value from keys[] should be in map
280
T funcResult = mappingFunction.apply(keys[0], keys[0]);
281
int expectedSize1 = 0;
282
removeThirdKeys(map, keys);
283
284
for (int i = 0; i < keys.length; i++) {
285
T retVal = map.computeIfPresent(keys[i], mappingFunction);
286
if (i % 3 != 2) { // key present
287
if (funcResult == null) { // was removed
288
assertFalse(map.containsKey(keys[i]),
289
String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
290
} else { // value was replaced
291
assertTrue(map.containsKey(keys[i]),
292
String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
293
expectedSize1++;
294
}
295
assertEquals(retVal, funcResult,
296
String.format("computeIfPresent: retVal(%s[%s])", desc, i));
297
assertEquals(funcResult, map.get(keys[i]),
298
String.format("replaceIfMapped: get(%s[%d])", desc, i));
299
300
} else { // odd: was removed, should not be replaced
301
assertNull(retVal,
302
String.format("replaceIfMapped: retVal(%s[%d])", desc, i));
303
assertNull(map.get(keys[i]),
304
String.format("replaceIfMapped: get(%s[%d])", desc, i));
305
assertFalse(map.containsKey(keys[i]),
306
String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
307
}
308
assertFalse(map.containsValue(keys[i]),
309
String.format("replaceIfMapped: !containsValue(%s[%d])", desc, i));
310
}
311
assertEquals(map.size(), expectedSize1,
312
String.format("map expected size#1 m%d != k%d", map.size(), expectedSize1));
313
}
314
315
@Test(dataProvider = "mapsWithObjectsAndStrings")
316
void testComputeIfPresentNonNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
317
Map<Object, Object> map = ms.get();
318
Object[] keys = map.keySet().toArray();
319
testComputeIfPresent(map, desc, keys, (k, v) -> val);
320
}
321
322
@Test(dataProvider = "mapsWithObjectsAndStrings")
323
void testComputeIfPresentNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
324
Map<Object, Object> map = ms.get();
325
Object[] keys = map.keySet().toArray();
326
testComputeIfPresent(map, desc, keys, (k, v) -> null);
327
}
328
329
@Test(dataProvider = "hashMapsWithObjects")
330
void testComputeNonNull(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
331
// remove a third of the keys
332
// call compute() for all keys[]
333
// all keys should be present: removed keys -> EXTRA, others to k-1
334
Map<IntKey, IntKey> map = ms.get();
335
IntKey[] keys = map.keySet().stream().sorted().toArray(IntKey[]::new);
336
BiFunction<IntKey, IntKey, IntKey> mappingFunction = (k, v) -> {
337
if (v == null) {
338
return val;
339
} else {
340
return keys[k.getValue() - 1];
341
}
342
};
343
removeThirdKeys(map, keys);
344
for (int i = 1; i < keys.length; i++) {
345
IntKey retVal = map.compute(keys[i], mappingFunction);
346
if (i % 3 != 2) { // key present, should be mapped to k-1
347
assertEquals(retVal, keys[i - 1],
348
String.format("compute: retVal(%s[%d])", desc, i));
349
assertEquals(keys[i - 1], map.get(keys[i]),
350
String.format("compute: get(%s[%d])", desc, i));
351
} else { // odd: was removed, should be replaced with EXTRA
352
assertEquals(retVal, val,
353
String.format("compute: retVal(%s[%d])", desc, i));
354
assertEquals(val, map.get(keys[i]),
355
String.format("compute: get(%s[%d])", desc, i));
356
}
357
assertTrue(map.containsKey(keys[i]),
358
String.format("compute: containsKey(%s[%d])", desc, i));
359
}
360
assertEquals(map.size(), keys.length,
361
String.format("map expected size#1 m%d != k%d", map.size(), keys.length));
362
assertTrue(map.containsValue(val),
363
String.format("compute: containsValue(%s[%s])", desc, val));
364
assertFalse(map.containsValue(null),
365
String.format("compute: !containsValue(%s,[null])", desc));
366
}
367
368
@Test(dataProvider = "mapsWithObjectsAndStrings")
369
void testComputeNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
370
// remove a third of the keys
371
// call compute() for all keys[]
372
// removed keys should -> EXTRA
373
// for other keys: func returns null, should have no mapping
374
Map<Object, Object> map = ms.get();
375
Object[] keys = map.keySet().toArray();
376
BiFunction<Object, Object, Object> mappingFunction = (k, v) -> {
377
// if absent/null -> EXTRA
378
// if present -> null
379
if (v == null) {
380
return val;
381
} else {
382
return null;
383
}
384
};
385
int expectedSize = 0;
386
removeThirdKeys(map, keys);
387
for (int i = 0; i < keys.length; i++) {
388
Object retVal = map.compute(keys[i], mappingFunction);
389
if (i % 3 != 2) { // key present, func returned null, should be absent from map
390
assertNull(retVal,
391
String.format("compute: retVal(%s[%d])", desc, i));
392
assertNull(map.get(keys[i]),
393
String.format("compute: get(%s[%d])", desc, i));
394
assertFalse(map.containsKey(keys[i]),
395
String.format("compute: containsKey(%s[%d])", desc, i));
396
assertFalse(map.containsValue(keys[i]),
397
String.format("compute: containsValue(%s[%s])", desc, i));
398
} else { // odd: was removed, should now be mapped to EXTRA
399
assertEquals(retVal, val,
400
String.format("compute: retVal(%s[%d])", desc, i));
401
assertEquals(val, map.get(keys[i]),
402
String.format("compute: get(%s[%d])", desc, i));
403
assertTrue(map.containsKey(keys[i]),
404
String.format("compute: containsKey(%s[%d])", desc, i));
405
expectedSize++;
406
}
407
}
408
assertTrue(map.containsValue(val),
409
String.format("compute: containsValue(%s[%s])", desc, val));
410
assertEquals(map.size(), expectedSize,
411
String.format("map expected size#1 m%d != k%d", map.size(), expectedSize));
412
}
413
414
@Test(dataProvider = "hashMapsWithObjects")
415
void testMergeNonNull(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
416
// remove a third of the keys
417
// call merge() for all keys[]
418
// all keys should be present: removed keys now -> EXTRA, other keys -> k-1
419
Map<IntKey, IntKey> map = ms.get();
420
IntKey[] keys = map.keySet().stream().sorted().toArray(IntKey[]::new);
421
422
// Map to preceding key
423
BiFunction<IntKey, IntKey, IntKey> mappingFunction
424
= (k, v) -> keys[k.getValue() - 1];
425
removeThirdKeys(map, keys);
426
for (int i = 1; i < keys.length; i++) {
427
IntKey retVal = map.merge(keys[i], val, mappingFunction);
428
if (i % 3 != 2) { // key present, should be mapped to k-1
429
assertEquals(retVal, keys[i - 1],
430
String.format("compute: retVal(%s[%d])", desc, i));
431
assertEquals(keys[i - 1], map.get(keys[i]),
432
String.format("compute: get(%s[%d])", desc, i));
433
} else { // odd: was removed, should be replaced with EXTRA
434
assertEquals(retVal, val,
435
String.format("compute: retVal(%s[%d])", desc, i));
436
assertEquals(val, map.get(keys[i]),
437
String.format("compute: get(%s[%d])", desc, i));
438
}
439
assertTrue(map.containsKey(keys[i]),
440
String.format("compute: containsKey(%s[%d])", desc, i));
441
}
442
443
assertEquals(map.size(), keys.length,
444
String.format("map expected size#1 m%d != k%d", map.size(), keys.length));
445
assertTrue(map.containsValue(val),
446
String.format("compute: containsValue(%s[%s])", desc, val));
447
assertFalse(map.containsValue(null),
448
String.format("compute: !containsValue(%s,[null])", desc));
449
}
450
451
@Test(dataProvider = "mapsWithObjectsAndStrings")
452
void testMergeNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
453
// remove a third of the keys
454
// call merge() for all keys[]
455
// result: removed keys -> EXTRA, other keys absent
456
457
Map<Object, Object> map = ms.get();
458
Object[] keys = map.keySet().toArray();
459
BiFunction<Object, Object, Object> mappingFunction = (k, v) -> null;
460
int expectedSize = 0;
461
removeThirdKeys(map, keys);
462
for (int i = 0; i < keys.length; i++) {
463
Object retVal = map.merge(keys[i], val, mappingFunction);
464
if (i % 3 != 2) { // key present, func returned null, should be absent from map
465
assertNull(retVal,
466
String.format("compute: retVal(%s[%d])", desc, i));
467
assertNull(map.get(keys[i]),
468
String.format("compute: get(%s[%d])", desc, i));
469
assertFalse(map.containsKey(keys[i]),
470
String.format("compute: containsKey(%s[%d])", desc, i));
471
} else { // odd: was removed, should now be mapped to EXTRA
472
assertEquals(retVal, val,
473
String.format("compute: retVal(%s[%d])", desc, i));
474
assertEquals(val, map.get(keys[i]),
475
String.format("compute: get(%s[%d])", desc, i));
476
assertTrue(map.containsKey(keys[i]),
477
String.format("compute: containsKey(%s[%d])", desc, i));
478
expectedSize++;
479
}
480
assertFalse(map.containsValue(keys[i]),
481
String.format("compute: containsValue(%s[%s])", desc, i));
482
}
483
assertTrue(map.containsValue(val),
484
String.format("compute: containsValue(%s[%s])", desc, val));
485
assertEquals(map.size(), expectedSize,
486
String.format("map expected size#1 m%d != k%d", map.size(), expectedSize));
487
}
488
489
/*
490
* Remove half of the keys
491
*/
492
private static <T> void removeOddKeys(Map<T, T> map, /*String keys_desc, */ T[] keys) {
493
int removes = 0;
494
for (int i = 0; i < keys.length; i++) {
495
if (i % 2 != 0) {
496
map.remove(keys[i]);
497
removes++;
498
}
499
}
500
assertEquals(map.size(), keys.length - removes,
501
String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
502
}
503
504
/*
505
* Remove every third key
506
* This will hopefully leave some removed keys in TreeBins for, e.g., computeIfAbsent
507
* w/ a func that returns null.
508
*
509
* TODO: consider using this in other tests (and maybe adding a remapThirdKeys)
510
*/
511
private static <T> void removeThirdKeys(Map<T, T> map, /*String keys_desc, */ T[] keys) {
512
int removes = 0;
513
for (int i = 0; i < keys.length; i++) {
514
if (i % 3 == 2) {
515
map.remove(keys[i]);
516
removes++;
517
}
518
}
519
assertEquals(map.size(), keys.length - removes,
520
String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
521
}
522
523
/*
524
* Re-map the odd-numbered keys to map to the EXTRA value
525
*/
526
private static <T> void remapOddKeys(Map<T, T> map, T[] keys, T val) {
527
for (int i = 0; i < keys.length; i++) {
528
if (i % 2 != 0) {
529
map.put(keys[i], val);
530
}
531
}
532
}
533
534
@DataProvider
535
public Iterator<Object[]> nullValueFriendlyMaps() {
536
return Arrays.asList(
537
new Object[]{"HashMap", (Supplier<Map<?, ?>>) HashMap::new},
538
new Object[]{"LinkedHashMap", (Supplier<Map<?, ?>>) LinkedHashMap::new},
539
new Object[]{"TreeMap", (Supplier<Map<?, ?>>) TreeMap::new},
540
new Object[]{"TreeMap(cmp)", (Supplier<Map<?, ?>>) () -> new TreeMap<>(Comparator.reverseOrder())},
541
new Object[]{"TreeMap.descendingMap", (Supplier<Map<?, ?>>) () -> new TreeMap<>().descendingMap()}
542
).iterator();
543
}
544
}
545
546