New Tests & Fixes

- Added: Tests for the new Stream replace functions to ensure no bugs
are left.
- Fixed: Custom HashSet reduce function with a default value was
checking incorrectly for present keys.
This commit is contained in:
Speiger 2021-12-10 03:23:28 +01:00
parent c4964806f0
commit c6afdb8762
8 changed files with 147 additions and 23 deletions

View File

@ -10,6 +10,8 @@
- Added: Unmodifiable and Synchronized Wrapper Collections can now be cloned. They clone the underlying map which doesn't break functionality. (Had a usecase for it) - Added: Unmodifiable and Synchronized Wrapper Collections can now be cloned. They clone the underlying map which doesn't break functionality. (Had a usecase for it)
- Added: A boxed putAll array variant. - Added: A boxed putAll array variant.
- Fixed: EnumMaps didn't keep track of their size and now got proper care and implementations as needed. There might be more work required but at least the core functionality is now up to date. - Fixed: EnumMaps didn't keep track of their size and now got proper care and implementations as needed. There might be more work required but at least the core functionality is now up to date.
- Added: Tests for the new Stream replace functions to ensure no bugs are left.
- Fixed: Custom HashSet reduce function with a default value was checking incorrectly for present keys.
### Version 0.4.5 ### Version 0.4.5
- Added: removeAll/retainAll(Collection c, Consumer r) which receives all the elements that got deleted from the collection - Added: removeAll/retainAll(Collection c, Consumer r) which receives all the elements that got deleted from the collection

View File

@ -18,7 +18,7 @@ repositories {
} }
archivesBaseName = 'Primitive Collections' archivesBaseName = 'Primitive Collections'
version = '0.4.5'; version = '0.4.6';
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'

View File

@ -1023,7 +1023,12 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
public <E> E[] toArray(E[] a) { public <E> E[] toArray(E[] a) {
if(a == null) a = (E[])new Object[size]; if(a == null) a = (E[])new Object[size];
else if(a.length < size) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size); else if(a.length < size) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size);
#if TYPE_OBJECT
System.arraycopy(data, 0, a, 0, size); System.arraycopy(data, 0, a, 0, size);
#else
for(int i = 0;i<size;i++)
a[i] = (E)KEY_TO_OBJ(data[i]);
#endif
return a; return a;
} }

View File

@ -160,6 +160,7 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
* @throws IllegalStateException if the keys and values do not match in lenght * @throws IllegalStateException if the keys and values do not match in lenght
*/ */
public ARRAY_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, int length) { public ARRAY_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, int length) {
this(length);
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size"); if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
putAll(keys, values, 0, length); putAll(keys, values, 0, length);
} }

View File

