diff --git a/Changelog.md b/Changelog.md index 6e564c0e..7fb41a26 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,11 @@ # Changelog of versions +### Version 0.4.4 +- Fixed: ObjectArrayList.of was causing crashes because of a Poor implementation. +- Added: Unsorted HashMaps/Sets now throw Concurrent exceptions if they were modified during a rehash. +- Added: Array/Collection version of enqueue and enqueueFirst to PriorityQueues. +- Added: fillBuffer function into PrimitiveLists which allow to optimize JavaNio buffers if needed. + ### Version 0.4.3 - Added: Wrapper now support the Optimized Lambda replacer functions to improve performance. - Added: FIFO Queue has now a minimum capacity and that is now checked more consistently. diff --git a/README.md b/README.md index 28e65bb1..0562afd0 100644 --- a/README.md +++ b/README.md @@ -72,13 +72,14 @@ repositories { } } dependencies { - compile 'de.speiger:Primitive-Collections:0.4.3' + compile 'de.speiger:Primitive-Collections:0.4.4' } ``` Direct: | Version | Jar | Sources | Java Doc | |--------- |------------------------------------------------------------------------------------------------------------------------------ |-------------------------------------------------------------------------------------------------------------------------------------- |-------------------------------------------------------------------------------------------------------------------------------------- | +| 0.4.4 | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.4/Primitive-Collections-0.4.4.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.4/Primitive-Collections-0.4.4-sources.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.4/Primitive-Collections-0.4.4-javadoc.jar) | | 0.4.3 | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.3/Primitive-Collections-0.4.3.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.3/Primitive-Collections-0.4.3-sources.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.3/Primitive-Collections-0.4.3-javadoc.jar) | | 0.4.2 | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.2/Primitive-Collections-0.4.2.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.2/Primitive-Collections-0.4.2-sources.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.2/Primitive-Collections-0.4.2-javadoc.jar) | | 0.4.1 | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.1/Primitive-Collections-0.4.1.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.1/Primitive-Collections-0.4.1-sources.jar) | [Download](https://maven.speiger.com/repository/main/de/speiger/Primitive-Collections/0.4.1/Primitive-Collections-0.4.1-javadoc.jar) | diff --git a/build.gradle b/build.gradle index 31b08df5..147342ad 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ repositories { } archivesBaseName = 'Primitive Collections' -version = '0.4.3'; +version = '0.4.4'; sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' diff --git a/src/builder/java/speiger/src/builder/GlobalVariables.java b/src/builder/java/speiger/src/builder/GlobalVariables.java index 40e69571..504db1d7 100644 --- a/src/builder/java/speiger/src/builder/GlobalVariables.java +++ b/src/builder/java/speiger/src/builder/GlobalVariables.java @@ -153,6 +153,7 @@ public class GlobalVariables addSimpleMapper("JAVA_UNARY_OPERATOR", type.isObject() ? "BinaryOperator" : type == ClassType.BOOLEAN ? "" : type.getCustomJDKType().getFileType()+"UnaryOperator"); addSimpleMapper("JAVA_SPLIT_ITERATOR", type.isPrimitiveBlocking() ? "Spliterator" : "Of"+type.getCustomJDKType().getFileType()); addSimpleMapper("JAVA_STREAM", type.isPrimitiveBlocking() ? "" : type.getCustomJDKType().getFileType()+"Stream"); + addSimpleMapper("JAVA_BUFFER", type.getFileType()+"Buffer"); //Final Classes addClassMapper("ARRAY_LIST", "ArrayList"); diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template index 25aca449..ee0579f6 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template @@ -15,6 +15,7 @@ import java.util.function.UnaryOperator; #if PRIMITIVES import java.util.function.JAVA_PREDICATE; import java.util.function.JAVA_UNARY_OPERATOR; +import java.nio.JAVA_BUFFER; #endif import speiger.src.collections.PACKAGE.collections.COLLECTION; @@ -181,7 +182,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE */ public static GENERIC_KEY_BRACES ARRAY_LIST KEY_GENERIC_TYPE of(Class c) { ARRAY_LIST KEY_GENERIC_TYPE list = new ARRAY_LISTBRACES(); - list.data = (KEY_TYPE[])ObjectArrays.newArray(c.getClass().getComponentType(), 0); + list.data = (KEY_TYPE[])ObjectArrays.newArray(c, 0); return list; } @@ -388,9 +389,15 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE size -= length; return a; } + +#endif +#if PRIMITIVES + @Override + public void fillBuffer(JAVA_BUFFER buffer) { + buffer.put(data, 0, size); + } #endif - /** * A function to find if the Element is present in this list. * @param o the element that is searched for diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template b/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template index ca384dd7..0797124a 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/LinkedList.template @@ -2,6 +2,8 @@ package speiger.src.collections.PACKAGE.lists; #if TYPE_OBJECT import java.util.Comparator; +#else if PRIMITIVES +import java.nio.JAVA_BUFFER; #endif import java.util.Collection; import java.util.Iterator; @@ -637,6 +639,14 @@ public class LINKED_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE return d; } +#endif +#if PRIMITIVES + @Override + public void fillBuffer(JAVA_BUFFER buffer) { + for(Entry KEY_GENERIC_TYPE entry = first;entry != null;entry = entry.next) + buffer.put(entry.value); + } + #endif @Override @Primitive diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/List.template b/src/builder/resources/speiger/assets/collections/templates/lists/List.template index ebb2677c..3ffc1f01 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/List.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/List.template @@ -1,5 +1,8 @@ package speiger.src.collections.PACKAGE.lists; +#if PRIMITIVES +import java.nio.JAVA_BUFFER; +#endif import java.util.List; #if !TYPE_OBJECT && !TYPE_BOOLEAN import java.util.Objects; @@ -255,6 +258,14 @@ public interface LIST KEY_GENERIC_TYPE extends COLLECTION KEY_GENERIC_TYPE, List */ public KEY_TYPE[] extractElements(int from, int to); +#if PRIMITIVES + /** + * Helper function that allows to fastFill a buffer reducing the duplication requirement + * @param buffer where the data should be stored in. + */ + public default void fillBuffer(JAVA_BUFFER buffer) { buffer.put(TO_ARRAY()); } + +#endif /** {@inheritDoc} *

