From 88e0179dd5b446bcc758f67504c3db981bc6c116 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 10 Nov 2017 10:35:51 +0100 Subject: [PATCH] add method removeIf --- .../java/org/lucares/collections/IntList.java | 25 ++++++--- .../org/lucares/collections/IntPredicate.java | 56 +++++++++++++++++++ .../org/lucares/collections/IntListTest.java | 45 +++++++++++++++ 3 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 primitiveCollections/src/main/java/org/lucares/collections/IntPredicate.java diff --git a/primitiveCollections/src/main/java/org/lucares/collections/IntList.java b/primitiveCollections/src/main/java/org/lucares/collections/IntList.java index 7fa8374..02d7f82 100644 --- a/primitiveCollections/src/main/java/org/lucares/collections/IntList.java +++ b/primitiveCollections/src/main/java/org/lucares/collections/IntList.java @@ -18,12 +18,7 @@ public final class IntList implements Serializable, Cloneable { // TODO support Iterator // TODO add mod counts // TODO support sublists - // TODO add retainAll - // TODO add removeAll - // TODO add retainAll for sorted lists - // TODO add removeAll for sorted lists - // TODO add removeIf - // TODO add replace + // TODO add remember if list is sorted so we can use binary search in indexOf // TODO add lastIndexOf // TODO remove bounds checks that are handled by java, e.g. negative indices @@ -155,7 +150,7 @@ public final class IntList implements Serializable, Cloneable { throw new IndexOutOfBoundsException("pos must not be negative, but was: " + pos); } if (pos > index) { - throw new IndexOutOfBoundsException("pos must not smaller than size(), but was: " + pos); + throw new IndexOutOfBoundsException("pos must be smaller than size(), but was: " + pos); } if (values == null) { throw new NullPointerException("values parameter must not be null"); @@ -261,6 +256,22 @@ public final class IntList implements Serializable, Cloneable { index = insertPosition; } + public void removeIf(final IntPredicate predicate) { + + final int size = index; + int insertPosition = 0; + for (int i = 0; i < size; i++) { + final int current = data[i]; + if (!predicate.test(current)) { + // keep current element + data[insertPosition] = current; + insertPosition++; + } + } + index = insertPosition; + + } + /** * Retains all elements contained in the specified list. * diff --git a/primitiveCollections/src/main/java/org/lucares/collections/IntPredicate.java b/primitiveCollections/src/main/java/org/lucares/collections/IntPredicate.java new file mode 100644 index 0000000..79d7d48 --- /dev/null +++ b/primitiveCollections/src/main/java/org/lucares/collections/IntPredicate.java @@ -0,0 +1,56 @@ +package org.lucares.collections; + +import java.util.function.Predicate; + +/** + * A {@link Predicate} for primitive integers. + */ +@FunctionalInterface +public interface IntPredicate { + + /** + * Evaluates the predicate. + * + * @param i + * the input argument + * @return {@code true} iff the input argument matches the predicate + */ + boolean test(int i); + + /** + * Returns a predicate that represents the logical AND of {@code this} and + * another predicate. The and operation is short-circuiting. + * + * @param other + * the other predicate + * @return the result of combining both predicates with a logical AND operation + * @throws NullPointerException + * if {@code other} is null + */ + default IntPredicate and(final IntPredicate other) { + return (t) -> test(t) && other.test(t); + } + + /** + * Returns a predicate that represents the logical OR of {@code this} and + * another predicate. The and operation is short-circuiting. + * + * @param other + * the other predicate + * @return the result of combining both predicates with a logical OR operation + * @throws NullPointerException + * if {@code other} is null + */ + default IntPredicate or(final IntPredicate other) { + return (t) -> test(t) || other.test(t); + } + + /** + * Returns a predicate that negates the result of this predicate. + * + * @return the negation of {@code this} + */ + default IntPredicate negate() { + return (t) -> !test(t); + } +} diff --git a/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java b/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java index 16e587c..69fd03e 100644 --- a/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java +++ b/primitiveCollections/src/test/java/org/lucares/collections/IntListTest.java @@ -692,4 +692,49 @@ public class IntListTest { Assert.assertArrayEquals(new int[] {}, list.toArray()); Assert.assertArrayEquals(new int[] {}, retain.toArray()); } + + @Test + public void testRemoveIf() { + final IntList list = IntList.of(1, 2, 3, 4, 5, 6); + + list.removeIf(i -> i % 2 == 0); + Assert.assertArrayEquals(new int[] { 1, 3, 5 }, list.toArray()); + } + + @Test + public void testRemoveIfNegationOfPredicate() { + final IntList list = IntList.of(1, 2, 3, 4, 5, 6); + + final IntPredicate predicate = i -> i % 2 == 0; + list.removeIf(predicate.negate()); + Assert.assertArrayEquals(new int[] { 2, 4, 6 }, list.toArray()); + } + + @Test + public void testRemoveIfWithAndCombinedPredicates() { + final IntList list = IntList.of(1, 2, 3, 4, 5, 6); + + final IntPredicate predicateA = i -> i % 2 == 0; + final IntPredicate predicateB = i -> i == 3 || i == 4; + list.removeIf(predicateA.and(predicateB)); + Assert.assertArrayEquals(new int[] { 1, 2, 3, 5, 6 }, list.toArray()); + } + + @Test + public void testRemoveIfWithOrCombinedPredicates() { + final IntList list = IntList.of(1, 2, 3, 4, 5, 6); + + final IntPredicate predicateA = i -> i % 2 == 0; + final IntPredicate predicateB = i -> i == 3 || i == 4; + list.removeIf(predicateA.or(predicateB)); + Assert.assertArrayEquals(new int[] { 1, 5 }, list.toArray()); + } + + @Test + public void testRemoveIfOnEmptyList() { + final IntList list = IntList.of(); + + list.removeIf(i -> false); + Assert.assertArrayEquals(new int[] {}, list.toArray()); + } }