@@ -350,82 +350,64 @@ public UnmodifiableArrayBackedMap copyAndRemove(String key) {
350
350
}
351
351
352
352
/**
353
- * Creates a new instance that contains the same entries as this map, minus all
354
- * of the keys passed in the arguments.
355
- *
356
- * @param key
357
- * @param value
358
- * @return
353
+ * Creates a new instance where the entries of provided keys are removed.
359
354
*/
360
355
public UnmodifiableArrayBackedMap copyAndRemoveAll (Iterable <String > keysToRemoveIterable ) {
356
+
357
+ // Short-circuit if the map is empty
361
358
if (isEmpty ()) {
362
- // shortcut: if this map is empty, the result will continue to be empty
363
359
return EMPTY_MAP ;
364
360
}
365
361
366
- // now we build a Set of keys to remove
367
- Set <String > keysToRemoveSet ;
362
+ // Collect distinct keys to remove
363
+ final Set <String > keysToRemove ;
368
364
if (keysToRemoveIterable instanceof Set ) {
369
- // we already have a set, let's cast it and reuse it
370
- keysToRemoveSet = (Set <String >) keysToRemoveIterable ;
365
+ keysToRemove = (Set <String >) keysToRemoveIterable ;
371
366
} else {
372
- // iterate through the keys and build a set
373
- keysToRemoveSet = new HashSet <>();
374
- for (String key : keysToRemoveIterable ) {
375
- keysToRemoveSet .add (key );
367
+ keysToRemove = new HashSet <>();
368
+ for (final String key : keysToRemoveIterable ) {
369
+ keysToRemove .add (key );
376
370
}
377
371
}
378
372
379
- int firstIndexToKeep = -1 ;
380
- int lastIndexToKeep = -1 ;
381
- int destinationIndex = 0 ;
382
- int numEntriesKept = 0 ;
383
- // build the new map
384
- UnmodifiableArrayBackedMap newMap = new UnmodifiableArrayBackedMap (numEntries );
385
- for (int indexInCurrentMap = 0 ; indexInCurrentMap < numEntries ; indexInCurrentMap ++) {
386
- // for each key in this map, check whether it's in the set we built above
387
- Object key = backingArray [getArrayIndexForKey (indexInCurrentMap )];
388
- if (!keysToRemoveSet .contains (key )) {
389
- // this key should be kept
390
- if (firstIndexToKeep == -1 ) {
391
- firstIndexToKeep = indexInCurrentMap ;
392
- }
393
- lastIndexToKeep = indexInCurrentMap ;
394
- } else if (lastIndexToKeep > 0 ) {
395
- // we hit a remove, copy any keys that are known ready
396
- int numEntriesToCopy = lastIndexToKeep - firstIndexToKeep + 1 ;
397
- System .arraycopy (
398
- backingArray ,
399
- getArrayIndexForKey (firstIndexToKeep ),
400
- newMap .backingArray ,
401
- getArrayIndexForKey (destinationIndex ),
402
- numEntriesToCopy * 2 );
403
- firstIndexToKeep = -1 ;
404
- lastIndexToKeep = -1 ;
405
- destinationIndex += numEntriesToCopy ;
406
- numEntriesKept += numEntriesToCopy ;
407
- }
408
- }
373
+ // Create the new map
374
+ final UnmodifiableArrayBackedMap oldMap = this ;
375
+ final int oldMapEntryCount = oldMap .numEntries ;
376
+ final UnmodifiableArrayBackedMap newMap = new UnmodifiableArrayBackedMap (oldMapEntryCount );
409
377
410
- if (lastIndexToKeep > -1 ) {
411
- // at least one key still requires copying
412
- int numEntriesToCopy = lastIndexToKeep - firstIndexToKeep + 1 ;
413
- System .arraycopy (
414
- backingArray ,
415
- getArrayIndexForKey (firstIndexToKeep ),
416
- newMap .backingArray ,
417
- getArrayIndexForKey (destinationIndex ),
418
- numEntriesToCopy * 2 );
419
- numEntriesKept += numEntriesToCopy ;
378
+ // Short-circuit if there is nothing to remove
379
+ if (keysToRemove .isEmpty ()) {
380
+ System .arraycopy (oldMap .backingArray , 0 , newMap .backingArray , 0 , oldMapEntryCount * 2 );
381
+ newMap .numEntries = oldMapEntryCount ;
382
+ return this ;
420
383
}
421
384
422
- if (numEntriesKept == 0 ) {
423
- return EMPTY_MAP ;
385
+ // Iterate over old map entries
386
+ int newMapEntryIndex = 0 ;
387
+ for (int oldMapEntryIndex = 0 ; oldMapEntryIndex < oldMapEntryCount ; oldMapEntryIndex ++) {
388
+ final int oldMapKeyIndex = getArrayIndexForKey (oldMapEntryIndex );
389
+ final Object key = oldMap .backingArray [oldMapKeyIndex ];
390
+
391
+ // Skip entries of removed keys
392
+ @ SuppressWarnings ("SuspiciousMethodCalls" )
393
+ final boolean removed = keysToRemove .contains (key );
394
+ if (removed ) {
395
+ continue ;
396
+ }
397
+
398
+ // Copy the entry
399
+ final int oldMapValueIndex = getArrayIndexForValue (oldMapEntryIndex );
400
+ final Object value = oldMap .backingArray [oldMapValueIndex ];
401
+ final int newMapKeyIndex = getArrayIndexForKey (newMapEntryIndex );
402
+ final int newMapValueIndex = getArrayIndexForValue (newMapEntryIndex );
403
+ newMap .backingArray [newMapKeyIndex ] = key ;
404
+ newMap .backingArray [newMapValueIndex ] = value ;
405
+ newMapEntryIndex ++;
424
406
}
425
407
426
- newMap .numEntries = numEntriesKept ;
408
+ // Cap and return the new map
409
+ newMap .numEntries = newMapEntryIndex ;
427
410
newMap .updateNumEntriesInArray ();
428
-
429
411
return newMap ;
430
412
}
431
413
0 commit comments