This default implementation delegates to the corresponding type-specific function. * @deprecated Please use the corresponding type-specific function instead. diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template index 8045bb70..03f43570 100644 --- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template +++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/customHash/OpenCustomHashMap.template @@ -1,6 +1,7 @@ package speiger.src.collections.PACKAGE.maps.impl.customHash; import java.util.Arrays; +import java.util.ConcurrentModificationException; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; @@ -667,7 +668,10 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1); VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1); for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) { - while(strategy.equals(keys[--i], EMPTY_KEY_VALUE)); + while(true) { + if(--i < 0) throw new ConcurrentModificationException("Map was modified during rehash"); + if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) break; + } if(!strategy.equals(newKeys[pos = HashUtil.mix(strategy.hashCode(keys[i])) & newMask], EMPTY_KEY_VALUE)) while(!strategy.equals(newKeys[pos = (++pos & newMask)], EMPTY_KEY_VALUE)); newKeys[pos] = keys[i]; diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template index b17f665f..5cd34740 100644 --- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template +++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/OpenHashMap.template @@ -1,6 +1,7 @@ package speiger.src.collections.PACKAGE.maps.impl.hash; import java.util.Arrays; +import java.util.ConcurrentModificationException; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; @@ -627,7 +628,10 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1); VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1); for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) { - while(KEY_EQUALS_NULL(keys[--i])); + while(true) { + if(--i < 0) throw new ConcurrentModificationException("Map was modified during rehash"); + if(KEY_EQUALS_NOT_NULL(keys[i])) break; + } if(KEY_EQUALS_NOT_NULL(newKeys[pos = HashUtil.mix(KEY_TO_HASH(keys[i])) & newMask])) while(KEY_EQUALS_NOT_NULL(newKeys[pos = (++pos & newMask)])); newKeys[pos] = keys[i]; diff --git a/src/builder/resources/speiger/assets/collections/templates/queues/PriorityDequeue.template b/src/builder/resources/speiger/assets/collections/templates/queues/PriorityDequeue.template index b6edb168..90ddb2b1 100644 --- a/src/builder/resources/speiger/assets/collections/templates/queues/PriorityDequeue.template +++ b/src/builder/resources/speiger/assets/collections/templates/queues/PriorityDequeue.template @@ -1,5 +1,12 @@ package speiger.src.collections.PACKAGE.queues; +#if TYPE_OBJECT +import java.util.Collection; +import java.util.Iterator; +#endif +import speiger.src.collections.PACKAGE.collections.COLLECTION; +import speiger.src.collections.PACKAGE.collections.ITERATOR; + /** * A Type Speciifc PriorityDeque or Dequeue interface to allow implementations like FIFO queues. * @Type(T) @@ -11,6 +18,56 @@ public interface PRIORITY_DEQUEUE KEY_GENERIC_TYPE extends PRIORITY_QUEUE KEY_GE * @param e the element that should be inserted into the first place */ public void enqueueFirst(KEY_TYPE e); + + /** + * Method to mass insert a elements into the first Index of the PriorityDequeue. + * @param e the elements that should be inserted + */ + public default void enqueueAllFirst(KEY_TYPE... e) { + enqueueAllFirst(e, 0, e.length); + } + + /** + * Method to mass insert a elements into the first Index of the PriorityDequeue. + * @param e the elements that should be inserted + * @param length the amount of elements that should be inserted + */ + public default void enqueueAllFirst(KEY_TYPE[] e, int length) { + enqueueAllFirst(e, 0, length); + } + + /** + * Method to mass insert a elements into the first Index of the PriorityDequeue. + * @param e the elements that should be inserted + * @param offset the offset where in the array should be started + * @param length the amount of elements that should be inserted + */ + public default void enqueueAllFirst(KEY_TYPE[] e, int offset, int length) { + for(int i = 0;i c) { + for(Iterator iter = c.iterator();iter.hasNext();) + enqueueFirst(iter.next()); + } + +#endif /** * A Method to remove a element from the last place instead of the first * @return the last element inserted diff --git a/src/builder/resources/speiger/assets/collections/templates/queues/PriorityQueue.template b/src/builder/resources/speiger/assets/collections/templates/queues/PriorityQueue.template index 8d0df4e4..d3f1e23b 100644 --- a/src/builder/resources/speiger/assets/collections/templates/queues/PriorityQueue.template +++ b/src/builder/resources/speiger/assets/collections/templates/queues/PriorityQueue.template @@ -2,11 +2,14 @@ package speiger.src.collections.PACKAGE.queues; #if TYPE_OBJECT import java.util.Comparator; -import speiger.src.collections.objects.collections.ObjectIterator; +import java.util.Collection; +import java.util.Iterator; #else import speiger.src.collections.PACKAGE.functions.COMPARATOR; #endif +import speiger.src.collections.PACKAGE.collections.COLLECTION; import speiger.src.collections.PACKAGE.collections.ITERABLE; +import speiger.src.collections.PACKAGE.collections.ITERATOR; /** * A Simple PriorityQueue (or Queue) interface that provides with the nessesary functions to interact with it, without cluttering with the Collection interface. @@ -33,6 +36,57 @@ public interface PRIORITY_QUEUE KEY_GENERIC_TYPE extends ITERABLE KEY_GENERIC_TY * @param e the element that should be inserted */ public void enqueue(KEY_TYPE e); + + /** + * Method to mass insert elements into the PriorityQueue + * @param e the elements that should be inserted + */ + public default void enqueueAll(KEY_TYPE... e) { + enqueueAll(e, 0, e.length); + } + + /** + * Method to mass insert elements into the PriorityQueue + * @param e the elements that should be inserted + * @param length the amount of elements that should be inserted + */ + public default void enqueueAll(KEY_TYPE[] e, int length) { + enqueueAll(e, 0, length); + } + + /** + * Method to mass insert elements into the PriorityQueue + * @param e the elements that should be inserted + * @param offset the offset where in the array should be started + * @param length the amount of elements that should be inserted + */ + public default void enqueueAll(KEY_TYPE[] e, int offset, int length) { + for(int i = 0;i c) { + for(Iterator iter = c.iterator();iter.hasNext();) + enqueue(iter.next()); + } + +#endif + /** * Method to extract a element from the PriorityQueue * @return a element from the Queue diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template index efab7194..fc69e8c6 100644 --- a/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template +++ b/src/builder/resources/speiger/assets/collections/templates/sets/OpenCustomHashSet.template @@ -2,6 +2,7 @@ package speiger.src.collections.PACKAGE.sets; import java.util.Arrays; import java.util.Collection; +import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; @@ -429,7 +430,10 @@ public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_T int newMask = newSize - 1; KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1); for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) { - while(strategy.equals(keys[--i], EMPTY_KEY_VALUE)); + while(true) { + if(--i < 0) throw new ConcurrentModificationException("Set was modified during rehash"); + if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) break; + } if(!strategy.equals(newKeys[pos = HashUtil.mix(KEY_TO_HASH(keys[i])) & newMask], EMPTY_KEY_VALUE)) while(!strategy.equals(newKeys[pos = (++pos & newMask)], EMPTY_KEY_VALUE)); newKeys[pos] = keys[i]; diff --git a/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template b/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template index 942a16fe..6e6c7227 100644 --- a/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template +++ b/src/builder/resources/speiger/assets/collections/templates/sets/OpenHashSet.template @@ -2,6 +2,7 @@ package speiger.src.collections.PACKAGE.sets; import java.util.Arrays; import java.util.Collection; +import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; @@ -461,7 +462,10 @@ public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE imp int newMask = newSize - 1; KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1); for(int i = nullIndex, pos = 0, j = (size - (containsNull ? 1 : 0));j-- != 0;) { - while(KEY_EQUALS_NULL(keys[--i])); + while(true) { + if(--i < 0) throw new ConcurrentModificationException("Set was modified during rehash"); + if(KEY_EQUALS_NOT_NULL(keys[i])) break; + } if(KEY_EQUALS_NOT_NULL(newKeys[pos = HashUtil.mix(KEY_TO_HASH(keys[i])) & newMask])) while(KEY_EQUALS_NOT_NULL(newKeys[pos = (++pos & newMask)])); newKeys[pos] = keys[i]; diff --git a/src/builder/resources/speiger/assets/collections/templates/utils/Lists.template b/src/builder/resources/speiger/assets/collections/templates/utils/Lists.template index 27b59a0c..1690856a 100644 --- a/src/builder/resources/speiger/assets/collections/templates/utils/Lists.template +++ b/src/builder/resources/speiger/assets/collections/templates/utils/Lists.template @@ -5,6 +5,9 @@ import java.util.Objects; import java.util.Random; import java.util.RandomAccess; import java.util.function.Consumer; +#if PRIMITIVES +import java.nio.JAVA_BUFFER; +#endif import speiger.src.collections.PACKAGE.collections.COLLECTION; #if !TYPE_OBJECT @@ -204,7 +207,11 @@ public class LISTS a[offset] = element; return a; } - +#if PRIMITIVES + @Override + public void fillBuffer(JAVA_BUFFER buffer) { buffer.put(element); } +#endif + @Override public void removeElements(int from, int to) { throw new UnsupportedOperationException(); } #if TYPE_OBJECT @@ -357,6 +364,9 @@ public class LISTS @Override public K[] extractElements(int from, int to, Class clz) { synchronized(mutex) { return l.extractElements(from, to, clz); } } +#endif +#if PRIMITIVES + public void fillBuffer(JAVA_BUFFER buffer) { synchronized(mutex) { l.fillBuffer(buffer); } } #endif @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() { @@ -469,6 +479,10 @@ public class LISTS @Override public K[] extractElements(int from, int to, Class clz) { throw new UnsupportedOperationException(); } +#endif +#if PRIMITIVES + public void fillBuffer(JAVA_BUFFER buffer) { l.fillBuffer(buffer); } + #endif @Override public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() { diff --git a/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template b/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template index 80471bac..25b20cb7 100644 --- a/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template +++ b/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template @@ -1,11 +1,13 @@ package speiger.src.collections.PACKAGE.utils; #if TYPE_OBJECT +import java.util.Collection; import java.util.Comparator; import java.util.function.Consumer; #endif import speiger.src.collections.PACKAGE.collections.ITERATOR; +import speiger.src.collections.PACKAGE.collections.COLLECTION; #if !TYPE_OBJECT import speiger.src.collections.PACKAGE.functions.COMPARATOR; #endif @@ -92,6 +94,14 @@ public class PRIORITY_QUEUES public void clear() { synchronized(mutex) { queue.clear(); } } @Override public void enqueue(KEY_TYPE e) { synchronized(mutex) { queue.enqueue(e); } } + @Override + public void enqueueAll(KEY_TYPE[] e, int offset, int length) { synchronized(mutex) { queue.enqueueAll(e, offset, length); } } + @Override + public void enqueueAll(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { queue.enqueueAll(c); } } +#if TYPE_OBJECT + @Override + public void enqueueAll(Collection c) { synchronized(mutex) { queue.enqueueAll(c); } } +#endif @Override public KEY_TYPE dequeue() { synchronized(mutex) { return queue.dequeue(); } } @Override @@ -143,6 +153,14 @@ public class PRIORITY_QUEUES @Override public void enqueueFirst(KEY_TYPE e) { synchronized(mutex) { dequeue.enqueueFirst(e); } } + @Override + public void enqueueAllFirst(KEY_TYPE[] e, int offset, int length) { synchronized(mutex) { dequeue.enqueueAllFirst(e, offset, length); } } + @Override + public void enqueueAllFirst(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { dequeue.enqueueAllFirst(c); } } +#if TYPE_OBJECT + @Override + public void enqueueAllFirst(Collection c) { synchronized(mutex) { dequeue.enqueueAllFirst(c); } } +#endif @Override public KEY_TYPE dequeueLast() { synchronized(mutex) { return dequeue.dequeueLast(); } } @Override diff --git a/src/test/java/speiger/src/collections/objects/list/ObjectArrayListTest.java b/src/test/java/speiger/src/collections/objects/list/ObjectArrayListTest.java index 7984b1e5..dd61d475 100644 --- a/src/test/java/speiger/src/collections/objects/list/ObjectArrayListTest.java +++ b/src/test/java/speiger/src/collections/objects/list/ObjectArrayListTest.java @@ -22,6 +22,13 @@ public class ObjectArrayListTest testCastable(ObjectArrayList.wrap("Test", "Testing", "Testing stuff"), true); } + @Test + public void testEmptyCreation() + { + ObjectArrayList test = ObjectArrayList.of(String.class); + Assert.assertTrue(test.isCastable()); + } + public void testCastable(IObjectArray castable, boolean result) { Assert.assertTrue(castable.isCastable() == result);