@ -570,7 +570,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
/** /**
* Starts a Map Builder that allows you to create maps as Constants a lot easier * Starts a Map Builder that allows you to create maps as Constants a lot easier
* Keys & Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen * Keys and Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen
* @Type(T) * @Type(T)
* @ValueType(V) * @ValueType(V)
* @return a MapBuilder * @return a MapBuilder
@ -581,7 +581,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
/** /**
* Starts a Map Builder that allows you to create maps as Constants a lot easier * Starts a Map Builder that allows you to create maps as Constants a lot easier
* Keys & Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen * Keys and Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen
* @param size the expected minimum size of Elements in the Map, default is 16 * @param size the expected minimum size of Elements in the Map, default is 16
* @Type(T) * @Type(T)
* @ValueType(V) * @ValueType(V)
@ -592,13 +592,13 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Starts a Map builder and puts in the Key & Value into it * Starts a Map builder and puts in the Key and Value into it
* Keys & Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen * Keys and Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen
* @param key the key that should be added * @param key the key that should be added
* @param value the value that should be added * @param value the value that should be added
* @Type(T) * @Type(T)
* @ValueType(V) * @ValueType(V)
* @return a MapBuilder with the key & value stored in it. * @return a MapBuilder with the key and value stored in it.
*/ */
public GENERIC_KEY_VALUE_BRACES BuilderCache KEY_VALUE_GENERIC_TYPE put(KEY_TYPE key, VALUE_TYPE value) { public GENERIC_KEY_VALUE_BRACES BuilderCache KEY_VALUE_GENERIC_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
return new BuilderCache KEY_VALUE_GENERIC_TYPE().put(key, value); return new BuilderCache KEY_VALUE_GENERIC_TYPE().put(key, value);
@ -606,13 +606,13 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
#if !TYPE_OBJECT || !VALUE_OBJECT #if !TYPE_OBJECT || !VALUE_OBJECT
/** /**
* Starts a Map builder and puts in the Key & Value into it * Starts a Map builder and puts in the Key and Value into it
* Keys & Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen * Keys and Values are stored as Array and then inserted using the putAllMethod when the mapType is choosen
* @param key the key that should be added * @param key the key that should be added
* @param value the value that should be added * @param value the value that should be added
* @Type(T) * @Type(T)
* @ValueType(V) * @ValueType(V)
* @return a MapBuilder with the key & value stored in it. * @return a MapBuilder with the key and value stored in it.
*/ */
public GENERIC_KEY_VALUE_BRACES BuilderCache KEY_VALUE_GENERIC_TYPE put(CLASS_TYPE key, CLASS_VALUE_TYPE value) { public GENERIC_KEY_VALUE_BRACES BuilderCache KEY_VALUE_GENERIC_TYPE put(CLASS_TYPE key, CLASS_VALUE_TYPE value) {
return new BuilderCache KEY_VALUE_GENERIC_TYPE().put(key, value); return new BuilderCache KEY_VALUE_GENERIC_TYPE().put(key, value);
@ -1449,7 +1449,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a Hash Map * Builds the Keys and Values into a Hash Map
* @return a HASH_MAP * @return a HASH_MAP
*/ */
public HASH_MAP KEY_VALUE_GENERIC_TYPE map() { public HASH_MAP KEY_VALUE_GENERIC_TYPE map() {
@ -1457,7 +1457,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a Linked Hash Map * Builds the Keys and Values into a Linked Hash Map
* @return a LINKED_HASH_MAP * @return a LINKED_HASH_MAP
*/ */
public LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE linkedMap() { public LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE linkedMap() {
@ -1465,7 +1465,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a Immutable Hash Map * Builds the Keys and Values into a Immutable Hash Map
* @return a IMMUTABLE_HASH_MAP * @return a IMMUTABLE_HASH_MAP
*/ */
public IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE immutable() { public IMMUTABLE_HASH_MAP KEY_VALUE_GENERIC_TYPE immutable() {
@ -1473,8 +1473,8 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a Custom Hash Map * Builds the Keys and Values into a Custom Hash Map
* @param strategy the that controls the keys & values * @param strategy the that controls the keys and values
* @return a CUSTOM_HASH_MAP * @return a CUSTOM_HASH_MAP
*/ */
public CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE customMap(STRATEGY KEY_GENERIC_TYPE strategy) { public CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE customMap(STRATEGY KEY_GENERIC_TYPE strategy) {
@ -1482,8 +1482,8 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a Linked Custom Hash Map * Builds the Keys and Values into a Linked Custom Hash Map
* @param strategy the that controls the keys & values * @param strategy the that controls the keys and values
* @return a LINKED_CUSTOM_HASH_MAP * @return a LINKED_CUSTOM_HASH_MAP
*/ */
public LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE customLinkedMap(STRATEGY KEY_GENERIC_TYPE strategy) { public LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE customLinkedMap(STRATEGY KEY_GENERIC_TYPE strategy) {
@ -1491,7 +1491,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a Array Map * Builds the Keys and Values into a Array Map
* @return a ARRAY_MAP * @return a ARRAY_MAP
*/ */
public ARRAY_MAP KEY_VALUE_GENERIC_TYPE arrayMap() { public ARRAY_MAP KEY_VALUE_GENERIC_TYPE arrayMap() {
@ -1499,7 +1499,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a RedBlack TreeMap * Builds the Keys and Values into a RedBlack TreeMap
* @return a RB_TREE_MAP * @return a RB_TREE_MAP
*/ */
public RB_TREE_MAP KEY_VALUE_GENERIC_TYPE rbTreeMap() { public RB_TREE_MAP KEY_VALUE_GENERIC_TYPE rbTreeMap() {
@ -1507,7 +1507,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a RedBlack TreeMap * Builds the Keys and Values into a RedBlack TreeMap
* @param comp the Comparator that sorts the Tree * @param comp the Comparator that sorts the Tree
* @return a RB_TREE_MAP * @return a RB_TREE_MAP
*/ */
@ -1516,7 +1516,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a AVL TreeMap * Builds the Keys and Values into a AVL TreeMap
* @return a AVL_TREE_MAP * @return a AVL_TREE_MAP
*/ */
public AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE avlTreeMap() { public AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE avlTreeMap() {
@ -1524,7 +1524,7 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
} }
/** /**
* Builds the Keys & Values into a AVL TreeMap * Builds the Keys and Values into a AVL TreeMap
* @param comp the Comparator that sorts the Tree * @param comp the Comparator that sorts the Tree
* @return a AVL_TREE_MAP * @return a AVL_TREE_MAP
*/ */

View File

@ -536,7 +536,7 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T
KEY_TYPE state = identity; KEY_TYPE state = identity;
if(containsNull) state = operator.APPLY_VALUE(state, keys[nullIndex]); if(containsNull) state = operator.APPLY_VALUE(state, keys[nullIndex]);
for(int i = nullIndex-1;i>=0;i--) { for(int i = nullIndex-1;i>=0;i--) {
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) continue; if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) continue;
state = operator.APPLY_VALUE(state, keys[i]); state = operator.APPLY_VALUE(state, keys[i]);
} }
return state; return state;

View File

@ -1,5 +1,6 @@
package speiger.src.collections.ints.base; package speiger.src.collections.ints.base;
import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@ -8,6 +9,11 @@ import org.junit.Test;
import speiger.src.collections.ints.collections.IntIterable; import speiger.src.collections.ints.collections.IntIterable;
import speiger.src.collections.ints.collections.IntIterator; import speiger.src.collections.ints.collections.IntIterator;
import speiger.src.collections.ints.lists.IntArrayList;
import speiger.src.collections.ints.utils.IntArrays;
import speiger.src.collections.ints.utils.IntIterators;
import speiger.src.collections.objects.utils.ObjectArrays;
import speiger.src.collections.objects.utils.ObjectIterators;
import speiger.src.collections.tests.IterableTest; import speiger.src.collections.tests.IterableTest;
@SuppressWarnings("javadoc") @SuppressWarnings("javadoc")
@ -15,6 +21,7 @@ public abstract class BaseIntIterableTest
{ {
protected static final int[] EMPTY_ARRAY = new int[0]; protected static final int[] EMPTY_ARRAY = new int[0];
protected static final int[] TEST_ARRAY = IntStream.range(0, 100).toArray(); protected static final int[] TEST_ARRAY = IntStream.range(0, 100).toArray();
protected static final int[] DISTINCT_ARRAY = IntStream.range(0, 100).flatMap(T -> Arrays.stream(new int[]{T, T})).toArray();
protected abstract IntIterable create(int[] data); protected abstract IntIterable create(int[] data);
@ -65,4 +72,103 @@ public abstract class BaseIntIterableTest
} }
} }
} }
@Test
public void testStreamCount() {
if(getValidIterableTests().contains(IterableTest.STREAM_COUNT)) {
long expected = IntStream.of(TEST_ARRAY).filter(T -> T % 2 == 0).count();
int size = create(TEST_ARRAY).count(T -> T % 2 == 0);
Assert.assertEquals(expected, size);
}
}
@Test
public void testStreamFilter() {
if(getValidIterableTests().contains(IterableTest.STREAM_FILTER)) {
int[] expected = IntStream.of(TEST_ARRAY).filter(T -> T % 2 == 0).toArray();
int[] actual = IntIterators.pour(create(TEST_ARRAY).filter(T -> T % 2 == 0).iterator()).toIntArray();
IntArrays.stableSort(actual);
Assert.assertArrayEquals(expected, actual);
}
}
@Test
public void testStreamFindFirst() {
if(getValidIterableTests().contains(IterableTest.STREAM_FIND_FIRST)) {
int expected = IntStream.of(TEST_ARRAY).filter(T -> T / 50 > 0).findFirst().getAsInt();
int actual = create(TEST_ARRAY).findFirst(T -> T / 50 > 0);
Assert.assertEquals(expected, actual);
}
}
@Test
public void teastStreamDistinct() {
if(getValidIterableTests().contains(IterableTest.STREAM_DISTINCT)) {
int[] expected = IntStream.of(DISTINCT_ARRAY).distinct().toArray();
int[] actual = IntIterators.pour(create(DISTINCT_ARRAY).distinct().iterator()).toIntArray();
IntArrays.stableSort(actual);
Assert.assertArrayEquals(expected, actual);
}
}
@Test
public void testStreamLimit() {
if(getValidIterableTests().contains(IterableTest.STREAM_LIMIT)) {
int[] expected = IntStream.of(TEST_ARRAY).limit(25).toArray();
int[] actual = IntIterators.pour(create(TEST_ARRAY).limit(25).iterator()).toIntArray();
Assert.assertEquals(expected.length, actual.length);
}
}
@Test
public void testStreamMap() {
if(getValidIterableTests().contains(IterableTest.STREAM_MAP)) {
Integer[] expected = IntStream.of(TEST_ARRAY).mapToObj(Integer::new).toArray(Integer[]::new);
Integer[] actual = ObjectIterators.pour(create(TEST_ARRAY).map(Integer::new).iterator()).toArray(Integer[]::new);
ObjectArrays.stableSort(actual);
Assert.assertArrayEquals(expected, actual);
}
}
@Test
public void testStreamMatches() {
if(getValidIterableTests().contains(IterableTest.STREAM_MATCHES)) {
IntIterable iterable = create(TEST_ARRAY);
Assert.assertTrue(iterable.matchesAll(T -> T >= 0));
Assert.assertFalse(iterable.matchesAll(T -> T < 0));
Assert.assertTrue(iterable.matchesAny(T -> T % 2 != 0));
Assert.assertFalse(iterable.matchesAny(T -> T % 2 >= 2));
Assert.assertTrue(iterable.matchesNone(T -> T % 2 >= 2));
Assert.assertFalse(iterable.matchesNone(T -> T % 2 != 0));
}
}
@Test
public void testStreamPeek() {
if(getValidIterableTests().contains(IterableTest.STREAM_PEEK)) {
int[] peekCount = new int[2];
create(TEST_ARRAY).peek(T -> peekCount[0]++).forEach(T -> peekCount[1]++);
Assert.assertEquals(TEST_ARRAY.length, peekCount[0]);
Assert.assertEquals(TEST_ARRAY.length, peekCount[1]);
}
}
@Test
public void testStreamPour() {
if(getValidIterableTests().contains(IterableTest.STREAM_POUR)) {
int[] expected = TEST_ARRAY;
int[] actual = create(TEST_ARRAY).pour(new IntArrayList()).toIntArray();
IntArrays.stableSort(actual);
Assert.assertArrayEquals(expected, actual);
}
}
@Test
public void testStreamReduce() {
if(getValidIterableTests().contains(IterableTest.STREAM_REDUCE)) {
int expected = IntStream.of(TEST_ARRAY).reduce(0, Integer::sum);
int actual = create(TEST_ARRAY).reduce(0, Integer::sum);
Assert.assertEquals(expected, actual);
}
}
} }

View File

@ -7,5 +7,15 @@ public enum IterableTest
ITERATOR_FOR_EACH, ITERATOR_FOR_EACH,
ITERATOR_LOOP, ITERATOR_LOOP,
ITERATOR_REMOVAL, ITERATOR_REMOVAL,
ITERATOR_SKIP; ITERATOR_SKIP,
STREAM_COUNT,
STREAM_FILTER,
STREAM_FIND_FIRST,
STREAM_DISTINCT,
STREAM_LIMIT,
STREAM_MAP,
STREAM_MATCHES,
STREAM_PEEK,
STREAM_POUR,
STREAM_REDUCE;
} }