Addition of PriorityQueues

-Added: PriorityQueue
-Added: PriorityDequeue
-Added: FIFOQueue
-Added: ArrayFIFO
-Added: ArrayPriorityQueue
-Added: HeapPriorityQueue
-Changed: Micro Optimization for Iterators to reduce Boxing/Unboxing
-Added: Helper replacers for cleaner template code.
-Added: Heap Methods to Arrays
-Changed: Upgraded to SCG1.0.1
This commit is contained in:
Speiger 2021-01-20 04:29:08 +01:00
parent 9a9e08311b
commit a8318a3941
22 changed files with 1075 additions and 93 deletions

View File

@ -1,6 +1,32 @@
# Primitive-Collections
Simple library to create primitive collections.
Using template files to generate them.
Project for self teaching.
# Primitive-Collections (To be Renamed)
This is a Simple Primitive Collections Library i started as a hobby Project.
It's basis is of FastUtil and Java's Collection Library
But both lib's have a lot of problems, and in FastUtils case foundation seem changes to be no longer possible.
So this project was started.
With a Rule-Sheet, and also hopefully more Test-Coverage.
Currently Cons against FastUtil (will/might change over time).
- No Maps, this is next on the todolist.
- No Singletons,
- No BigLists/Sets/Maps
- No Custom Spliterator support.
- No Reference Collections.
- Some implementations are slower due to not including all Micro-optimizations (this might not change)
- Not as Specific Case Testing compared to FastUtil
- No Java Serialization implemented
- Code Generator is right now not finalized and no automatic setup exists as of this moment.
Pros against FastUtil
- A Cleaner implementation of Collections that do exists: NavigableSet (Exists), PriorityQueues are Save-able outside of java Serialization and a lot of others.
- More Consistency with features, not leaving a lot of holes in implementations. (Anything outside of HashMaps/Lists have massive holes)
- Abstract Tests to allow more coverage on tests and allow quicker implementation on tests on new Implementations.
- A lot better packaging where each types have their own packages to also make it easier to use the library. (lists/sets/collections/queues/utils)
- Due to package name choice: This Library imports do not overshadow java imports. (Anything after s is overshadowed)
- No Linux Environment necessary to generate the sourcecode if you want to work on it. All done with Java and or Gradle.
- A lot of extra functions that become useful in some cases, like: ITrimmable, IArray, extractElements(from, to), moveToFirst/Last, PriorityQueue iterator. Better Synchronization wrappers that expose useful interfaces.
- More Control how internals work thanks to SanityChecks
- Support to some extend of a Java Specific Feature: Non-TypeSepcific Collection Non Delete functions. (any method that used Object as Parameter instead of Generic)
This Library also includes my own MergeSort Algorithm that does not need to duplicate the input array.
It is a bit slower depending on the size, but is a stable sort that does not require to duplicate an array

View File

