Skip to content

Commit 4e749b6

Browse files
committed
Both versions of removeAll fuller documented; varargs version fully implemented and tested. Collections version implementation remains skeletal, tests unwritten.
1 parent d37e9a0 commit 4e749b6

File tree

2 files changed

+125
-20
lines changed

2 files changed

+125
-20
lines changed

src/net/danielhildebrandt/JArray.java

+59-20
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package net.danielhildebrandt;
22

3-
import java.util.ArrayList;
43
import java.util.Arrays;
54
import java.util.Collection;
65
import java.util.Comparator;
76
import java.util.HashSet;
87
import java.util.Iterator;
9-
import java.util.List;
108
import java.util.Set;
119

1210
/**
@@ -381,15 +379,38 @@ public static final <E> E removeLast(E[] arr, E emptyElem, E removed)
381379
}
382380

383381
/**
382+
* Removes all instances of each listed item from the array. Returns an array
383+
* of all elements successfully removed - this will be a subset of
384+
* {@code removed}, in no particular order.
385+
* <p>
386+
* If the array of elements to be removed is empty, this method will return an
387+
* empty array, having removed nothing and throwing no exceptions. If any of
388+
* the elements of the removal array are the empty element, this method will
389+
* behave as though they weren't there. Inlcusion of the same element many
390+
* times will have no additional effect. The "empty element" is the element
391+
* used in the array to represent an empty spot - this is often simply
392+
* {@code null}, but can also be a pseudo-empty element if {@code null} is to
393+
* be considered a valid element.
394+
* <p>
395+
* This method ensures that the array is complete both before and after its
396+
* execution. Completeness is defined by the array in question having all
397+
* instances of the empty element placed only at its trailing end. Refer also
398+
* to {@link #isComplete(Object[], Object) isComplete}.
384399
*
400+
* @param arr the array from which to remove zero or more elements
401+
* @param emptyElem the element representing "nothing" in the array
402+
* @param removed an array of elements to remove
403+
* @return an array of the elements successfully removed (a subset of
404+
* {@code removed})
405+
* @throws IllegalArgumentException if the array to remove from is null
406+
* @throws IncompleteArrayException if the array to remove from is incomplete
407+
* @throws NullPointerException if the array from which to remove or the array
408+
* of element to take out is a null reference
385409
*
386-
* @param arr
387-
* @param emptyElem
388-
* @param removed
389-
* @return
410+
* @see #isComplete(Object[], Object)
390411
*/
391412
@SafeVarargs
392-
public static final <E> E[] removeAll(E[] arr, E emptyElem, E... removed)
413+
public static final <E> Object[] removeAll(E[] arr, E emptyElem, E... removed)
393414
{
394415
if(arr == null)
395416
throw new NullPointerException("The array removed from cannot be a null reference.");
@@ -403,37 +424,56 @@ else if(!isComplete(arr, emptyElem))
403424
throw new IncompleteArrayException(arr, emptyElem);
404425
else {
405426
Set<E> removalSet = new HashSet<E>(Arrays.asList(removed));
427+
Set<E> removedElemSet = new HashSet<E>();
406428

407-
// For each element set to be removed (except empty)...
408429
for(E elem: removalSet) {
409-
if(!elem.equals(emptyElem)) {
410-
// Write over each instance of elem, dragging over subsequent elements
430+
if(((elem != null) ? (!elem.equals(emptyElem)) : (elem != emptyElem)) && !removedElemSet.contains(elem)) {
411431
for(int i = 0; i < arr.length; ++i) {
412-
if((emptyElem == null && arr[i] == emptyElem) || (emptyElem != null && arr[i].equals(emptyElem)))
432+
if((emptyElem == null) ? (arr[i] == emptyElem) : (arr[i].equals(emptyElem)))
413433
break;
414-
else if((elem != null && arr[i].equals(elem)) || (elem == null && arr[i] == elem)) {
434+
else if((elem != null) ? (arr[i].equals(elem)) : (arr[i] == elem)) {
415435
for(int j = i; j < arr.length - 1; ++j)
416436
arr[j] = arr[j + 1];
417437
arr[arr.length - 1] = emptyElem;
438+
removedElemSet.add(elem);
418439
--i;
419440
}
420441
}
421442
}
422443
}
423444

424-
return null;
445+
return removedElemSet.toArray();
425446
}
426447
}
427448

428449
/**
450+
* Removes all instances of each listed item from the array. Returns a
451+
* collection of all elements successfully removed - this will be a subset of
452+
* {@code removed}, in no particular order.
453+
* <p>
454+
* If the collection of elements to be removed is empty, this method will
455+
* return an empty collection, having removed nothing and throwing no
456+
* exceptions. If any of the elements of the removal collection are the empty
457+
* element, this method will behave as though they weren't there. Inlcusion of
458+
* the same element many times will have no additional effect. The "empty
459+
* element" is the element used in the array to represent an empty spot - this
460+
* is often simply {@code null}, but can also be a pseudo-empty element if
461+
* {@code null} is to be considered a valid element.
462+
* <p>
463+
* This method ensures that the array is complete both before and after its
464+
* execution. Completeness is defined by the array in question having all
465+
* instances of the empty element placed only at its trailing end. Refer also
466+
* to {@link #isComplete(Object[], Object) isComplete}.
429467
*
468+
* @param arr arr the array from which to remove zero or more elements
469+
* @param emptyElem the element representing "nothing" in the array
470+
* @param removed a collection of elements to remove
471+
* @return a {@code Collection} of the elements successfully removed (a subset
472+
* of {@code removed})
430473
*
431-
* @param arr
432-
* @param emptyElem
433-
* @param removed
434-
* @return
474+
* @see #isComplete(Object[], Object)
435475
*/
436-
public static final <E> List<E> removeAll(E[] arr, E emptyElem, Collection<? extends E> removed)
476+
public static final <E> Collection<E> removeAll(E[] arr, E emptyElem, Collection<? extends E> removed)
437477
{
438478
if(arr == null)
439479
throw new NullPointerException("The array removed from cannot be a null reference.");
@@ -442,11 +482,10 @@ else if(removed == null)
442482
else if(arr.length == 0)
443483
throw new IllegalArgumentException("The array removed from must be non-empty.");
444484
else if(removed.size() == 0)
445-
return new ArrayList<E>(0);
485+
return new HashSet<E>();
446486
else if(!isComplete(arr, emptyElem))
447487
throw new IncompleteArrayException(arr, emptyElem);
448488
else {
449-
// Set<E> removalSet = new HashSet<E>(removed);
450489
return null;
451490
}
452491
}

test/net/danielhildebrandt/test/JArrayTest.java

+66
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,72 @@ public final void removeAll_Varargs_NonNullEmptyElement()
681681
removeAll(before, "", "Saruman the White", "Minas Morgul");
682682
assertThat(before, is(equalTo(after)));
683683
}
684+
685+
@Test
686+
public final void removeAll_Varargs_RemoveIncludesEmptyElement()
687+
{
688+
String[] before = {"Eru Illúvatar", "Valar", "Melkor", "Arda", ""};
689+
String[] after = {"Eru Illúvatar", "Valar", "Arda", "", ""};
690+
691+
removeAll(before, "", "Melkor", "");
692+
assertThat(before, is(equalTo(after)));
693+
}
694+
695+
@Test
696+
public final void removeAll_Varargs_RemovalDuplicates()
697+
{
698+
Object[] before = {"Weathertop", "Sarn Gebir", "Bree", "Weathertop", "Sarn Gebir"};
699+
Object[] after = {"Sarn Gebir", "Bree", "Sarn Gebir", null, null};
700+
701+
removeAll(before, null, "Weathertop", "Weathertop", "Weathertop");
702+
assertThat(before, is(equalTo(after)));
703+
}
704+
705+
@Test
706+
public final void removeAll_Varargs_RemoveNonExistent()
707+
{
708+
String[] before = {"Orthanc", "Osgiliath", "Dol Amroth", "Minas Tirith", ""};
709+
String[] after = {"Orthanc", "Osgiliath", "Dol Amroth", "Minas Tirith", ""};
710+
711+
removeAll(before, "", "Near Harad", "Far Harad");
712+
assertThat(before, is(equalTo(after)));
713+
}
714+
715+
@Test
716+
public final void removeAll_Varargs_ReturnValue()
717+
{
718+
String[] arr = {"Music of the Ainur", "Plateau of Gorgoroth", "Utumno", "Dol Guldur", null, null, null};
719+
Object[] removed = removeAll(arr, null, "Utumno", "Angband", null);
720+
assertThat(removed, is(equalTo(new Object[] {"Utumno"})));
721+
}
722+
723+
@Test(expected = NullPointerException.class)
724+
public final void removeAll_Varargs_NullRemovalArray()
725+
{
726+
Object[] arr = null;
727+
removeAll(arr, "", "Balrog");
728+
}
729+
730+
@Test(expected = NullPointerException.class)
731+
public final void removeAll_Varargs_NullRemovedArray()
732+
{
733+
String[] arr = null;
734+
removeAll(arr, null, "Sauron");
735+
}
736+
737+
@Test(expected = IllegalArgumentException.class)
738+
public final void removeAll_Varargs_EmptyRemovalArray()
739+
{
740+
String[] arr = {};
741+
removeAll(arr, null, "Tom Bombadil");
742+
}
743+
744+
@Test(expected = IncompleteArrayException.class)
745+
public final void removeAll_Varargs_IncompletelArray()
746+
{
747+
String[] arr = {"Moria", "", "Isengard", "Fangorn", "Aragorn", "", ""};
748+
removeAll(arr, "", "Moria");
749+
}
684750
}
685751

686752
public static final class IsCompleteTest

0 commit comments

Comments
 (0)