@ -1,26 +1,30 @@
plugins {
id 'java-library'
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
eclipse {
classpath {
downloadJavadoc = true
downloadSources = true
}
}
repositories {
jcenter()
flatDir {
dirs '/libs'
}
}
dependencies {
compile 'SimpleCodeGenerator:Simple Code Generator:1.0'
testImplementation 'junit:junit:4.12'
}
plugins {
id 'java-library'
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
eclipse {
classpath {
downloadJavadoc = true
downloadSources = true
}
}
repositories {
jcenter()
flatDir {
dirs '/libs'
}
}
dependencies {
compile 'SimpleCodeGenerator:Simple Code Generator:1.0.1'
testImplementation 'junit:junit:4.12'
}
test {
useJUnit()
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,6 +8,7 @@ import java.util.Set;
import java.util.function.UnaryOperator;
import speiger.src.builder.mappers.ArgumentMapper;
import speiger.src.builder.mappers.IMapper;
import speiger.src.builder.mappers.InjectMapper;
import speiger.src.builder.mappers.LineMapper;
import speiger.src.builder.mappers.SimpleMapper;
@ -15,7 +16,7 @@ import speiger.src.builder.processor.TemplateProcess;
public class GlobalVariables
{
List<UnaryOperator<String>> operators = new ArrayList<>();
List<IMapper> operators = new ArrayList<>();
Set<String> flags = new LinkedHashSet<>();
ClassType type;
@ -42,13 +43,12 @@ public class GlobalVariables
addSimpleMapper("JAVA_TYPE", type.getCustomJDKType().getKeyType());
addSimpleMapper("SANITY_CAST", "castTo"+type.getFileType());
}
addAnnontion("@PrimitiveOverride", "@Override");
addSimpleMapper("@PrimitiveDoc", "");
addDeprication("@Primitive");
addAnnontion("@Primitive", "@Deprecated");
return this;
}
public GlobalVariables createHelperVariables()
{
addArgumentMapper("EQUALS_KEY_TYPE", type.isObject() ? "Objects.equals(%2$s, %1$s)" : "Objects.equals(%2$s, KEY_TO_OBJ(%1$s))").removeBraces();
@ -63,7 +63,10 @@ public class GlobalVariables
addInjectMapper("CLASS_TO_KEY", "(("+type.getClassType()+")%s)."+type.getKeyType()+"Value()").removeBraces();
addSimpleMapper("APPLY", "applyAs"+type.getCustomJDKType().getNonFileType());
addInjectMapper("TO_HASH", type.isObject() ? "%s.hashCode()" : type.getClassType()+".hashCode(%s)").removeBraces();
addSimpleMapper("CAST_KEY_ARRAY ", type.isObject() ? "(KEY_TYPE[])" : "");
addSimpleMapper("EMPTY_KEY_ARRAY", type.isObject() ? "(KEY_TYPE[])ARRAYS.EMPTY_ARRAY" : "ARRAYS.EMPTY_ARRAY");
addInjectMapper("NEW_KEY_ARRAY", type.isObject() ? "(KEY_TYPE[])new Object[%s]" : "new KEY_TYPE[%s]").removeBraces();
addInjectMapper("NEW_CLASS_ARRAY", type.isObject() ? "(CLASS_TYPE[])new Object[%s]" : "new CLASS_TYPE[%s]").removeBraces();
return this;
}
@ -75,6 +78,9 @@ public class GlobalVariables
//Final Classes
addClassMapper("ARRAY_LIST", "ArrayList");
addClassMapper("ARRAY_FIFO_QUEUE", "ArrayFIFOQueue");
addClassMapper("ARRAY_PRIORITY_QUEUE", "ArrayPriorityQueue");
addClassMapper("HEAP_PRIORITY_QUEUE", "HeapPriorityQueue");
addClassMapper("LINKED_CUSTOM_HASH_SET", "LinkedOpenCustomHashSet");
addClassMapper("LINKED_HASH_SET", "LinkedOpenHashSet");
addClassMapper("CUSTOM_HASH_SET", "OpenCustomHashSet");
@ -105,6 +111,8 @@ public class GlobalVariables
addClassMapper("LIST_ITER", "ListIter");
addClassMapper("LIST", "List");
addClassMapper("NAVIGABLE_SET", "NavigableSet");
addClassMapper("PRIORITY_QUEUE", "PriorityQueue");
addClassMapper("PRIORITY_DEQUEUE", "PriorityDequeue");
addClassMapper("SORTED_SET", "SortedSet");
addClassMapper("SET", "Set");
addClassMapper("STRATEGY", "Strategy");
@ -129,7 +137,12 @@ public class GlobalVariables
addFunctionMapper("NEXT", "next");
addSimpleMapper("TO_ARRAY", "to"+type.getNonFileType()+"Array");
addFunctionMapper("GET_KEY", "get");
addFunctionMapper("ENQUEUE_FIRST", "enqueueFirst");
addFunctionMapper("ENQUEUE", "enqueue");
addFunctionMapper("DEQUEUE_LAST", "dequeueLast");
addFunctionMapper("DEQUEUE", "dequeue");
addFunctionMapper("REMOVE_KEY", "rem");
addFunctionMapper("REMOVE_LAST", "removeLast");
addFunctionMapper("REMOVE", "remove");
addFunctionMapper("PREVIOUS", "previous");
addFunctionMapper("PEEK", "peek");
@ -175,38 +188,38 @@ public class GlobalVariables
private void addClassMapper(String pattern, String replacement)
{
operators.add(new SimpleMapper(pattern, type.getFileType()+replacement));
operators.add(new SimpleMapper(type.name()+"["+pattern+"]", pattern, type.getFileType()+replacement));
}
private void addAbstractMapper(String pattern, String replacement)
{
operators.add(new SimpleMapper(pattern, String.format(replacement, type.getFileType())));
operators.add(new SimpleMapper(type.name()+"["+pattern+"]", pattern, String.format(replacement, type.getFileType())));
}
private void addFunctionMapper(String pattern, String replacement)
{
operators.add(new SimpleMapper(pattern, replacement+type.getNonFileType()));
operators.add(new SimpleMapper(type.name()+"["+pattern+"]", pattern, replacement+type.getNonFileType()));
}
private void addFunctionMappers(String pattern, String replacement)
{
operators.add(new SimpleMapper(pattern, String.format(replacement, type.getNonFileType())));
operators.add(new SimpleMapper(type.name()+"["+pattern+"]", pattern, String.format(replacement, type.getNonFileType())));
}
private void addSimpleMapper(String pattern, String replacement)
{
operators.add(new SimpleMapper(pattern, replacement));
operators.add(new SimpleMapper(type.name()+"["+pattern+"]", pattern, replacement));
}
private void addDeprication(String pattern)
private void addAnnontion(String pattern, String value)
{
if(type == ClassType.OBJECT) operators.add(new LineMapper(pattern));
else operators.add(new SimpleMapper(pattern, "@Deprecated"));
if(type == ClassType.OBJECT) operators.add(new LineMapper(type.name()+"["+pattern+"]", pattern));
else operators.add(new SimpleMapper(type.name()+"["+pattern+"]", pattern, value));
}
private InjectMapper addInjectMapper(String pattern, String replacement)
{
InjectMapper mapper = new InjectMapper(pattern, replacement);
InjectMapper mapper = new InjectMapper(type.name()+"["+pattern+"]", pattern, replacement);
operators.add(mapper);
return mapper;
}
@ -218,7 +231,7 @@ public class GlobalVariables
private ArgumentMapper addArgumentMapper(String pattern, String replacement, String splitter)
{
ArgumentMapper mapper = new ArgumentMapper(pattern, replacement, splitter);
ArgumentMapper mapper = new ArgumentMapper(type.name()+"["+pattern+"]", pattern, replacement, splitter);
operators.add(mapper);
return mapper;
}

View File

@ -37,6 +37,12 @@ public class TestBuilder extends TemplateProcessor
return true;
}
@Override
protected boolean debugUnusedMappers()
{
return false;
}
@Override
protected void init()
{
@ -55,20 +61,19 @@ public class TestBuilder extends TemplateProcessor
nameRemapper.put("AbstractCollection", "Abstract%sCollection");
nameRemapper.put("AbstractSet", "Abstract%sSet");
nameRemapper.put("AbstractList", "Abstract%sList");
blocked.put("Consumer", EnumSet.of(ClassType.OBJECT));
blocked.put("Comparator", EnumSet.of(ClassType.OBJECT));
blocked.put("Stack", EnumSet.of(ClassType.OBJECT));
blocked.put("Sets", EnumSet.of(ClassType.BOOLEAN));
blocked.put("ArraySet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("AVLTreeSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("RBTreeSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("RBTreeSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("SortedSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("NavigableSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("OpenHashSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("OpenCustomHashSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("LinkedOpenHashSet", EnumSet.of(ClassType.BOOLEAN));
blocked.put("LinkedOpenCustomHashSet", EnumSet.of(ClassType.BOOLEAN));
addBlockage(ClassType.OBJECT, "Consumer", "Comparator", "Stack");
addBlockage(ClassType.BOOLEAN, "Sets", "ArraySet", "AVLTreeSet", "RBTreeSet", "SortedSet", "NavigableSet", "OpenHashSet", "OpenCustomHashSet", "LinkedOpenHashSet", "LinkedOpenCustomHashSet");
}
protected void addBlockage(ClassType type, String...args) {
for(String s : args) {
EnumSet<ClassType> set = blocked.get(s);
if(set == null) {
set = EnumSet.noneOf(ClassType.class);
blocked.put(s, set);
}
set.add(type);
}
}
@Override
@ -89,7 +94,7 @@ public class TestBuilder extends TemplateProcessor
{
try
{
new TestBuilder().process(false);
new TestBuilder().process(false);
}
catch(InterruptedException e)
{

View File

@ -27,9 +27,7 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle
@Override
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
boolean modified = false;
for(KEY_TYPE e : c) {
modified |= add(e);
}
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
return modified;
}
@ -49,7 +47,7 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle
*/
@Override
public boolean contains(KEY_TYPE e) {
for(KEY_TYPE entry : this) { if(EQUALS(entry, e)) return true; }
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) { if(EQUALS(iter.NEXT(), e)) return true; }
return false;
}
@ -75,8 +73,8 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle
@Override
public boolean containsAll(COLLECTION KEY_GENERIC_TYPE c) {
Objects.requireNonNull(c);
for(KEY_TYPE e : c)
if(!contains(e))
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();)
if(!contains(iter.NEXT()))
return false;
return true;
}
@ -107,8 +105,8 @@ public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractColle
@Override
public boolean containsAny(COLLECTION KEY_GENERIC_TYPE c) {
Objects.requireNonNull(c);
for(KEY_TYPE e : c)
if(contains(e))
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();)
if(contains(iter.NEXT()))
return true;
return false;
}

View File

@ -43,8 +43,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
boolean modified = false;
for(KEY_TYPE e : c)
modified |= add(e);
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
return modified;
}
@ -56,8 +55,7 @@ public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
@Override
public boolean addAll(LIST KEY_GENERIC_TYPE c) {
boolean modified = false;
for(KEY_TYPE e : c)
modified |= add(e);
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
return modified;
}

View File

@ -65,11 +65,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
* Creates a new ArrayList with a Empty array.
*/
public ARRAY_LIST() {
#if TYPE_OBJECT
data = (KEY_TYPE[])ARRAYS.EMPTY_ARRAY;
#else
data = ARRAYS.EMPTY_ARRAY;
#endif
data = EMPTY_KEY_ARRAY;
}
/**
@ -880,11 +876,7 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE
public boolean trim(int size) {
if(size > size() || size() == data.length) return false;
int value = Math.max(size, size());
#if TYPE_OBJECT
data = value == 0 ? (KEY_TYPE[])ARRAYS.EMPTY_ARRAY : Arrays.copyOf(data, value);
#else
data = value == 0 ? ARRAYS.EMPTY_ARRAY : Arrays.copyOf(data, value);
#endif
data = value == 0 ? EMPTY_KEY_ARRAY : Arrays.copyOf(data, value);
return true;
}

View File

@ -0,0 +1,275 @@
package speiger.src.collections.PACKAGE.queues;
#if TYPE_OBJECT
import java.util.Arrays;
import java.util.Comparator;
#endif
import java.util.NoSuchElementException;
import speiger.src.collections.PACKAGE.collections.ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
#endif
import speiger.src.collections.utils.ITrimmable;
public class ARRAY_FIFO_QUEUE KEY_GENERIC_TYPE implements PRIORITY_DEQUEUE KEY_GENERIC_TYPE, ITrimmable
{
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public static final int MIN_CAPACITY = 4;
protected transient KEY_TYPE[] array;
protected int first;
protected int last;
public ARRAY_FIFO_QUEUE(KEY_TYPE[] values) {
this(values, 0, values.length);
}
public ARRAY_FIFO_QUEUE(KEY_TYPE[] values, int size) {
this(values, 0, size);
}
public ARRAY_FIFO_QUEUE(KEY_TYPE[] values, int offset, int size) {
if (values.length < size) throw new IllegalArgumentException("Initial array (" + values.length + ") is smaller then the expected size (" + size + ")");
if(values.length <= 0) values = NEW_KEY_ARRAY(1);
array = values;
first = offset;
last = (offset + size) % array.length;
if(array.length == size) expand();
}
public ARRAY_FIFO_QUEUE(int capacity) {
if (capacity < 0) throw new IllegalArgumentException("Initial capacity (" + capacity + ") is negative");
array = NEW_KEY_ARRAY(Math.max(1, capacity));
}
public ARRAY_FIFO_QUEUE() {
this(MIN_CAPACITY);
}
@Override
public ITERATOR KEY_GENERIC_TYPE iterator() {
return new Iter();
}
@Override
public int size() {
final int apparentLength = last - first;
return apparentLength >= 0 ? apparentLength : array.length + apparentLength;
}
@Override
public void clear() {
#if TYPE_OBJECT
Arrays.fill(array, null);
#endif
first = last = 0;
}
@Override
public void ENQUEUE(KEY_TYPE e) {
array[last] = e;
last = ++last % array.length;
if(last == first) expand();
}
@Override
public void ENQUEUE_FIRST(KEY_TYPE e) {
if(first == 0) first = array.length;
array[--first] = e;
if(first == last) expand();
}
@Override
public KEY_TYPE DEQUEUE() {
if(first == last) throw new NoSuchElementException();
KEY_TYPE data = array[first];
#if TYPE_OBJECT
array[first] = null;
#endif
first = ++first % array.length;
reduce();
return data;
}
@Override
public KEY_TYPE DEQUEUE_LAST() {
if(first == last) throw new NoSuchElementException();
if(last == 0) last = array.length;
KEY_TYPE data = array[--last];
#if TYPE_OBJECT
array[last] = null;
#endif
reduce();
return data;
}
@Override
public KEY_TYPE PEEK(int index) {
if(first == last || index < 0 || index > size()) throw new NoSuchElementException();
return array[(first + index) % array.length];
}
@Override
public boolean REMOVE(KEY_TYPE e) {
if(first == last) return false;
for(int i = 0,m=size();i<m;i++) {
int index = (first + i) % array.length;
if(e == array[index])
return removeIndex(index);
}
return false;
}
@Override
public boolean REMOVE_LAST(KEY_TYPE e) {
if(first == last) return false;
if(first == last) return false;
for(int i = size()-1;i>=0;i--) {
int index = (first + i) % array.length;
if(e == array[index])
return removeIndex(index);
}
return false;
}
protected boolean removeIndex(int index) {
if(first >= last ? index < first && index > last : index < first || index > last) return false;
if(index == first) {
#if TYPE_OBJECT
array[first] = null;
#endif
first++;
}
else if(index == last) {
last--;
#if TYPE_OBJECT
array[last] = null;
#endif
}
else if(index > last) {
System.arraycopy(array, first, array, first+1, (index - first));
#if TYPE_OBJECT
array[first] = null;
#endif
first = ++first % array.length;
}
else if(index < first) {
System.arraycopy(array, index+1, array, index, (last - index) - 1);
#if TYPE_OBJECT
array[last] = null;
#endif
if(--last < 0) last += array.length;
}
else {
if(index - first < last - index) {
System.arraycopy(array, first, array, first+1, (index - first));
#if TYPE_OBJECT
array[first] = null;
#endif
first = ++first % array.length;
}
else {
System.arraycopy(array, index+1, array, index, (last - index) - 1);
#if TYPE_OBJECT
array[last] = null;
#endif
if(--last < 0) last += array.length;
}
}
reduce();
return true;
}
@Override
public void onChanged() {}
@Override
public COMPARATOR KEY_SUPER_GENERIC_TYPE comparator() { return null; }
@Override
public boolean trim(int size) {
int newSize = Math.max(size, size());
if(newSize >= array.length) return false;
KEY_TYPE[] newArray = NEW_KEY_ARRAY(newSize);
if(first <= last) System.arraycopy(array, first, newArray, 0, last - first);
else {
System.arraycopy(array, first, newArray, 0, array.length - first);
System.arraycopy(array, 0, newArray, array.length - first, last);
}
first = 0;
last = size();
array = newArray;
return true;
}
@Override
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] input) {
if(input == null || input.length < size()) input = NEW_KEY_ARRAY(size());
if (first <= last) System.arraycopy(array, first, input, 0, last - first);
else {
System.arraycopy(array, first, input, 0, array.length - first);
System.arraycopy(array, 0, input, array.length - first, last);
}
return input;
}
#if !TYPE_OBJECT
@Override
public CLASS_TYPE[] toArray(CLASS_TYPE[] input) {
if(input == null || input.length < size()) input = NEW_CLASS_ARRAY(size());
if (first <= last) {
for(int i = 0,m=last-first;i<m;i++)
input[i] = KEY_TO_OBJ(array[first + i]);
}
else {
int offset = 0;
for(int i = 0,m=array.length-first;i<m;i++,offset++)
input[i] = KEY_TO_OBJ(array[first + i]);
for(int i = 0;i<last;i++)
input[offset+i] = KEY_TO_OBJ(array[i]);
}
return input;
}
#endif
protected void reduce() {
final int size = size();
if (array.length > MIN_CAPACITY && size <= array.length / 4) resize(size, array.length / 2);
}
protected void expand() {
resize(array.length, (int)Math.min(MAX_ARRAY_SIZE, 2L * array.length));
}
protected final void resize(int oldSize, int newSize) {
KEY_TYPE[] newArray = NEW_KEY_ARRAY(newSize);
if(first >= last) {
if(oldSize != 0)
{
System.arraycopy(array, first, newArray, 0, array.length - first);
System.arraycopy(array, 0, newArray, array.length - first, last);
}
}
else System.arraycopy(array, first, newArray, 0, last-first);
first = 0;
last = oldSize;
array = newArray;
}
private class Iter implements ITERATOR KEY_GENERIC_TYPE
{
int index = first;
@Override
public boolean hasNext()
{
return index != last;
}
@Override
public KEY_TYPE NEXT() {
KEY_TYPE value = array[index];
removeIndex(index++);
return value;
}
}
}

View File

@ -0,0 +1,220 @@
package speiger.src.collections.PACKAGE.queues;
import java.util.Arrays;
import java.util.NoSuchElementException;
#if TYPE_OBJECT
import java.util.Comparator;
import java.util.Objects;
#endif
import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
#endif
import speiger.src.collections.PACKAGE.utils.ARRAYS;
public class ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE implements PRIORITY_QUEUE KEY_GENERIC_TYPE
{
protected transient KEY_TYPE[] array = EMPTY_KEY_ARRAY;
protected int size;
protected int firstIndex = -1;
protected COMPARATOR KEY_SUPER_GENERIC_TYPE comparator;
public ARRAY_PRIORITY_QUEUE() {
this(0, null);
}
public ARRAY_PRIORITY_QUEUE(COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
this(0, comp);
}
public ARRAY_PRIORITY_QUEUE(int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
if(size > 0) array = NEW_KEY_ARRAY(size);
this.size = size;
comparator = comp;
}
public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array) {
this(array, array.length);
}
public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array, int size) {
this.array = Arrays.copyOf(array, size);
this.size = size;
}
public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
this(array, array.length, comp);
}
public ARRAY_PRIORITY_QUEUE(KEY_TYPE[] array, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
this.array = Arrays.copyOf(array, size);
this.size = size;
this.comparator = comp;
}
public ARRAY_PRIORITY_QUEUE(COLLECTION KEY_GENERIC_TYPE c) {
array = CAST_KEY_ARRAY c.TO_ARRAY();
size = c.size();
}
public ARRAY_PRIORITY_QUEUE(COLLECTION KEY_GENERIC_TYPE c, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
array = CAST_KEY_ARRAY c.TO_ARRAY();
size = c.size();
comparator = comp;
}
public static GENERIC_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array) {
return wrap(array, array.length);
}
public static GENERIC_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, int size) {
ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE queue = new ARRAY_PRIORITY_QUEUEBRACES();
queue.array = array;
queue.size = size;
return queue;
}
public static GENERIC_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
return wrap(array, array.length, comp);
}
public static GENERIC_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE queue = new ARRAY_PRIORITY_QUEUEBRACES(comp);
queue.array = array;
queue.size = size;
return queue;
}
@Override
public void ENQUEUE(KEY_TYPE e) {
if(size == array.length) array = Arrays.copyOf(array, size+1);
if(firstIndex != -1){
int compare = comparator == null ? COMPARE_TO_KEY(e, array[firstIndex]) : comparator.compare(e, array[firstIndex]);
if(compare < 0) firstIndex = size;
else if(compare > 0) firstIndex = -1;
}
array[size++] = e;
}
@Override
public KEY_TYPE DEQUEUE() {
if(size <= 0) throw new NoSuchElementException();
int index = findFirstIndex();
KEY_TYPE value = array[index];
if(index != --size) System.arraycopy(array, index+1, array, index, size - index);
#if TYPE_OBJECT
array[size] = null;
#endif
firstIndex = -1;
return value;
}
@Override
public KEY_TYPE PEEK(int index) {
if(index < 0 || index >= size) throw new NoSuchElementException();
return array[index];
}
@Override
public boolean REMOVE(KEY_TYPE e) {
for(int i = 0;i<size;i++)
if(EQUALS(e, array[i])) return removeIndex(i);
return false;
}
@Override
public boolean REMOVE_LAST(KEY_TYPE e) {
for(int i = size-1;i>=0;i--)
if(EQUALS(e, array[i])) return removeIndex(i);
return false;
}
protected boolean removeIndex(int index) {
if(index != --size) System.arraycopy(array, index+1, array, index, size - index);
#if TYPE_OBJECT
array[size] = null;
#endif
if(index == firstIndex) firstIndex = -1;
else if(index >= firstIndex) firstIndex--;
return true;
}
@Override
public void onChanged() {
firstIndex = -1;
}
@Override
public int size() {
return size;
}
@Override
public void clear() {
#if TYPE_OBJECT
Arrays.fill(array, null);
#endif
size = 0;
}
@Override
public ITERATOR KEY_GENERIC_TYPE iterator() {
return new Iter();
}
@Override
public COMPARATOR KEY_SUPER_GENERIC_TYPE comparator() {
return comparator;
}
@Override
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] input) {
if(input == null || input.length < size()) input = NEW_KEY_ARRAY(size());
System.arraycopy(array, 0, input, 0, size());
return input;
}
#if !TYPE_OBJECT
@Override
public CLASS_TYPE[] toArray(CLASS_TYPE[] input) {
if(input == null || input.length < size()) input = new CLASS_TYPE[size()];
for(int i = 0;i<size;i++) input[i] = KEY_TO_OBJ(array[i]);
return input;
}
#endif
protected int findFirstIndex() {
if(firstIndex == -1) {
int index = size-1;
KEY_TYPE value = array[index];
if(comparator == null) {
for(int i = index;firstIndex == -1 && i>=0;i--) {
if(COMPARE_TO_KEY(array[i], value) < 0)
value = array[index = i];
}
}
else {
for(int i = index;firstIndex == -1 && i>=0;i--) {
if(comparator.compare(array[i], value) < 0)
value = array[index = i];
}
}
firstIndex = index;
}
return firstIndex;
}
public class Iter implements ITERATOR KEY_GENERIC_TYPE {
@Override
public boolean hasNext() {
return !isEmpty();
}
@Override
public KEY_TYPE NEXT() {
return DEQUEUE();
}
}
}

View File

@ -0,0 +1,199 @@
package speiger.src.collections.PACKAGE.queues;
import java.util.Arrays;
import java.util.NoSuchElementException;
#if TYPE_OBJECT
import java.util.Comparator;
import java.util.Objects;
#endif
import speiger.src.collections.PACKAGE.collections.COLLECTION;
import speiger.src.collections.PACKAGE.collections.ITERATOR;
#if !TYPE_OBJECT
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
#endif
import speiger.src.collections.PACKAGE.utils.ARRAYS;
public class HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE implements PRIORITY_QUEUE KEY_GENERIC_TYPE
{
protected transient KEY_TYPE[] array = EMPTY_KEY_ARRAY;
protected int size;
protected COMPARATOR KEY_SUPER_GENERIC_TYPE comparator;
public HEAP_PRIORITY_QUEUE() {
this(0, null);
}
public HEAP_PRIORITY_QUEUE(COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
this(0, comp);
}
public HEAP_PRIORITY_QUEUE(int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
if(size > 0) array = NEW_KEY_ARRAY(size);
this.size = size;
comparator = comp;
}
public HEAP_PRIORITY_QUEUE(KEY_TYPE[] array) {
this(array, array.length);
}
public HEAP_PRIORITY_QUEUE(KEY_TYPE[] array, int size) {
this.array = Arrays.copyOf(array, size);
this.size = size;
ARRAYS.heapify(array, size, null);
}
public HEAP_PRIORITY_QUEUE(KEY_TYPE[] array, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
this(array, array.length, comp);
}
public HEAP_PRIORITY_QUEUE(KEY_TYPE[] array, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
this.array = Arrays.copyOf(array, size);
this.size = size;
comparator = comp;
ARRAYS.heapify(array, size, comp);
}
public HEAP_PRIORITY_QUEUE(COLLECTION KEY_GENERIC_TYPE c) {
array = CAST_KEY_ARRAY c.TO_ARRAY();
size = c.size();
ARRAYS.heapify(array, size, null);
}
public HEAP_PRIORITY_QUEUE(COLLECTION KEY_GENERIC_TYPE c, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
array = CAST_KEY_ARRAY c.TO_ARRAY();
size = c.size();
comparator = comp;
ARRAYS.heapify(array, size, comp);
}
public static GENERIC_BRACES HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array) {
return wrap(array, array.length);
}
public static GENERIC_BRACES HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, int size) {
HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE queue = new HEAP_PRIORITY_QUEUEBRACES();
queue.array = array;
queue.size = size;
ARRAYS.heapify(array, size, null);
return queue;
}
public static GENERIC_BRACES HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
return wrap(array, array.length, comp);
}
public static GENERIC_BRACES HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE queue = new HEAP_PRIORITY_QUEUEBRACES(comp);
queue.array = array;
queue.size = size;
ARRAYS.heapify(array, size, comp);
return queue;
}
@Override
public int size() {
return size;
}
@Override
public void clear() {
#if TYPE_OBJECT
Arrays.fill(array, null);
#endif
size = 0;
}
@Override
public ITERATOR KEY_GENERIC_TYPE iterator() {
return new Iter();
}
@Override
public void ENQUEUE(KEY_TYPE e) {
if(size == array.length) array = Arrays.copyOf(array, size + 1);
array[size++] = e;
ARRAYS.shiftUp(array, size-1, comparator);
}
@Override
public KEY_TYPE DEQUEUE() {
if(size <= 0) throw new NoSuchElementException();
KEY_TYPE value = array[0];
array[0] = array[--size];
#if TYPE_OBJECT
array[size] = null;
#endif
if(size != 0) ARRAYS.shiftDown(array, size, 0, comparator);
return value;
}
@Override
public KEY_TYPE PEEK(int index) {
if(index < 0 || index >= size) throw new NoSuchElementException();
return array[index];
}
@Override
public boolean REMOVE(KEY_TYPE e) {
for(int i = 0;i<size;i++)
if(EQUALS(e, array[i])) return removeIndex(i);
return false;
}
@Override
public boolean REMOVE_LAST(KEY_TYPE e) {
for(int i = size-1;i>=0;i--)
if(EQUALS(e, array[i])) return removeIndex(i);
return false;
}
protected boolean removeIndex(int index) {
array[index] = array[--size];
#if TYPE_OBJECT
array[size] = null;
#endif
if(size != index) ARRAYS.shiftDown(array, size, index, comparator);
return true;
}
@Override
public void onChanged() {
if(size <= 0) return;
ARRAYS.shiftDown(array, size, 0, comparator);
}
@Override
public COMPARATOR KEY_SUPER_GENERIC_TYPE comparator() {
return comparator;
}
@Override
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] input) {
if(input == null || input.length < size()) input = NEW_KEY_ARRAY(size());
System.arraycopy(array, 0, input, 0, size());
return input;
}
#if !TYPE_OBJECT
@Override
public CLASS_TYPE[] toArray(CLASS_TYPE[] input) {
if(input == null || input.length < size()) input = new CLASS_TYPE[size()];
for(int i = 0;i<size;i++) input[i] = KEY_TO_OBJ(array[i]);
return input;
}
#endif
public class Iter implements ITERATOR KEY_GENERIC_TYPE {
@Override
public boolean hasNext() {
return !isEmpty();
}
@Override
public KEY_TYPE NEXT() {
return DEQUEUE();
}
}
}

View File

@ -0,0 +1,12 @@
package speiger.src.collections.PACKAGE.queues;
public interface PRIORITY_DEQUEUE KEY_GENERIC_TYPE extends PRIORITY_QUEUE KEY_GENERIC_TYPE
{
public void ENQUEUE_FIRST(KEY_TYPE e);
public KEY_TYPE DEQUEUE_LAST();
#if !TYPE_OBJECT
public default void enqueueFirst(CLASS_TYPE e) { ENQUEUE_FIRST(OBJ_TO_KEY(e)); }
public default CLASS_TYPE dequeueLast() { return KEY_TO_OBJ(DEQUEUE_LAST()); }
#endif
}

View File

@ -0,0 +1,58 @@
package speiger.src.collections.PACKAGE.queues;
#if TYPE_OBJECT
import java.util.Comparator;
#else
import speiger.src.collections.PACKAGE.collections.ITERABLE;
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
import speiger.src.collections.objects.queues.ObjectPriorityQueue;
#endif
#if TYPE_OBJECT
public interface PRIORITY_QUEUE KEY_GENERIC_TYPE extends Iterable<KEY_TYPE>
#else
public interface PRIORITY_QUEUE KEY_GENERIC_TYPE extends ObjectPriorityQueue<CLASS_TYPE>, ITERABLE KEY_GENERIC_TYPE
#endif
{
#if TYPE_OBJECT
public default boolean isEmpty() { return size() <= 0; }
public int size();
public void clear();
#endif
public void ENQUEUE(KEY_TYPE e);
public KEY_TYPE DEQUEUE();
public KEY_TYPE PEEK(int index);
public default KEY_TYPE FIRST_KEY() { return peek(0); }
public default KEY_TYPE LAST_KEY() { return peek(size()-1); }
public boolean REMOVE(KEY_TYPE e);
public boolean REMOVE_LAST(KEY_TYPE e);
public void onChanged();
@PrimitiveOverride
public COMPARATOR KEY_SUPER_GENERIC_TYPE comparator();
public default KEY_TYPE[] TO_ARRAY() { return TO_ARRAY(NEW_KEY_ARRAY(size())); }
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] input);
#if !TYPE_OBJECT
public default void enqueue(CLASS_TYPE e) { ENQUEUE(OBJ_TO_KEY(e)); }
public default CLASS_TYPE dequeue() { return KEY_TO_OBJ(DEQUEUE()); }
public default CLASS_TYPE peek(int index) { return KEY_TO_OBJ(PEEK(index)); }
public default CLASS_TYPE first() { return peek(0); }
public default CLASS_TYPE last() { return peek(size()-1); }
public default boolean remove(CLASS_TYPE e) { return REMOVE(OBJ_TO_KEY(e)); }
public default boolean removeLast(CLASS_TYPE e) { return REMOVE_LAST(OBJ_TO_KEY(e)); }
@Deprecated
public default CLASS_TYPE[] toArray() { return toArray(new CLASS_TYPE[size()]); }
@Deprecated
public CLASS_TYPE[] toArray(CLASS_TYPE[] input);
#endif
}

View File

@ -14,11 +14,7 @@ public abstract class ABSTRACT_SET KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION
int hashCode = 1;
ITERATOR KEY_GENERIC_TYPE i = iterator();
while(i.hasNext())
#if TYPE_OBJECT
hashCode = 31 * hashCode + i.next().hashCode();
#else
hashCode = 31 * hashCode + TO_HASH(i.NEXT());
#endif
return hashCode;
}

View File

@ -23,11 +23,7 @@ public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE im
protected int size = 0;
public ARRAY_SET() {
#if TYPE_OBJECT
data = (KEY_TYPE[])ARRAYS.EMPTY_ARRAY;
#else
data = ARRAYS.EMPTY_ARRAY;
#endif
data = EMPTY_KEY_ARRAY;
}
public ARRAY_SET(int capacity) {

View File

@ -100,12 +100,70 @@ public class ARRAYS
* @param length the lenght the array should be.
* @return a Array with the requested type and length
*/
public static KEY_GENERIC_TYPE KEY_TYPE[] newArray(Class<KEY_TYPE> clz, int length) {
public static GENERIC_BRACES KEY_TYPE[] newArray(Class<KEY_TYPE> clz, int length) {
if(clz == Object.class) return (KEY_TYPE[])new Object[length];
return (KEY_TYPE[]) java.lang.reflect.Array.newInstance(clz, length);
}
#endif
public static GENERIC_BRACES int shiftDown(KEY_TYPE[] data, int size, int index, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
int half = size >>> 1;
KEY_TYPE value = data[index];
if(comp != null) {
while(index < half) {
int child = (index << 1) + 1;
KEY_TYPE childValue = data[child];
int right = child+1;
if(right < size && comp.compare(data[right], childValue) < 0) childValue = data[child = right];
if(comp.compare(value, childValue) <= 0) break;
data[index] = childValue;
index = child;
}
}
else {
while(index < half) {
int child = (index << 1) + 1;
KEY_TYPE childValue = data[child];
int right = child+1;
if(right < size && COMPARE_TO_KEY(data[right], childValue) < 0) childValue = data[child = right];
if(COMPARE_TO_KEY(value, childValue) <= 0) break;
data[index] = childValue;
index = child;
}
}
data[index] = value;
return index;
}
public static GENERIC_BRACES int shiftUp(KEY_TYPE[] data, int index, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
KEY_TYPE value = data[index];
if(comp != null) {
while(index > 0) {
int parent = (index - 1) >>> 1;
KEY_TYPE parentValue = data[parent];
if(comp.compare(value, parentValue) >= 0) break;
data[index] = parentValue;
index = parent;
}
}
else {
while(index > 0) {
int parent = (index - 1) >>> 1;
KEY_TYPE parentValue = data[parent];
if(COMPARE_TO_KEY(value, parentValue) >= 0) break;
data[index] = parentValue;
index = parent;
}
}
data[index] = value;
return index;
}
public static GENERIC_BRACES KEY_TYPE[] heapify(KEY_TYPE[] data, int size, COMPARATOR KEY_SUPER_GENERIC_TYPE comp) {
for(int i = (size >>> 1) - 1;i>=0;shiftDown(data, size, i--, comp));
return data;
}
public static GENERIC_BRACES KEY_TYPE[] shuffle(KEY_TYPE[] array) {
return shuffle(array, SanityChecks.getRandom());
}

View File

@ -0,0 +1,114 @@
package speiger.src.collections.ints.base;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.util.EnumSet;
import org.junit.Assert;
import org.junit.Test;
import speiger.src.collections.ints.queues.IntPriorityQueue;
import speiger.src.collections.tests.IterableTest;
import speiger.src.collections.tests.PriorityQueueTest;
public abstract class BaseIntPriorityQueueTest extends BaseIntIterableTest
{
@Override
protected abstract IntPriorityQueue create(int[] data);
@Override
protected EnumSet<IterableTest> getValidIterableTests() { return EnumSet.of(IterableTest.FOR_EACH, IterableTest.ITERATOR_FOR_EACH, IterableTest.ITERATOR_LOOP, IterableTest.ITERATOR_SKIP); }
protected EnumSet<PriorityQueueTest> getValidPriorityQueueTests() { return EnumSet.allOf(PriorityQueueTest.class); }
@Test
public void testEnqueue() {
if(getValidPriorityQueueTests().contains(PriorityQueueTest.IN_OUT)) {
IntPriorityQueue queue = create(EMPTY_ARRAY);
for(int i = 0;i<100;i++) {
queue.enqueueInt(i);
Assert.assertEquals(i, queue.lastInt());
}
for(int i = 0;i<100;i++) {
Assert.assertEquals(i, queue.firstInt());
Assert.assertEquals(99, queue.lastInt());
Assert.assertEquals(i, queue.dequeueInt());
}
}
}
@Test
public void testPeek() {
if(getValidPriorityQueueTests().contains(PriorityQueueTest.PEEK)) {
IntPriorityQueue queue = create(EMPTY_ARRAY);
for(int i = 0;i<100;i++) {
queue.enqueueInt(i);
Assert.assertEquals(i, queue.lastInt());
}
for(int i = 0;i<100;i++) {
assertEquals(i, queue.peekInt(i));
}
}
}
@Test
public void testRemove() {
if(getValidPriorityQueueTests().contains(PriorityQueueTest.REMOVE)) {
IntPriorityQueue queue = create(EMPTY_ARRAY);
for(int i = 0;i<100;i++) {
queue.enqueueInt(i);
Assert.assertEquals(i, queue.lastInt());
}
queue.removeInt(40);
for(int i = 0;i<99;i++) {
if(i >= 40) assertEquals(i + 1, queue.dequeueInt());
else assertEquals(i, queue.dequeueInt());
}
for(int i = 0;i<100;i++) {
queue.enqueueInt(i);
Assert.assertEquals(i, queue.lastInt());
}
queue.removeLastInt(40);
for(int i = 0;i<99;i++) {
if(i >= 40) assertEquals(i + 1, queue.dequeueInt());
else assertEquals(i, queue.dequeueInt());
}
}
}
@Test
@SuppressWarnings("deprecation")
public void testToArray() {
if(getValidPriorityQueueTests().contains(PriorityQueueTest.TO_ARRAY)) {
IntPriorityQueue q = create(EMPTY_ARRAY);
Integer[] ref = new Integer[100];
Integer[] shiftArray = new Integer[100];
int[] primRef = new int[100];
int[] shiftPrimArray = new int[100];
for(int i = 0; i < 100; i++) {
q.enqueue(i);
assertEquals(i, q.lastInt());
ref[i] = Integer.valueOf(i);
primRef[i] = i;
shiftPrimArray[(i+80) % 100] = i;
shiftArray[(i+80) % 100] = Integer.valueOf(i);
}
assertArrayEquals(q.toArray(), ref);
assertArrayEquals(q.toArray(new Integer[100]), ref);
assertArrayEquals(q.toArray(null), ref);
assertArrayEquals(q.toIntArray(), primRef);
assertArrayEquals(q.toIntArray(new int[100]), primRef);
assertArrayEquals(q.toIntArray(null), primRef);
IntPriorityQueue other = create(q.toIntArray());
for(int i = 0;i<100;i++) {
assertEquals(other.peekInt(i), primRef[i]);
}
for(int i = 0;i<20;i++) {
other.dequeueInt();
other.enqueue(i);
}
assertArrayEquals(other.toIntArray(), shiftPrimArray);
assertArrayEquals(other.toIntArray(new int[100]), shiftPrimArray);
assertArrayEquals(other.toArray(), shiftArray);
}
}
}

View File

@ -0,0 +1,9 @@
package speiger.src.collections.ints.queues;
import speiger.src.collections.ints.base.BaseIntPriorityQueueTest;
public class IntArrayFIFOQueueTests extends BaseIntPriorityQueueTest
{
@Override
protected IntPriorityQueue create(int[] data){return new IntArrayFIFOQueue(data);}
}

View File

@ -0,0 +1,9 @@
package speiger.src.collections.tests;
public enum PriorityQueueTest
{
IN_OUT,
PEEK,
REMOVE,
TO_ARRAY,
}