Project is now buildable.
-Moved: Code generation is in its own sourceset. -Fixed: Bugs that caused that the project isnt buildable. -Changed: Made build.gradle to a standard.
This commit is contained in:
+206
@@ -0,0 +1,206 @@
|
||||
package speiger.src.collections.PACKAGE.collections;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.AbstractCollection;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
|
||||
public abstract class ABSTRACT_COLLECTION KEY_GENERIC_TYPE extends AbstractCollection<CLASS_TYPE> implements COLLECTION KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public abstract ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean add(CLASS_TYPE e) { return COLLECTION.super.add(e); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
boolean modified = false;
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
|
||||
return modified;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean contains(Object e) { return COLLECTION.super.contains(e); }
|
||||
|
||||
/**
|
||||
* A Type-Specific implementation of contains. This implementation iterates over the elements and returns true if the value match.
|
||||
* @param value that should be searched for.
|
||||
* @return true if the value was found.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) { if(KEY_EQUALS(iter.NEXT(), e)) return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean addAll(Collection<? extends CLASS_TYPE> c)
|
||||
{
|
||||
return c instanceof COLLECTION ? addAll((COLLECTION KEY_GENERIC_TYPE)c) : super.addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific implementation of containsAll. This implementation iterates over all elements and checks all elements are present in the other collection.
|
||||
* @param the collection that should be checked if it contains all elements.
|
||||
* @return true if all elements were found in the collection
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
public boolean containsAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
Objects.requireNonNull(c);
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();)
|
||||
if(!contains(iter.NEXT()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation iterates over the elements of the collection and checks if they are stored in this collection
|
||||
* @param c the elements that should be checked for
|
||||
* @return true if any element is in this collection
|
||||
* @deprecated if this is a primitive collection
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAny(Collection<?> c) {
|
||||
Objects.requireNonNull(c);
|
||||
for(Object e : c)
|
||||
if(contains(e))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation iterates over the elements of the collection and checks if they are stored in this collection.
|
||||
* @param c the elements that should be checked for
|
||||
* @return true if any element is in this collection
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
public boolean containsAny(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
Objects.requireNonNull(c);
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();)
|
||||
if(contains(iter.NEXT()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean remove(Object e) { return COLLECTION.super.remove(e); }
|
||||
|
||||
/**
|
||||
* A Type-Specific implementation of remove. This implementation iterates over the elements until it finds the element that is searched for or it runs out of elements.
|
||||
* It stops after finding the first element
|
||||
* @param e the element that is searched for
|
||||
* @return true if the element was found and removed.
|
||||
*/
|
||||
@Override
|
||||
public boolean REMOVE_KEY(KEY_TYPE e) {
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) {
|
||||
if(KEY_EQUALS(iter.NEXT(), e)) {
|
||||
iter.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific implementation of removeAll. This Implementation iterates over all elements and removes them as they were found in the other collection.
|
||||
* @param c the elements that should be deleted
|
||||
* @return true if the collection was modified.
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
Objects.requireNonNull(c);
|
||||
boolean modified = false;
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) {
|
||||
if(c.contains(iter.NEXT())) {
|
||||
iter.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific implementation of retainAll. This Implementation iterates over all elements and removes them as they were not found in the other collection.
|
||||
* @param c the elements that should be kept
|
||||
* @return true if the collection was modified.
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
Objects.requireNonNull(c);
|
||||
if(c.isEmpty()) {
|
||||
boolean modified = !isEmpty();
|
||||
clear();
|
||||
return modified;
|
||||
}
|
||||
boolean modified = false;
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) {
|
||||
if(!c.contains(iter.NEXT())) {
|
||||
iter.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific implementation of toArray that links to {@link #TO_ARRAY(KEY_TYPE[])} with a newly created array.
|
||||
* @return an array containing all of the elements in this collection
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY() {
|
||||
return TO_ARRAY(new KEY_TYPE[size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific implementation of toArray. This implementation iterates over all elements and unwraps them into primitive type.
|
||||
* @param a array that the elements should be injected to. If null or to small a new array with the right size is created
|
||||
* @return an array containing all of the elements in this collection
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
|
||||
if(a == null || a.length < size()) a = new KEY_TYPE[size()];
|
||||
ITERATORS.unwrap(a, iterator());
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package speiger.src.collections.PACKAGE.collections;
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
|
||||
/**
|
||||
* A Type-Specific {@link ObjectBidirectionalIterator} to reduce (un)boxing
|
||||
*/
|
||||
public interface BI_ITERATOR KEY_GENERIC_TYPE extends ITERATOR KEY_GENERIC_TYPE, ObjectBidirectionalIterator<CLASS_TYPE>
|
||||
#else
|
||||
/**
|
||||
* This is a basically a {@link ListIterator} without the index functions.
|
||||
* Allowing to have a simple Bidirectional Iterator without having to keep track of the Iteration index.
|
||||
*/
|
||||
public interface BI_ITERATOR KEY_GENERIC_TYPE extends ITERATOR KEY_GENERIC_TYPE
|
||||
#endif
|
||||
{
|
||||
/**
|
||||
* Returns true if the Iterator has a Previous element
|
||||
* @return true if the Iterator has a Previouse element
|
||||
*/
|
||||
public boolean hasPrevious();
|
||||
|
||||
/**
|
||||
* Returns the Previous element of the iterator.
|
||||
* @return the Previous element of the iterator.
|
||||
* @throws NoSuchElementException if the iteration has no more elements
|
||||
*/
|
||||
public KEY_TYPE PREVIOUS();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE previous() {
|
||||
return KEY_TO_OBJ(PREVIOUS());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
default int skip(int amount)
|
||||
{
|
||||
return ITERATOR.super.skip(amount);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Reverses the Given amount of elements if possible. A Optimization function to reverse elements faster if the implementation allows it.
|
||||
* @param amount the amount of elements that should be reversed
|
||||
* @return the amount of elements that were reversed
|
||||
*/
|
||||
public default int back(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Can't go forward");
|
||||
int i = 0;
|
||||
for(;i<amount && hasPrevious();previous(),i++);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
package speiger.src.collections.PACKAGE.collections;
|
||||
|
||||
import java.util.Collection;
|
||||
#if PRIMITIVES
|
||||
import java.util.Objects;
|
||||
import java.util.function.JAVA_PREDICATE;
|
||||
import java.util.function.Predicate;
|
||||
#endif
|
||||
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific {@link Collection} that reduces (un)boxing
|
||||
*/
|
||||
public interface COLLECTION KEY_GENERIC_TYPE extends Collection<CLASS_TYPE>, ITERABLE KEY_GENERIC_TYPE
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific add function to reduce (un)boxing
|
||||
* @see Collection#add(Object)
|
||||
* @return true if the element was added to the collection
|
||||
*/
|
||||
public boolean add(KEY_TYPE o);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific addAll function to reduce (un)boxing
|
||||
* @see Collection#addAll(Collection)
|
||||
* @return true if elements were added into the collection
|
||||
*/
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific contains function to reduce (un)boxing
|
||||
* @see Collection#contains(Object)
|
||||
* @return true if the element is found in the collection
|
||||
*/
|
||||
public boolean contains(KEY_TYPE o);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific containsAll function to reduce (un)boxing
|
||||
* @see Collection#containsAll(Object)
|
||||
* @return true if all the element is found in the collection
|
||||
*/
|
||||
public boolean containsAll(COLLECTION KEY_GENERIC_TYPE c);
|
||||
|
||||
/**
|
||||
* A Type-Specific containsAny function to reduce (un)boxing
|
||||
* @see #containsAny(Collection)
|
||||
* @return true if any element was found
|
||||
*/
|
||||
public boolean containsAny(COLLECTION KEY_GENERIC_TYPE c);
|
||||
|
||||
/**
|
||||
* Returns true if any element of the Collection is found in the provided collection.
|
||||
* A Small Optimization function to find out of any element is present when comparing collections and not all of them.
|
||||
* @return true if any element was found.
|
||||
*/
|
||||
@Primitive
|
||||
public boolean containsAny(Collection<?> c);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific remove function that reduces (un)boxing.
|
||||
* @return true if the element was removed
|
||||
* @see Collection#remove(Object)
|
||||
*/
|
||||
public boolean REMOVE_KEY(KEY_TYPE o);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific removeAll function that reduces (un)boxing.
|
||||
* @return true if any element was removed
|
||||
* @see Collection#removeAll(Collection)
|
||||
*/
|
||||
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c);
|
||||
|
||||
/**
|
||||
* A Type-Specific retainAll function that reduces (un)boxing.
|
||||
* @return true if any element was removed
|
||||
* @see Collection#retainAll(Collection)
|
||||
*/
|
||||
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific toArray function that delegates to {@link #TO_ARRAY(KEY_TYPE[])} with a newly created array.
|
||||
* @return an array containing all of the elements in this collection
|
||||
* @see Collection#toArray()
|
||||
*/
|
||||
public KEY_TYPE[] TO_ARRAY();
|
||||
|
||||
/**
|
||||
* A Type-Specific toArray function that reduces (un)boxing.
|
||||
* @param a array that the elements should be injected to. If null or to small a new array with the right size is created
|
||||
* @return an array containing all of the elements in this collection
|
||||
* @see Collection#toArray(Object[])
|
||||
*/
|
||||
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a);
|
||||
|
||||
#if PRIMITIVES
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean removeIf(Predicate<? super CLASS_TYPE> filter) {
|
||||
Objects.requireNonNull(filter);
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
return remIf(v -> filter.test(KEY_TO_OBJ(SanityChecks.SANITY_CAST(v))));
|
||||
#else
|
||||
return remIf(v -> filter.test(KEY_TO_OBJ(v)));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific removeIf function to reduce (un)boxing.
|
||||
* <p>Removes elements that were selected by the filter
|
||||
* @see Collection#removeIf(Predicate)
|
||||
* @param filter Filters the elements that should be removed
|
||||
* @throws NullPointerException if filter is null
|
||||
*/
|
||||
public default boolean remIf(JAVA_PREDICATE filter) {
|
||||
Objects.requireNonNull(filter);
|
||||
boolean removed = false;
|
||||
final ITERATOR each = iterator();
|
||||
while (each.hasNext()) {
|
||||
if (filter.test(each.NEXT())) {
|
||||
each.remove();
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
#endif
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean add(CLASS_TYPE o) { return add(OBJ_TO_KEY(o)); }
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean contains(Object o) { return o != null && contains(CLASS_TO_KEY(o)); }
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean remove(Object o) { return o != null && REMOVE_KEY(CLASS_TO_KEY(o)); }
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Returns a Type-Specific Iterator to reduce (un)boxing
|
||||
* @return a iterator of the collection
|
||||
* @see Collection#iterator()
|
||||
*/
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package speiger.src.collections.PACKAGE.collections;
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A Type-Specific {@link Iterable} that reduces (un)boxing
|
||||
*/
|
||||
public interface ITERABLE KEY_GENERIC_TYPE extends Iterable<CLASS_TYPE>
|
||||
{
|
||||
/**
|
||||
* Returns an iterator over elements of type {@code T}.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
@Override
|
||||
ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
#if !TYPE_OBJECT
|
||||
|
||||
/**
|
||||
* A Type Specific foreach function that reduces (un)boxing
|
||||
*
|
||||
* @implSpec
|
||||
* <p>The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* iterator().forEachRemaining(action);
|
||||
* }</pre>
|
||||
*
|
||||
* @param action The action to be performed for each element
|
||||
* @throws NullPointerException if the specified action is null
|
||||
* @see Iterable#forEach(Consumer)
|
||||
*/
|
||||
default void forEach(CONSUMER action) {
|
||||
Objects.requireNonNull(action);
|
||||
iterator().forEachRemaining(action);
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
default void forEach(Consumer<? super CLASS_TYPE> action) {
|
||||
Objects.requireNonNull(action);
|
||||
iterator().forEachRemaining(action);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package speiger.src.collections.PACKAGE.collections;
|
||||
|
||||
import java.util.Iterator;
|
||||
#if !TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A Type-Specific {@link Iterator} that reduces (un)boxing
|
||||
*/
|
||||
public interface ITERATOR KEY_GENERIC_TYPE extends Iterator<CLASS_TYPE>
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* Returns the next element in the iteration.
|
||||
*
|
||||
* @return the next element in the iteration
|
||||
* @throws NoSuchElementException if the iteration has no more elements
|
||||
* @see Iterator#next()
|
||||
*/
|
||||
public KEY_TYPE NEXT();
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE next() { return KEY_TO_OBJ(NEXT()); }
|
||||
|
||||
/**
|
||||
* Performs the given action for each remaining element until all elements
|
||||
* have been processed or the action throws an exception. Actions are
|
||||
* performed in the order of iteration, if that order is specified.
|
||||
* Exceptions thrown by the action are relayed to the caller.
|
||||
*
|
||||
* @implSpec
|
||||
* <p>The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* while (hasNext()) action.accept(NEXT());
|
||||
* }</pre>
|
||||
*
|
||||
* @param action The action to be performed for each element
|
||||
* @throws NullPointerException if the specified action is null
|
||||
* @see Iterator#forEachRemaining(Consumer)
|
||||
*/
|
||||
public default void forEachRemaining(CONSUMER action) {
|
||||
Objects.requireNonNull(action);
|
||||
while(hasNext()) { action.accept(NEXT()); }
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
default void forEachRemaining(Consumer<? super CLASS_TYPE> action) {
|
||||
Objects.requireNonNull(action);
|
||||
forEachRemaining(action::accept);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Skips the Given amount of elements if possible. A Optimization function to skip elements faster if the implementation allows it.
|
||||
* @param amount the amount of elements that should be skipped
|
||||
* @return the amount of elements that were skipped
|
||||
*/
|
||||
default int skip(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int i = 0;
|
||||
for(;i<amount && hasNext();NEXT(), i++);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package speiger.src.collections.PACKAGE.collections;
|
||||
|
||||
import speiger.src.collections.utils.Stack;
|
||||
|
||||
/**
|
||||
* A Type-Specific {@link Stack} that reduces (un)boxing
|
||||
*/
|
||||
public interface STACK extends Stack<CLASS_TYPE>
|
||||
{
|
||||
/**
|
||||
* Inserts a given Object on top of the stack
|
||||
* @param e the Object to insert
|
||||
* @see Stack#push(Object)
|
||||
*/
|
||||
public void PUSH(KEY_TYPE e);
|
||||
|
||||
/**
|
||||
* Removes the Object on top of the stack.
|
||||
* @return the element that is on top of the stack
|
||||
* @throws ArrayIndexOutOfBoundsException if the stack is empty
|
||||
* @see Stack#pop()
|
||||
*/
|
||||
public KEY_TYPE POP();
|
||||
|
||||
/**
|
||||
* Provides the Object on top of the stack
|
||||
* @return the element that is on top of the stack
|
||||
* @throws ArrayIndexOutOfBoundsException if the stack is empty
|
||||
* @see Stack#top()
|
||||
*/
|
||||
public default KEY_TYPE TOP() {
|
||||
return PEEK(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Selected Object from the stack.
|
||||
* Top to bottom
|
||||
* @param index of the element that should be provided
|
||||
* @return the element that was requested
|
||||
* @throws ArrayIndexOutOfBoundsException if the index is out of bounds
|
||||
* @see Stack#peek(int)
|
||||
*/
|
||||
public KEY_TYPE PEEK(int index);
|
||||
|
||||
#if !OBJECT_TYPE
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default void push(CLASS_TYPE e) { PUSH(OBJ_TO_KEY(e)); }
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE pop() { return KEY_TO_OBJ(POP()); }
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE top() {
|
||||
return peek(size() - 1);
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE peek(int index) { return KEY_TO_OBJ(PEEK(index)); }
|
||||
#endif
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package speiger.src.collections.PACKAGE.functions;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Type-Specific Class for Comparator to reduce (un)boxing
|
||||
*/
|
||||
public interface COMPARATOR extends Comparator<CLASS_TYPE>
|
||||
{
|
||||
/**
|
||||
* Type-Specific compare function to reduce (un)boxing
|
||||
* @see Comparator#compare(Object, Object)
|
||||
*/
|
||||
int compare(KEY_TYPE o1, KEY_TYPE o2);
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default int compare(CLASS_TYPE o1, CLASS_TYPE o2) {
|
||||
return compare(OBJ_TO_KEY(o1), OBJ_TO_KEY(o2));
|
||||
}
|
||||
|
||||
/**
|
||||
* A Wrapper function to convert a Non-Type-Specific Comparator to a Type-Specific-Comparator
|
||||
* @param c comparator to convert
|
||||
* @return the wrapper of the comparator
|
||||
* @throws NullPointerException if the comparator is null
|
||||
*/
|
||||
public static COMPARATOR of(Comparator<CLASS_TYPE> c) {
|
||||
Objects.requireNonNull(c);
|
||||
return (K, V) -> c.compare(KEY_TO_OBJ(K), KEY_TO_OBJ(V));
|
||||
}
|
||||
|
||||
public default COMPARATOR reversed() {
|
||||
return new Reversed(this);
|
||||
}
|
||||
|
||||
static class Reversed implements COMPARATOR
|
||||
{
|
||||
COMPARATOR original;
|
||||
|
||||
public Reversed(COMPARATOR original) {
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
public int compare(KEY_TYPE o1, KEY_TYPE o2) {
|
||||
return original.compare(o2, o1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR reversed() {
|
||||
return original;
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package speiger.src.collections.PACKAGE.functions;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
/**
|
||||
* Type-Specific Consumer interface that reduces (un)boxing and allows to merge other consumer types into this interface
|
||||
*/
|
||||
@FunctionalInterface
|
||||
#if JDK_TYPE && !TYPE_BOOLEAN
|
||||
public interface CONSUMER extends Consumer<CLASS_TYPE>, JAVA_CONSUMER
|
||||
#else
|
||||
public interface CONSUMER extends Consumer<CLASS_TYPE>
|
||||
#endif
|
||||
{
|
||||
/**
|
||||
* Type-Specific function to reduce (un)boxing.
|
||||
* Performs this operation on the given argument.
|
||||
*
|
||||
* @param t the input argument
|
||||
*/
|
||||
void accept(KEY_TYPE t);
|
||||
|
||||
public default CONSUMER andThen(CONSUMER after) {
|
||||
Objects.requireNonNull(after);
|
||||
return T -> {accept(T); after.accept(T);};
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default void accept(CLASS_TYPE t) { accept(OBJ_TO_KEY(t)); }
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default CONSUMER andThen(Consumer<? super CLASS_TYPE> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return T -> {accept(T); after.accept(KEY_TO_OBJ(T));};
|
||||
}
|
||||
#if JDK_TYPE && PRIMITIVES
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default CONSUMER andThen(JAVA_CONSUMER after) {
|
||||
Objects.requireNonNull(after);
|
||||
return T -> {accept(T); after.accept(T);};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package speiger.src.collections.PACKAGE.functions.consumer;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public interface BI_CONSUMER KEY_VALUE_GENERIC_TYPE extends BiConsumer<CLASS_TYPE, CLASS_VALUE_TYPE>
|
||||
{
|
||||
void accept(KEY_TYPE k, VALUE_TYPE v);
|
||||
|
||||
public default BI_CONSUMER KEY_VALUE_GENERIC_TYPE andThen(BI_CONSUMER KEY_VALUE_GENERIC_TYPE after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (K, V) -> {accept(K, V); after.accept(K, V);};
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default void accept(CLASS_TYPE k, CLASS_VALUE_TYPE v) { accept(OBJ_TO_KEY(k), OBJ_TO_VALUE(v)); }
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default BI_CONSUMER KEY_VALUE_GENERIC_TYPE andThen(BiConsumer<? super CLASS_TYPE, ? super CLASS_VALUE_TYPE> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (K, V) -> {accept(K, V); after.accept(KEY_TO_OBJ(K), VALUE_TO_OBJ(V));};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package speiger.src.collections.PACKAGE.functions.function;
|
||||
|
||||
#if JDK_FUNCTION && VALUE_BOOLEAN
|
||||
import java.util.Objects;
|
||||
#endif
|
||||
|
||||
@FunctionalInterface
|
||||
#if JDK_FUNCTION
|
||||
public interface FUNCTION KEY_VALUE_GENERIC_TYPE extends JAVA_FUNCTION KEY_VALUE_GENERIC_TYPE
|
||||
#else
|
||||
public interface FUNCTION KEY_VALUE_GENERIC_TYPE
|
||||
#endif
|
||||
{
|
||||
public VALUE_TYPE GET_VALUE(KEY_TYPE k);
|
||||
#if JDK_FUNCTION
|
||||
#if VALUE_BOOLEAN
|
||||
|
||||
@Override
|
||||
public default VALUE_TYPE test(KEY_TYPE k) { return GET_VALUE(k); }
|
||||
|
||||
public default FUNCTION KEY_VALUE_GENERIC_TYPE andType(FUNCTION KEY_VALUE_GENERIC_TYPE other) {
|
||||
Objects.requireNonNull(other);
|
||||
return T -> GET_VALUE(T) && other.GET_VALUE(T);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default FUNCTION KEY_VALUE_GENERIC_TYPE and(JAVA_FUNCTION KEY_VALUE_SUPER_GENERIC_TYPE other) {
|
||||
Objects.requireNonNull(other);
|
||||
return T -> GET_VALUE(T) && other.test(T);
|
||||
}
|
||||
|
||||
@Override
|
||||
public default FUNCTION KEY_VALUE_GENERIC_TYPE negate() {
|
||||
return T -> !GET_VALUE(T);
|
||||
}
|
||||
|
||||
public default FUNCTION KEY_VALUE_GENERIC_TYPE orType(FUNCTION KEY_VALUE_GENERIC_TYPE other) {
|
||||
Objects.requireNonNull(other);
|
||||
return T -> GET_VALUE(T) || other.GET_VALUE(T);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default FUNCTION KEY_VALUE_GENERIC_TYPE or(JAVA_FUNCTION KEY_VALUE_SUPER_GENERIC_TYPE other) {
|
||||
Objects.requireNonNull(other);
|
||||
return T -> GET_VALUE(T) || other.test(T);
|
||||
}
|
||||
#else if VALUE_OBJECT
|
||||
|
||||
@Override
|
||||
public default VALUE_TYPE apply(KEY_TYPE k) { return GET_VALUE(k); }
|
||||
#else
|
||||
|
||||
@Override
|
||||
public default VALUE_TYPE APPLY_VALUE(KEY_TYPE k) { return GET_VALUE(k); }
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package speiger.src.collections.PACKAGE.functions.function;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
#if !SAME_TYPE || TYPE_BOOLEAN || !JDK_TYPE
|
||||
public interface UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE extends BiFunction<CLASS_TYPE, CLASS_VALUE_TYPE, CLASS_VALUE_TYPE>
|
||||
#else
|
||||
#if SAME_TYPE && TYPE_OBJECT
|
||||
public interface UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE extends BiFunction<CLASS_TYPE, CLASS_VALUE_TYPE, CLASS_VALUE_TYPE>
|
||||
#else
|
||||
public interface UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE extends BiFunction<CLASS_TYPE, CLASS_VALUE_TYPE, CLASS_VALUE_TYPE>, JAVA_BINARY_OPERATOR
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
#else if SAME_TYPE && !TYPE_OBJECT && JDK_TYPE && !TYPE_BOOLEAN
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE apply(CLASS_TYPE k, CLASS_VALUE_TYPE v) { return VALUE_TO_OBJ(APPLY_VALUE(OBJ_TO_KEY(k), OBJ_TO_VALUE(v))); }
|
||||
#else
|
||||
public VALUE_TYPE APPLY_VALUE(KEY_TYPE k, VALUE_TYPE v);
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE apply(CLASS_TYPE k, CLASS_VALUE_TYPE v) { return VALUE_TO_OBJ(APPLY_VALUE(OBJ_TO_KEY(k), OBJ_TO_VALUE(v))); }
|
||||
#endif
|
||||
}
|
||||
+433
@@ -0,0 +1,433 @@
|
||||
package speiger.src.collections.PACKAGE.lists;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
|
||||
/**
|
||||
* Abstract implementation of the {@link LIST} interface.
|
||||
*/
|
||||
public abstract class ABSTRACT_LIST KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific implementation of add function that delegates to {@link #add(int, KEY_TYPE)}
|
||||
*/
|
||||
@Override
|
||||
public boolean add(KEY_TYPE e) {
|
||||
add(size(), e);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void add(int index, CLASS_TYPE element) {
|
||||
add(index, OBJ_TO_KEY(element));
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific implementation that iterates over the elements and adds them.
|
||||
* @param c the elements that wants to be added
|
||||
* @return true if the list was modified
|
||||
*/
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
boolean modified = false;
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific implementation that iterates over the elements and adds them.
|
||||
* @param c the elements that wants to be added
|
||||
* @return true if the list was modified
|
||||
*/
|
||||
@Override
|
||||
public boolean addAll(LIST KEY_GENERIC_TYPE c) {
|
||||
boolean modified = false;
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = c.iterator();iter.hasNext();modified |= add(iter.NEXT()));
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* The IndexOf implementation iterates over all elements and compares them to the search value.
|
||||
* @param e the value that the index is searched for.
|
||||
* @return index of the value that was searched for. -1 if not found
|
||||
* @deprecated it is highly suggested not to use this with Primitives because of boxing. But it is still supported because of ObjectComparason that are custom objects and allow to find the contents.
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public int indexOf(Object o) {
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
#if TYPE_OBJECT
|
||||
if(o == null) {
|
||||
while(iter.hasNext()) {
|
||||
if(iter.NEXT() == null)
|
||||
return iter.previousIndex();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if(o == null) return -1;
|
||||
#endif
|
||||
while(iter.hasNext()) {
|
||||
if(EQUALS_KEY_TYPE(iter.NEXT(), o))
|
||||
return iter.previousIndex();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The lastIndexOf implementation iterates over all elements and compares them to the search value.
|
||||
* @param e the value that the index is searched for.
|
||||
* @return the last index of the value that was searched for. -1 if not found
|
||||
* @deprecated it is highly suggested not to use this with Primitives because of boxing. But it is still supported because of ObjectComparason that are custom objects and allow to find the contents.
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public int lastIndexOf(Object o) {
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator(size());
|
||||
#if TYPE_OBJECT
|
||||
if(o == null) {
|
||||
while(iter.hasPrevious()) {
|
||||
if(iter.PREVIOUS() == null)
|
||||
return iter.nextIndex();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if(o == null) return -1;
|
||||
#endif
|
||||
while(iter.hasPrevious()) {
|
||||
if(EQUALS_KEY_TYPE(iter.PREVIOUS(), o))
|
||||
return iter.nextIndex();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* The indexOf implementation iterates over all elements and compares them to the search value.
|
||||
* @param e the value that the index is searched for.
|
||||
* @return index of the value that was searched for. -1 if not found
|
||||
*/
|
||||
@Override
|
||||
public int indexOf(KEY_TYPE e) {
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
while(iter.hasNext()) {
|
||||
if(KEY_EQUALS(iter.NEXT(), e))
|
||||
return iter.previousIndex();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The lastIndexOf implementation iterates over all elements and compares them to the search value.
|
||||
* @param e the value that the index is searched for.
|
||||
* @return the last index of the value that was searched for. -1 if not found
|
||||
*/
|
||||
@Override
|
||||
public int lastIndexOf(KEY_TYPE e) {
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator(size());
|
||||
while(iter.hasPrevious()) {
|
||||
if(KEY_EQUALS(iter.PREVIOUS(), e))
|
||||
return iter.nextIndex();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Compares if the list are the same.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this)
|
||||
return true;
|
||||
if (!(o instanceof List))
|
||||
return false;
|
||||
List<?> l = (List<?>)o;
|
||||
if(l.size() != size()) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(l instanceof LIST)
|
||||
{
|
||||
LIST_ITERATOR e1 = listIterator();
|
||||
LIST_ITERATOR e2 = ((LIST)l).listIterator();
|
||||
while (e1.hasNext() && e2.hasNext()) {
|
||||
if(!(KEY_EQUALS(e1.NEXT(), e2.NEXT())))
|
||||
return false;
|
||||
}
|
||||
return !(e1.hasNext() || e2.hasNext());
|
||||
}
|
||||
#endif
|
||||
ListIterator<CLASS_TYPE> e1 = listIterator();
|
||||
ListIterator<?> e2 = l.listIterator();
|
||||
while (e1.hasNext() && e2.hasNext()) {
|
||||
if(!Objects.equals(e1.next(), e2.next()))
|
||||
return false;
|
||||
}
|
||||
return !(e1.hasNext() || e2.hasNext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the hashcode based on the values stored in the list.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 1;
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE i = listIterator();
|
||||
while(i.hasNext())
|
||||
#if TYPE_OBJECT
|
||||
hashCode = 31 * hashCode + i.next().hashCode();
|
||||
#else
|
||||
hashCode = 31 * hashCode + KEY_TO_HASH(i.NEXT());
|
||||
#endif
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST KEY_GENERIC_TYPE subList(int fromIndex, int toIndex) {
|
||||
return new SUB_LIST(this, fromIndex, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return listIterator(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() {
|
||||
return listIterator(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
|
||||
return new LIST_ITER(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void size(int size) {
|
||||
while(size > size()) add(EMPTY_KEY_VALUE);
|
||||
while(size < size()) REMOVE(size() - 1);
|
||||
}
|
||||
|
||||
private class SUB_LIST extends ABSTRACT_LIST KEY_GENERIC_TYPE {
|
||||
ABSTRACT_LIST KEY_GENERIC_TYPE l;
|
||||
int offset;
|
||||
int size;
|
||||
|
||||
SUB_LIST(ABSTRACT_LIST KEY_GENERIC_TYPE l, int from, int to) {
|
||||
if (from < 0) throw new IndexOutOfBoundsException("fromIndex = " + from);
|
||||
else if (to > l.size()) throw new IndexOutOfBoundsException("toIndex = " + to);
|
||||
else if (from > to) throw new IllegalArgumentException("fromIndex(" + from + ") > toIndex(" + to + ")");
|
||||
this.l = l;
|
||||
offset = from;
|
||||
size = to - from;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, KEY_TYPE e) {
|
||||
checkAddRange(index);
|
||||
l.add(index+offset, e);
|
||||
size++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) {
|
||||
checkAddRange(index);
|
||||
int size = c.size();
|
||||
if(size == 0) return false;
|
||||
l.addAll(index + offset, l);
|
||||
offset += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) {
|
||||
checkAddRange(index);
|
||||
int size = c.size();
|
||||
if(size == 0) return false;
|
||||
l.addAll(index + offset, l);
|
||||
offset += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) {
|
||||
checkAddRange(index);
|
||||
int size = c.size();
|
||||
if(size == 0) return false;
|
||||
l.addAll(index + offset, l);
|
||||
offset += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addElements(int from, KEY_TYPE[] a, int offset, int length) {
|
||||
checkRange(from);
|
||||
l.addElements(from + this.offset, a, offset, length);
|
||||
size += length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) {
|
||||
checkRange(from);
|
||||
return l.getElements(from + this.offset, a, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeElements(int from, int to) {
|
||||
checkRange(from);
|
||||
checkRange(to);
|
||||
l.removeElements(from + offset, to + offset);
|
||||
size -= to - from;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public <K> K[] extractElements(int from, int to, Class<K> clz) {
|
||||
checkRange(from);
|
||||
checkRange(to);
|
||||
K[] a = l.extractElements(from + offset, to + offset, clz);
|
||||
size -= to - from;
|
||||
return a;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public KEY_TYPE[] extractElements(int from, int to) {
|
||||
checkRange(from);
|
||||
checkRange(to);
|
||||
KEY_TYPE[] a = l.extractElements(from + offset, to + offset);
|
||||
size -= to - from;
|
||||
return a;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public KEY_TYPE GET_KEY(int index) {
|
||||
checkRange(index);
|
||||
return l.GET_KEY(index + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE set(int index, KEY_TYPE e) {
|
||||
checkRange(index);
|
||||
return l.set(index + offset, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE REMOVE(int index) {
|
||||
checkRange(index);
|
||||
size--;
|
||||
return l.REMOVE(index + offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private void checkRange(int index) {
|
||||
if (index < 0 || index >= size)
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
}
|
||||
|
||||
private void checkAddRange(int index) {
|
||||
if (index < 0 || index > size)
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
}
|
||||
}
|
||||
|
||||
private class LIST_ITER implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
int index;
|
||||
int lastReturned = -1;
|
||||
|
||||
LIST_ITER(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
lastReturned = index;
|
||||
return GET_KEY(index++);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return index > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
lastReturned = index;
|
||||
return GET_KEY(index--);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return index-1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(lastReturned == -1)
|
||||
throw new IllegalStateException();
|
||||
ABSTRACT_LIST.this.REMOVE(lastReturned);
|
||||
if(lastReturned < index)
|
||||
index--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(KEY_TYPE e) {
|
||||
if(lastReturned == -1)
|
||||
throw new IllegalStateException();
|
||||
ABSTRACT_LIST.this.set(lastReturned, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) {
|
||||
if(lastReturned == -1)
|
||||
throw new IllegalStateException();
|
||||
ABSTRACT_LIST.this.add(index++, e);
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skip(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int steps = Math.min(amount, (size() - 1) - index);
|
||||
index += steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int back(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int steps = Math.min(amount, index);
|
||||
index -= steps;
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,909 @@
|
||||
package speiger.src.collections.PACKAGE.lists;
|
||||
|
||||
import java.util.Arrays;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#endif
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.function.Consumer;
|
||||
#endif
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
#if PRIMITIVES
|
||||
import java.util.function.JAVA_PREDICATE;
|
||||
import java.util.function.JAVA_UNARY_OPERATOR;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.collections.STACK;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.ARRAYS;
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#if TYPE_OBJECT
|
||||
import speiger.src.collections.utils.Stack;
|
||||
#else
|
||||
import speiger.src.collections.objects.utils.ObjectArrays;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.IARRAY;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
#if TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific Array-based implementation of list that is written to reduce (un)boxing
|
||||
*
|
||||
* <p>This implementation is optimized to improve how data is processed with interfaces like {@link IARRAY}, {@link Stack}
|
||||
* and with optimized functions that use type-specific implementations for primitives and optimized logic for bulkactions.
|
||||
*/
|
||||
public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE implements IARRAY<KEY_TYPE>, Stack<KEY_TYPE>
|
||||
#else
|
||||
/**
|
||||
* A Type-Specific Array-based implementation of list that is written to reduce (un)boxing
|
||||
*
|
||||
* <p>This implementation is optimized to improve how data is processed with interfaces like {@link IARRAY}, {@link STACK}
|
||||
* and with optimized functions that use type-specific implementations for primitives and optimized logic for bulkactions.
|
||||
*/
|
||||
public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE implements IARRAY, STACK
|
||||
#endif
|
||||
{
|
||||
static final int DEFAULT_ARRAY_SIZE = 10;
|
||||
|
||||
/** The backing array */
|
||||
protected transient KEY_TYPE[] data;
|
||||
/** The current size of the elements stored in the backing array */
|
||||
protected int size = 0;
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList with a Empty array.
|
||||
*/
|
||||
public ARRAY_LIST() {
|
||||
data = EMPTY_KEY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList with the specific requested size
|
||||
*/
|
||||
public ARRAY_LIST(int size) {
|
||||
data = NEW_KEY_ARRAY(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList a copy with the contents of the Collection.
|
||||
*/
|
||||
public ARRAY_LIST(Collection<? extends CLASS_TYPE> c) {
|
||||
this(c.size());
|
||||
size = ITERATORS.unwrap(data, c.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList a copy with the contents of the Collection.
|
||||
*/
|
||||
public ARRAY_LIST(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
this(c.size());
|
||||
size = ITERATORS.unwrap(data, c.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList a copy with the contents of the List.
|
||||
*/
|
||||
public ARRAY_LIST(LIST KEY_GENERIC_TYPE l) {
|
||||
this(l.size());
|
||||
size = l.size();
|
||||
l.getElements(0, data, 0, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList with a Copy of the array
|
||||
*/
|
||||
public ARRAY_LIST(KEY_TYPE[] a) {
|
||||
this(a, 0, a.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList with a Copy of the array with a custom length
|
||||
*/
|
||||
public ARRAY_LIST(KEY_TYPE[] a, int length) {
|
||||
this(a, 0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ArrayList with a Copy of the array with in the custom range.
|
||||
*/
|
||||
public ARRAY_LIST(KEY_TYPE[] a, int offset, int length) {
|
||||
this(length);
|
||||
SanityChecks.checkArrayCapacity(a.length, offset, length);
|
||||
System.arraycopy(a, offset, data, 0, length);
|
||||
size = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped arraylist that uses the array as backing array
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES ARRAY_LIST KEY_GENERIC_TYPE wrap(KEY_TYPE[] a) {
|
||||
return wrap(a, a.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wrapped arraylist that uses the array as backing array and a custom fillsize
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES ARRAY_LIST KEY_GENERIC_TYPE wrap(KEY_TYPE[] a, int length) {
|
||||
SanityChecks.checkArrayCapacity(a.length, 0, length);
|
||||
ARRAY_LIST KEY_GENERIC_TYPE list = new ARRAY_LISTBRACES();
|
||||
list.data = a;
|
||||
list.size = length;
|
||||
return list;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
/**
|
||||
* Creates a new ArrayList with a EmptyObject array of the Type requested
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES ARRAY_LIST KEY_GENERIC_TYPE of(Class<KEY_TYPE> c) {
|
||||
ARRAY_LIST KEY_GENERIC_TYPE list = new ARRAY_LISTBRACES();
|
||||
list.data = (KEY_TYPE[])ObjectArrays.newArray(c.getClass().getComponentType(), 0);
|
||||
return list;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Appends the specified element to the end of this list.
|
||||
*
|
||||
* @param e element to be appended to this list
|
||||
* @return <tt>true</tt> (as specified by {@link Collection#add})
|
||||
*/
|
||||
@Override
|
||||
public boolean add(KEY_TYPE e) {
|
||||
grow(size + 1);
|
||||
data[size++] = e;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified element to the end of this Stack.
|
||||
* @param e element to be appended to this Stack
|
||||
*/
|
||||
@Override
|
||||
public void PUSH(KEY_TYPE e) {
|
||||
add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified element to the index of the list
|
||||
* @param index the index where to append the element to
|
||||
* @param e the element to append to the list
|
||||
* @throws IndexOutOfBoundsException if index is outside of the lists range
|
||||
*/
|
||||
@Override
|
||||
public void add(int index, KEY_TYPE e) {
|
||||
checkAddRange(index);
|
||||
grow(size + 1);
|
||||
if(index != size) System.arraycopy(data, index, data, index+1, size - index);
|
||||
data[index] = e;
|
||||
size++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified elements to the index of the list.
|
||||
* This function may delegate to more appropiate function if nessesary
|
||||
* @param index the index where to append the elements to
|
||||
* @param e the elements to append to the list
|
||||
* @throws IndexOutOfBoundsException if index is outside of the lists range
|
||||
* @deprecated if type is primitive
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) {
|
||||
if(c instanceof COLLECTION) return addAll(index, (COLLECTION KEY_GENERIC_TYPE)c);
|
||||
int add = c.size();
|
||||
if(add <= 0) return false;
|
||||
grow(size + add);
|
||||
if(index != size) System.arraycopy(data, index, data, index+add, size - index);
|
||||
size+=add;
|
||||
Iterator<? extends CLASS_TYPE> iter = c.iterator();
|
||||
while(add != 0) data[index++] = OBJ_TO_KEY(iter.next());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified elements to the index of the list.
|
||||
* This function may delegate to more appropiate function if nessesary
|
||||
* @param index the index where to append the elements to
|
||||
* @param e the elements to append to the list
|
||||
* @throws IndexOutOfBoundsException if index is outside of the lists range
|
||||
* @deprecated if type is primitive
|
||||
*/
|
||||
@Override
|
||||
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) {
|
||||
if(c instanceof LIST) return addAll(index, (LIST KEY_GENERIC_TYPE)c);
|
||||
int add = c.size();
|
||||
if(add <= 0) return false;
|
||||
grow(size + add);
|
||||
if(index != size) System.arraycopy(data, index, data, index+add, size - index);
|
||||
size+=add;
|
||||
ITERATOR KEY_GENERIC_TYPE iter = c.iterator();
|
||||
while(add-- != 0) data[index++] = iter.NEXT();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified elements to the index of the list.
|
||||
* @param index the index where to append the elements to
|
||||
* @param e the elements to append to the list
|
||||
* @throws IndexOutOfBoundsException if index is outside of the lists range
|
||||
* @deprecated if type is primitive
|
||||
*/
|
||||
@Override
|
||||
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) {
|
||||
int add = c.size();
|
||||
if(add <= 0) return false;
|
||||
checkAddRange(index);
|
||||
grow(size + add);
|
||||
if(index != size) System.arraycopy(data, index, data, index+add, size - index);
|
||||
size+=add;
|
||||
c.getElements(0, data, index, c.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified array elements to the index of the list.
|
||||
* @param from the index where to append the elements to
|
||||
* @param a the elements to append to the list
|
||||
* @param offset where to start ino the array
|
||||
* @param length the amount of elements to insert
|
||||
* @throws IndexOutOfBoundsException if index is outside of the lists range
|
||||
* @deprecated if type is primitive
|
||||
*/
|
||||
@Override
|
||||
public void addElements(int from, KEY_TYPE[] a, int offset, int length) {
|
||||
if(length <= 0) return;
|
||||
checkAddRange(from);
|
||||
grow(size + length);
|
||||
if(from != size) System.arraycopy(data, from, data, from+length, size - length);
|
||||
size+=length;
|
||||
System.arraycopy(a, offset, data, from, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to fast fetch elements from the list
|
||||
* @param from index where the list should be fetching elements from
|
||||
* @param a the array where the values should be inserted to
|
||||
* @param offset the startIndex of where the array should be written to
|
||||
* @param length the number of elements the values should be fetched from
|
||||
* @returns the inputArray
|
||||
* @throws NullPointerException if the array is null
|
||||
* @throws IndexOutOfBoundsException if from is outside of the lists range
|
||||
* @throws IllegalStateException if offset or length are smaller then 0 or exceed the array length
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) {
|
||||
SanityChecks.checkArrayCapacity(size, offset, length);
|
||||
System.arraycopy(data, from, a, offset, length);
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* a function to fast remove elements from the list.
|
||||
* @param from the start index of where the elements should be removed from (inclusive)
|
||||
* @param to the end index of where the elements should be removed to (exclusive)
|
||||
*/
|
||||
@Override
|
||||
public void removeElements(int from, int to) {
|
||||
checkRange(from);
|
||||
checkAddRange(to);
|
||||
int length = to - from;
|
||||
if(length <= 0) return;
|
||||
if(to != size) System.arraycopy(data, to, data, from, size - to);
|
||||
#if TYPE_OBJECT
|
||||
for(int i = 0;i<length;i++)
|
||||
data[i+to] = null;
|
||||
#endif
|
||||
size -= length;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
/**
|
||||
* A function to fast extract elements out of the list, this removes the elements that were fetched.
|
||||
* @param from the start index of where the elements should be fetched from (inclusive)
|
||||
* @param to the end index of where the elements should be fetched to (exclusive)
|
||||
* @param type the type of the OutputArray
|
||||
* @return a array of the elements that were fetched
|
||||
*/
|
||||
@Override
|
||||
public <K> K[] extractElements(int from, int to, Class<K> type) {
|
||||
checkRange(from);
|
||||
checkAddRange(to);
|
||||
int length = to - from;
|
||||
K[] a = ARRAYS.newArray(type, length);
|
||||
if(length <= 0) return a;
|
||||
System.arraycopy(data, from, a, 0, length);
|
||||
if(to != size) System.arraycopy(data, to, data, from, size - to);
|
||||
for(int i = 0;i<length;i++)
|
||||
data[i+to] = null;
|
||||
size -= length;
|
||||
return a;
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* A function to fast extract elements out of the list, this removes the elements that were fetched.
|
||||
* @param from the start index of where the elements should be fetched from (inclusive)
|
||||
* @param to the end index of where the elements should be fetched to (exclusive)
|
||||
* @return a array of the elements that were fetched
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE[] extractElements(int from, int to) {
|
||||
int length = to - from;
|
||||
if(length <= 0) return ARRAYS.EMPTY_ARRAY;
|
||||
KEY_TYPE[] a = new KEY_TYPE[length];
|
||||
System.arraycopy(data, from, a, 0, length);
|
||||
if(to != size) System.arraycopy(data, to, data, from, size - to);
|
||||
size -= length;
|
||||
return a;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A function to find if the Element is present in this list.
|
||||
* @param e the element that is searched for
|
||||
* @return if the element was found.
|
||||
* @deprecated if type-specific but still supported because of special edgecase Object-Comparason features
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean contains(Object o) {
|
||||
return indexOf(o) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to find the index of a given element
|
||||
* @param e the element that is searched for
|
||||
* @return the index of the element if found. (if not found then -1)
|
||||
* @deprecated if type-specific but still supported because of special edgecase Object-Comparason features
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public int indexOf(Object o) {
|
||||
#if TYPE_OBJECT
|
||||
if(o == null) {
|
||||
for(int i = 0;i<size;i++)
|
||||
if(data[i] == null) return i;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if(o == null) return -1;
|
||||
#endif
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(EQUALS_KEY_TYPE(data[i], o)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to find the last index of a given element
|
||||
* @param e the element that is searched for
|
||||
* @return the last index of the element if found. (if not found then -1)
|
||||
* @deprecated if type-specific but still supported because of special edgecase Object-Comparason features
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public int lastIndexOf(Object o) {
|
||||
#if TYPE_OBJECT
|
||||
if(o == null) {
|
||||
for(int i = size - 1;i>=0;i--)
|
||||
if(data[i] == null) return i;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if(o == null) return -1;
|
||||
#endif
|
||||
for(int i = size - 1;i>=0;i--) {
|
||||
if(EQUALS_KEY_TYPE(data[i], o)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#stableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
@Override
|
||||
public void sort(Comparator<? super CLASS_TYPE> c) {
|
||||
if(c != null) ARRAYS.stableSort(data, size, c);
|
||||
else ARRAYS.stableSort((Comparable[])data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements using a unstable sort
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#unstableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
@Override
|
||||
public void unstableSort(Comparator<? super CLASS_TYPE> c) {
|
||||
if(c != null) ARRAYS.unstableSort(data, size, c);
|
||||
else ARRAYS.unstableSort((Comparable[])data, size);
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* A Type Specific implementation of the Collection#contains function.
|
||||
* @param the element that is searched for.
|
||||
* @returns if the element was found
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
return indexOf(e) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific function to find the index of a given element
|
||||
* @param e the element that is searched for
|
||||
* @return the index of the element if found. (if not found then -1)
|
||||
*/
|
||||
@Override
|
||||
public int indexOf(KEY_TYPE e) {
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(KEY_EQUALS(data[i], e)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific function to find the last index of a given element
|
||||
* @param e the element that is searched for
|
||||
* @return the last index of the element if found. (if not found then -1)
|
||||
*/
|
||||
@Override
|
||||
public int lastIndexOf(KEY_TYPE e) {
|
||||
for(int i = size - 1;i>=0;i--) {
|
||||
if(KEY_EQUALS(data[i], e)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#stableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
@Override
|
||||
public void sort(COMPARATOR c) {
|
||||
if(c != null) ARRAYS.stableSort(data, size, c);
|
||||
else ARRAYS.stableSort(data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements using a unstable sort
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#unstableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
@Override
|
||||
public void unstableSort(COMPARATOR c) {
|
||||
if(c != null) ARRAYS.unstableSort(data, size, c);
|
||||
else ARRAYS.unstableSort(data, size);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific get function to reduce (un)boxing
|
||||
* @param index the index of the element to fetch
|
||||
* @return the value of the requested index
|
||||
* @throws IndexOutOfBoundsException if the index is out of range
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE GET_KEY(int index) {
|
||||
checkRange(index);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Selected Object from the stack.
|
||||
* Top to bottom
|
||||
* @param index of the element that should be provided
|
||||
* @return the element that was requested
|
||||
* @throws ArrayIndexOutOfBoundsException if the index is out of bounds
|
||||
* @see Stack#peek(int)
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE PEEK(int index) {
|
||||
checkRange((size() - 1) - index);
|
||||
return data[(size() - 1) - index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the Underlying Array in the Implementation
|
||||
* @return underlying Array
|
||||
* @throws ClassCastException if the return type does not match the underlying array. (Only for Object Implementations)
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE[] elements() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type Specific foreach function that reduces (un)boxing
|
||||
*
|
||||
* @implSpec
|
||||
* <p>The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* for(int i = 0;i<size;i++)
|
||||
* action.accept(data[i]);
|
||||
* }</pre>
|
||||
*
|
||||
* @param action The action to be performed for each element
|
||||
* @throws NullPointerException if the specified action is null
|
||||
* @see Iterable#forEach(Consumer)
|
||||
*/
|
||||
@Override
|
||||
public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
|
||||
Objects.requireNonNull(action);
|
||||
for(int i = 0;i<size;i++)
|
||||
action.accept(data[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Type-Specific set function to reduce (un)boxing
|
||||
* @param index the index of the element to set
|
||||
* @param e the value that should be set
|
||||
* @return the previous element
|
||||
* @throws IndexOutOfBoundsException if the index is out of range
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE set(int index, KEY_TYPE e) {
|
||||
checkRange(index);
|
||||
KEY_TYPE old = data[index];
|
||||
data[index] = e;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to replace all values in the list
|
||||
* @param o the action to replace the values
|
||||
* @throws NullPointerException if o is null
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public void replaceAll(UnaryOperator<CLASS_TYPE> o) {
|
||||
#if PRIMITIVES
|
||||
Objects.requireNonNull(o);
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(SanityChecks.SANITY_CAST(T)))));
|
||||
#else
|
||||
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(T))));
|
||||
#endif
|
||||
#else
|
||||
Objects.requireNonNull(o);
|
||||
for(int i = 0;i<size;i++)
|
||||
data[i] = OBJ_TO_KEY(o.apply(KEY_TO_OBJ(data[i])));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if PRIMITIVES
|
||||
/**
|
||||
* A Type-Specific replace function to reduce (un)boxing
|
||||
* @param o the action to replace the values
|
||||
* @throws NullPointerException if o is null
|
||||
*/
|
||||
@Override
|
||||
public void REPLACE(JAVA_UNARY_OPERATOR o) {
|
||||
for(int i = 0;i<size;i++)
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
data[i] = SanityChecks.SANITY_CAST(o.APPLY_CAST(data[i]));
|
||||
#else
|
||||
data[i] = o.APPLY(data[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific remove function to reduce (un)boxing
|
||||
* @param index the index of the element to fetch
|
||||
* @return the value of the requested index
|
||||
* @throws IndexOutOfBoundsException if the index is out of range
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE REMOVE(int index) {
|
||||
checkRange(index);
|
||||
KEY_TYPE old = data[index];
|
||||
size--;
|
||||
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
|
||||
#if TYPE_OBJECT
|
||||
data[size] = null;
|
||||
#endif
|
||||
return old;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific implementation of remove. This implementation iterates over the elements until it finds the element that is searched for or it runs out of elements.
|
||||
* It stops after finding the first element
|
||||
* @param e the element that is searched for
|
||||
* @return true if the element was found and removed.
|
||||
*/
|
||||
@Override
|
||||
public boolean REMOVE_KEY(KEY_TYPE type) {
|
||||
int index = indexOf(type);
|
||||
if(index == -1) return false;
|
||||
REMOVE(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific pop function to reduce (un)boxing
|
||||
* @param index the index of the element to fetch
|
||||
* @return the value of the requested index
|
||||
* @throws IndexOutOfBoundsException if the index is out of range
|
||||
*/
|
||||
@Override
|
||||
public KEY_TYPE POP() {
|
||||
return REMOVE(size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to remove all elements that were provided in the other collection
|
||||
* This function might delegate to a more appropiate function if nessesary
|
||||
* @param c the elements that should be removed
|
||||
* @return true if the collection was modified
|
||||
* @throws NullPointerException if the collection is null
|
||||
* @deprecated if the collection is type-specific
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
if(c.isEmpty()) return false;
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(!c.contains(KEY_TO_OBJ(data[i]))) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
#if TYPE_OBJECT
|
||||
Arrays.fill(data, j, size, null);
|
||||
#endif
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to retain all elements that were provided in the other collection
|
||||
* This function might delegate to a more appropiate function if nessesary
|
||||
* @param c the elements that should be kept. If empty, ARRAY_LIST#clear is called.
|
||||
* @return true if the collection was modified
|
||||
* @throws NullPointerException if the collection is null
|
||||
* @deprecated if the collection is type-specific
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
if(c.isEmpty()) {
|
||||
boolean modifed = size > 0;
|
||||
clear();
|
||||
return modifed;
|
||||
}
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(c.contains(KEY_TO_OBJ(data[i]))) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
#if TYPE_OBJECT
|
||||
Arrays.fill(data, j, size, null);
|
||||
#endif
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* A optimized List#removeIf(Predicate) that more quickly removes elements from the list then the ArrayList implementation
|
||||
* @param filter the filter to remove elements
|
||||
* @return true if the list was modified
|
||||
* @deprecated if Type-Specific, use #remIf instead
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeIf(Predicate<? super CLASS_TYPE> filter) {
|
||||
Objects.requireNonNull(filter);
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(!filter.test(KEY_TO_OBJ(data[i]))) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
#if TYPE_OBJECT
|
||||
Arrays.fill(data, j, size, null);
|
||||
#endif
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to remove all elements that were provided in the other collection
|
||||
* @param c the elements that should be removed
|
||||
* @return true if the collection was modified
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
if(c.isEmpty()) return false;
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(!c.contains(data[i])) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
#if TYPE_OBJECT
|
||||
Arrays.fill(data, j, size, null);
|
||||
#endif
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to retain all elements that were provided in the other collection
|
||||
* This function might delegate to a more appropiate function if nessesary
|
||||
* @param c the elements that should be kept. If empty, ARRAY_LIST#clear is called.
|
||||
* @return true if the collection was modified
|
||||
* @throws NullPointerException if the collection is null
|
||||
*/
|
||||
@Override
|
||||
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
if(c.isEmpty()) {
|
||||
boolean modifed = size > 0;
|
||||
clear();
|
||||
return modifed;
|
||||
}
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(c.contains(data[i])) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
#if TYPE_OBJECT
|
||||
Arrays.fill(data, j, size, null);
|
||||
#endif
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
#if PRIMITIVES
|
||||
/**
|
||||
* A optimized List#removeIf(Predicate) that more quickly removes elements from the list then the ArrayList implementation
|
||||
* @param filter the filter to remove elements
|
||||
* @return true if the list was modified
|
||||
*/
|
||||
@Override
|
||||
public boolean remIf(JAVA_PREDICATE filter) {
|
||||
Objects.requireNonNull(filter);
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(!filter.test(data[i])) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A toArray implementation that ensures the Array itself is a Object.
|
||||
* @return a Array of the elements in the list
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public Object[] toArray() {
|
||||
Object[] obj = new Object[size];
|
||||
for(int i = 0;i<size;i++)
|
||||
obj[i] = KEY_TO_OBJ(data[i]);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* A toArray implementation that ensures the Array itself is a Object.
|
||||
* @param a original array. If null a Object array with the right size is created. If to small the Array of the same type is created with the right size
|
||||
* @return a Array of the elements in the list
|
||||
*/
|
||||
@Override
|
||||
@Primitive
|
||||
public <E> E[] toArray(E[] a) {
|
||||
if(a == null) a = (E[])new Object[size];
|
||||
else if(a.length < size) a = (E[])ObjectArrays.newArray(a.getClass().getComponentType(), size);
|
||||
for(int i = 0;i<size;i++)
|
||||
a[i] = (E)KEY_TO_OBJ(data[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
|
||||
if(a.length < size) a = new KEY_TYPE[size];
|
||||
System.arraycopy(data, 0, a, 0, size);
|
||||
return a;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A function to return the size of the list
|
||||
* @return the size of elements in the list
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to ensure the elements are within the requested size.
|
||||
* If smaller then the stored elements they get removed as needed.
|
||||
* If bigger it is ensured that enough room is provided depending on the implementation
|
||||
* @param size the requested amount of elements/room for elements
|
||||
*/
|
||||
@Override
|
||||
public void size(int size) {
|
||||
if(size > data.length)
|
||||
data = Arrays.copyOf(data, size);
|
||||
else if(size < size() && size >= 0)
|
||||
Arrays.fill(data, size, size(), EMPTY_KEY_VALUE);
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to clear all elements in the list.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
#if TYPE_OBJECT
|
||||
for(int i = 0;i<size;data[i] = null,i++);
|
||||
#endif
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the original collection down to the size of the current elements or the requested size depending which is bigger
|
||||
* @param size the requested trim size.
|
||||
*/
|
||||
@Override
|
||||
public boolean trim(int size) {
|
||||
if(size > size() || size() == data.length) return false;
|
||||
int value = Math.max(size, size());
|
||||
data = value == 0 ? EMPTY_KEY_ARRAY : Arrays.copyOf(data, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the capacity of this implementation instance, if necessary,
|
||||
* to ensure that it can hold at least the number of elements specified by
|
||||
* the minimum capacity argument.
|
||||
*
|
||||
* @param size the desired minimum capacity
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int size) {
|
||||
grow(size);
|
||||
}
|
||||
|
||||
protected void grow(int capacity) {
|
||||
if(capacity < data.length) return;
|
||||
data = Arrays.copyOf(data, data == ARRAYS.EMPTY_ARRAY ? DEFAULT_ARRAY_SIZE : (int)Math.max(Math.min((long)data.length + (data.length >> 1), SanityChecks.MAX_ARRAY_SIZE), capacity));
|
||||
}
|
||||
|
||||
protected void checkRange(int index) {
|
||||
if (index < 0 || index >= size)
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
}
|
||||
|
||||
protected void checkAddRange(int index) {
|
||||
if (index < 0 || index > size)
|
||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
package speiger.src.collections.PACKAGE.lists;
|
||||
|
||||
import java.util.List;
|
||||
#if !TYPE_OBJECT && !TYPE_BOOLEAN
|
||||
import java.util.Objects;
|
||||
import java.util.function.JAVA_UNARY_OPERATOR;
|
||||
import java.util.function.UnaryOperator;
|
||||
#else if TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
import java.util.function.UnaryOperator;
|
||||
#endif
|
||||
import java.util.Comparator;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.ARRAYS;
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
#endif
|
||||
|
||||
public interface LIST KEY_GENERIC_TYPE extends COLLECTION KEY_GENERIC_TYPE, List<CLASS_TYPE>
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific add Function to reduce (un)boxing
|
||||
* @param e the element to add
|
||||
* @return true if the list was modified
|
||||
* @see List#add(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean add(KEY_TYPE e);
|
||||
|
||||
/**
|
||||
* A Type-Specific add Function to reduce (un)boxing
|
||||
* @param e the element to add
|
||||
* @param index index at which the specified element is to be inserted
|
||||
* @see List#add(int, Object)
|
||||
*/
|
||||
public void add(int index, KEY_TYPE e);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific addAll Function to reduce (un)boxing
|
||||
* @param c the elements that need to be added
|
||||
* @param index index at which the specified elements is to be inserted
|
||||
* @return true if the list was modified
|
||||
* @see List#addAll(int, Object)
|
||||
*/
|
||||
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c);
|
||||
|
||||
/**
|
||||
* A Type-Specific and optimized addAll function that allows a faster transfer of elements
|
||||
* @param c the elements that need to be added
|
||||
* @return true if the list was modified
|
||||
*/
|
||||
public boolean addAll(LIST KEY_GENERIC_TYPE c);
|
||||
|
||||
/**
|
||||
* A Type-Specific and optimized addAll function that allows a faster transfer of elements
|
||||
* @param c the elements that need to be added
|
||||
* @param index index at which the specified elements is to be inserted
|
||||
* @return true if the list was modified
|
||||
*/
|
||||
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Type-Specific get function to reduce (un)boxing
|
||||
* @param index the index of the value that is requested
|
||||
* @return the value at the given index
|
||||
* @throws IndexOutOfBoundsException if the index is not within the list range
|
||||
* @see List#get(int)
|
||||
*/
|
||||
public KEY_TYPE GET_KEY(int index);
|
||||
|
||||
/**
|
||||
* A Type-Specific set function to reduce (un)boxing
|
||||
* @param index index of the element to replace
|
||||
* @param element element to be stored at the specified position
|
||||
* @return the element previously at the specified position
|
||||
* @throws IndexOutOfBoundsException if the index is not within the list range
|
||||
* @see List#set(int, Object)
|
||||
*/
|
||||
public KEY_TYPE set(int index, KEY_TYPE e);
|
||||
|
||||
/**
|
||||
* A Type-Specific remove function to reduce (un)boxing
|
||||
* @param index the index of the element to be removed
|
||||
* @return the element previously at the specified position
|
||||
* @see List#remove(int)
|
||||
*/
|
||||
public KEY_TYPE REMOVE(int index);
|
||||
|
||||
/**
|
||||
* A Type-Specific indexOf function to reduce (un)boxing
|
||||
* @param e the element that is searched for
|
||||
* @return the index of the element if found. (if not found then -1)
|
||||
* @note does not support null values
|
||||
*/
|
||||
public int indexOf(KEY_TYPE e);
|
||||
|
||||
/**
|
||||
* A Type-Specific lastIndexOf function to reduce (un)boxing
|
||||
* @param e the element that is searched for
|
||||
* @return the lastIndex of the element if found. (if not found then -1)
|
||||
* @note does not support null values
|
||||
*/
|
||||
public int lastIndexOf(KEY_TYPE e);
|
||||
|
||||
#if !TYPE_BOOLEAN
|
||||
/**
|
||||
* A Type-Specific replace function to reduce (un)boxing
|
||||
* @param o the action to replace the values
|
||||
* @throws NullPointerException if o is null
|
||||
*/
|
||||
public default void REPLACE(JAVA_UNARY_OPERATOR o) {
|
||||
Objects.requireNonNull(o);
|
||||
LIST_ITERATOR iter = listIterator();
|
||||
while (iter.hasNext())
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
iter.set(SanityChecks.SANITY_CAST(o.APPLY_CAST(iter.NEXT())));
|
||||
#else
|
||||
iter.set(o.APPLY(iter.NEXT()));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
/**
|
||||
* A function to replace all values in the list
|
||||
* @param o the action to replace the values
|
||||
* @throws NullPointerException if o is null
|
||||
*/
|
||||
@Override
|
||||
public default void replaceAll(UnaryOperator<CLASS_TYPE> o) {
|
||||
Objects.requireNonNull(o);
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
while (iter.hasNext()) iter.set(o.apply(iter.NEXT()));
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A function to fast add elements to the list
|
||||
* @param from the index where the elements should be added into the list
|
||||
* @param a the elements that should be added
|
||||
* @throws IndexOutOfBoundsException if from is outside of the lists range
|
||||
*/
|
||||
public default void addElements(int from, KEY_TYPE[] a) { addElements(from, a, 0, a.length); }
|
||||
|
||||
/**
|
||||
* A function to fast add elements to the list
|
||||
* @param from the index where the elements should be added into the list
|
||||
* @param a the elements that should be added
|
||||
* @param offset the start index of the array should be read from
|
||||
* @param length how many elements should be read from
|
||||
* @throws IndexOutOfBoundsException if from is outside of the lists range
|
||||
* @throws IllegalStateException if offset or length are smaller then 0 or exceed the array length
|
||||
*/
|
||||
public void addElements(int from, KEY_TYPE[] a, int offset, int length);
|
||||
|
||||
/**
|
||||
* A function to fast fetch elements from the list
|
||||
* @param from index where the list should be fetching elements from
|
||||
* @param a the array where the values should be inserted to
|
||||
* @returns the inputArray
|
||||
* @throws NullPointerException if the array is null
|
||||
* @throws IndexOutOfBoundsException if from is outside of the lists range
|
||||
* @throws IllegalStateException if offset or length are smaller then 0 or exceed the array length
|
||||
*/
|
||||
public default KEY_TYPE[] getElements(int from, KEY_TYPE[] a) { return getElements(from, a, 0, a.length); }
|
||||
|
||||
/**
|
||||
* A function to fast fetch elements from the list
|
||||
* @param from index where the list should be fetching elements from
|
||||
* @param a the array where the values should be inserted to
|
||||
* @param offset the startIndex of where the array should be written to
|
||||
* @param length the number of elements the values should be fetched from
|
||||
* @returns the inputArray
|
||||
* @throws NullPointerException if the array is null
|
||||
* @throws IndexOutOfBoundsException if from is outside of the lists range
|
||||
* @throws IllegalStateException if offset or length are smaller then 0 or exceed the array length
|
||||
*/
|
||||
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length);
|
||||
|
||||
/**
|
||||
* a function to fast remove elements from the list.
|
||||
* @param from the start index of where the elements should be removed from (inclusive)
|
||||
* @param to the end index of where the elements should be removed to (exclusive)
|
||||
*/
|
||||
public void removeElements(int from, int to);
|
||||
|
||||
#if TYPE_OBJECT
|
||||
/**
|
||||
* A function to fast extract elements out of the list, this removes the elements that were fetched.
|
||||
* @param from the start index of where the elements should be fetched from (inclusive)
|
||||
* @param to the end index of where the elements should be fetched to (exclusive)
|
||||
* @param type the type of the OutputArray
|
||||
* @return a array of the elements that were fetched
|
||||
*/
|
||||
public <K> K[] extractElements(int from, int to, Class<K> type);
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#stableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
@Override
|
||||
public default void sort(Comparator<? super CLASS_TYPE> c) {
|
||||
KEY_TYPE[] array = (KEY_TYPE[])TO_ARRAY();
|
||||
if(c != null) ARRAYS.stableSort(array, c);
|
||||
else ARRAYS.stableSort((Comparable[])array);
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
for (int i = 0,m=size();i<m && iter.hasNext();i++) {
|
||||
iter.NEXT();
|
||||
iter.set(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements using a unstable sort
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#unstableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
public default void unstableSort(Comparator<? super CLASS_TYPE> c) {
|
||||
KEY_TYPE[] array = (KEY_TYPE[])TO_ARRAY();
|
||||
if(c != null) ARRAYS.unstableSort(array, c);
|
||||
else ARRAYS.unstableSort((Comparable[])array);
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
for (int i = 0,m=size();i<m && iter.hasNext();i++) {
|
||||
iter.NEXT();
|
||||
iter.set(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* A function to fast extract elements out of the list, this removes the elements that were fetched.
|
||||
* @param from the start index of where the elements should be fetched from (inclusive)
|
||||
* @param to the end index of where the elements should be fetched to (exclusive)
|
||||
* @return a array of the elements that were fetched
|
||||
*/
|
||||
public KEY_TYPE[] extractElements(int from, int to);
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
default void sort(Comparator<? super CLASS_TYPE> c) {
|
||||
sort((K, V) -> c.compare(KEY_TO_OBJ(K), KEY_TO_OBJ(V)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#stableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
public default void sort(COMPARATOR c) {
|
||||
KEY_TYPE[] array = TO_ARRAY();
|
||||
if(c != null) ARRAYS.stableSort(array, c);
|
||||
else ARRAYS.stableSort(array);
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
for (int i = 0,m=size();i<m && iter.hasNext();i++) {
|
||||
iter.NEXT();
|
||||
iter.set(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public default void unstableSort(Comparator<? super CLASS_TYPE> c) {
|
||||
unstableSort((K, V) -> c.compare(KEY_TO_OBJ(K), KEY_TO_OBJ(V)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the elements specified by the Natural order either by using the Comparator or the elements using a unstable sort
|
||||
* @see List#sort(Comparator)
|
||||
* @see ARRAYS#unstableSort(KEY_TYPE[], Comparator)
|
||||
*/
|
||||
public default void unstableSort(COMPARATOR c) {
|
||||
KEY_TYPE[] array = TO_ARRAY();
|
||||
if(c != null) ARRAYS.unstableSort(array, c);
|
||||
else ARRAYS.unstableSort(array);
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter = listIterator();
|
||||
for (int i = 0,m=size();i<m && iter.hasNext();i++) {
|
||||
iter.NEXT();
|
||||
iter.set(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* A Type-Specific Iterator of listIterator
|
||||
* @see List#listIterator
|
||||
*/
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator();
|
||||
|
||||
/**
|
||||
* A Type-Specific Iterator of listIterator
|
||||
* @see List#listIterator(int)
|
||||
*/
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index);
|
||||
|
||||
/**
|
||||
* A Type-Specific List of subList
|
||||
* @see List#subList(int, int)
|
||||
*/
|
||||
@Override
|
||||
public LIST KEY_GENERIC_TYPE subList(int from, int to);
|
||||
|
||||
/**
|
||||
* A function to ensure the elements are within the requested size.
|
||||
* If smaller then the stored elements they get removed as needed.
|
||||
* If bigger it is ensured that enough room is provided depending on the implementation
|
||||
* @param size the requested amount of elements/room for elements
|
||||
*/
|
||||
public void size(int size);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean add(CLASS_TYPE e) {
|
||||
return COLLECTION.super.add(e);
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE get(int index) {
|
||||
return KEY_TO_OBJ(GET_KEY(index));
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE set(int index, CLASS_TYPE e) {
|
||||
return KEY_TO_OBJ(set(index, OBJ_TO_KEY(e)));
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default int indexOf(Object o) {
|
||||
return indexOf(CLASS_TO_KEY(o));
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default int lastIndexOf(Object o) {
|
||||
return lastIndexOf(CLASS_TO_KEY(o));
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean contains(Object o) {
|
||||
return COLLECTION.super.contains(o);
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default boolean remove(Object o) {
|
||||
return COLLECTION.super.remove(o);
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE remove(int index) {
|
||||
return KEY_TO_OBJ(REMOVE(index));
|
||||
}
|
||||
|
||||
#if !TYPE_BOOLEAN
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default void replaceAll(UnaryOperator<CLASS_TYPE> o) {
|
||||
Objects.requireNonNull(o);
|
||||
#if TYPE_BYTE || TYPE_SHORT || TYPE_CHAR || TYPE_FLOAT
|
||||
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ((KEY_TYPE)T))));
|
||||
#else
|
||||
REPLACE(T -> OBJ_TO_KEY(o.apply(KEY_TO_OBJ(T))));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package speiger.src.collections.PACKAGE.lists;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
|
||||
public interface LIST_ITERATOR KEY_GENERIC_TYPE extends ListIterator<CLASS_TYPE>, BI_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Primitive set function to reduce (un)boxing
|
||||
* @see ListIterator#set(Object)
|
||||
*/
|
||||
public void set(KEY_TYPE e);
|
||||
|
||||
/**
|
||||
* A Primitive set function to reduce (un)boxing
|
||||
* @see ListIterator#set(Object)
|
||||
*/
|
||||
public void add(KEY_TYPE e);
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE previous() {
|
||||
return BI_ITERATOR.super.previous();
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE next() {
|
||||
return BI_ITERATOR.super.next();
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default void set(CLASS_TYPE e) {
|
||||
set(OBJ_TO_KEY(e));
|
||||
}
|
||||
|
||||
/** {@inheritDoc}
|
||||
* <p>This default implementation delegates to the corresponding type-specific function.
|
||||
* @deprecated Please use the corresponding type-specific function instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public default void add(CLASS_TYPE e) {
|
||||
add(OBJ_TO_KEY(e));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+405
@@ -0,0 +1,405 @@
|
||||
package speiger.src.collections.PACKAGE.maps.abstracts;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
|
||||
import speiger.src.collections.PACKAGE.functions.function.FUNCTION;
|
||||
import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR;
|
||||
import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
|
||||
import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
import speiger.src.collections.PACKAGE.utils.maps.MAPS;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
#if !SAME_TYPE
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
|
||||
import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_UNARY_OPERATOR;
|
||||
#endif
|
||||
#if !TYPE_OBJECT && !VALUE_OBJECT
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
#endif
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
#endif
|
||||
|
||||
public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CLASS_TYPE, CLASS_VALUE_TYPE> implements MAP KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
protected VALUE_TYPE defaultReturnValue = EMPTY_VALUE;
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE getDefaultReturnValue() {
|
||||
return defaultReturnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE setDefaultReturnValue(VALUE_TYPE v) {
|
||||
defaultReturnValue = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(MAP KEY_VALUE_GENERIC_TYPE m) {
|
||||
for(ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iter = MAPS.fastIterator(m);iter.hasNext();) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = iter.next();
|
||||
put(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> m)
|
||||
{
|
||||
if(m instanceof MAP) putAll((MAP KEY_VALUE_GENERIC_TYPE)m);
|
||||
else super.putAll(m);
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = keySet().iterator();iter.hasNext();)
|
||||
if(EQUALS_KEY_TYPE(iter.NEXT(), key)) return true;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
|
||||
@Override
|
||||
public boolean containsKey(KEY_TYPE key) {
|
||||
for(ITERATOR KEY_GENERIC_TYPE iter = keySet().iterator();iter.hasNext();)
|
||||
if(KEY_EQUALS(iter.NEXT(), key)) return true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if VALUE_OBJECT
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
for(VALUE_ITERATOR VALUE_GENERIC_TYPE iter = values().iterator();iter.hasNext();)
|
||||
if(EQUALS_VALUE_TYPE(iter.VALUE_NEXT(), value)) return true;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
|
||||
@Override
|
||||
public boolean containsValue(VALUE_TYPE value) {
|
||||
for(VALUE_ITERATOR VALUE_GENERIC_TYPE iter = values().iterator();iter.hasNext();)
|
||||
if(VALUE_EQUALS(iter.VALUE_NEXT(), value)) return true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public boolean replace(KEY_TYPE key, VALUE_TYPE oldValue, VALUE_TYPE newValue) {
|
||||
VALUE_TYPE curValue = get(key);
|
||||
if (VALUE_EQUALS_NOT(curValue, oldValue) || (VALUE_EQUALS(curValue, getDefaultReturnValue()) && !containsKey(key))) {
|
||||
return false;
|
||||
}
|
||||
put(key, newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE replace(KEY_TYPE key, VALUE_TYPE value) {
|
||||
VALUE_TYPE curValue;
|
||||
if (VALUE_EQUALS_NOT((curValue = get(key)), getDefaultReturnValue()) || containsKey(key)) {
|
||||
curValue = put(key, value);
|
||||
}
|
||||
return curValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void REPLACE_VALUES(UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
for(ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iter = MAPS.fastIterator(this);iter.hasNext();) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = iter.next();
|
||||
entry.setValue(mappingFunction.APPLY_VALUE(entry.ENTRY_KEY(), entry.ENTRY_VALUE()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
VALUE_TYPE value = get(key);
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
|
||||
if(VALUE_EQUALS_NOT(value, getDefaultReturnValue()) || containsKey(key)) {
|
||||
remove(key);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
VALUE_TYPE value;
|
||||
if((value = get(key)) == getDefaultReturnValue()) {
|
||||
VALUE_TYPE newValue = mappingFunction.GET_VALUE(key);
|
||||
if(VALUE_EQUALS_NOT(newValue, getDefaultReturnValue())) {
|
||||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
VALUE_TYPE value;
|
||||
if(VALUE_EQUALS_NOT((value = get(key)), getDefaultReturnValue())) {
|
||||
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value);
|
||||
if(VALUE_EQUALS_NOT(newValue, getDefaultReturnValue())) {
|
||||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
remove(key);
|
||||
}
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
|
||||
Objects.requireNonNull(mappingFunction);
|
||||
VALUE_TYPE oldValue = get(key);
|
||||
VALUE_TYPE newValue = VALUE_EQUALS(oldValue, getDefaultReturnValue()) ? value : mappingFunction.APPLY_VALUE(oldValue, value);
|
||||
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) remove(key);
|
||||
else put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public CLASS_VALUE_TYPE get(Object key) {
|
||||
return VALUE_TO_OBJ(GET_VALUE((T)key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
|
||||
CLASS_VALUE_TYPE value = get(key);
|
||||
return VALUE_EQUALS_NOT(value, getDefaultReturnValue()) || containsKey(key) ? value : defaultValue;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public CLASS_VALUE_TYPE get(Object key) {
|
||||
return VALUE_TO_OBJ(key instanceof CLASS_TYPE ? GET_VALUE(CLASS_TO_KEY(key)) : getDefaultReturnValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
|
||||
return VALUE_TO_OBJ(key instanceof CLASS_TYPE ? getOrDefault(CLASS_TO_KEY(key), OBJ_TO_VALUE(defaultValue)) : getDefaultReturnValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
|
||||
VALUE_TYPE value = get(key);
|
||||
return VALUE_EQUALS_NOT(value, getDefaultReturnValue()) || containsKey(key) ? value : defaultValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
|
||||
Objects.requireNonNull(action);
|
||||
for(ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iter = MAPS.fastIterator(this);iter.hasNext();) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = iter.next();
|
||||
action.accept(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SET KEY_GENERIC_TYPE keySet() {
|
||||
return new ABSTRACT_SET KEY_GENERIC_TYPE() {
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
return VALUE_EQUALS_NOT(ABSTRACT_MAP.this.remove(o), getDefaultReturnValue());
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return VALUE_EQUALS_NOT(ABSTRACT_MAP.this.remove(o), getDefaultReturnValue());
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new ITERATOR KEY_GENERIC_TYPE() {
|
||||
ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iter = MAPS.fastIterator(ABSTRACT_MAP.this);
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return iter.next().ENTRY_KEY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
iter.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ABSTRACT_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ABSTRACT_MAP.this.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
|
||||
return new VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE() {
|
||||
@Override
|
||||
public boolean add(VALUE_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ABSTRACT_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ABSTRACT_MAP.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
|
||||
return new VALUE_ITERATOR VALUE_GENERIC_TYPE() {
|
||||
ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iter = MAPS.fastIterator(ABSTRACT_MAP.this);
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_NEXT() {
|
||||
return iter.next().ENTRY_VALUE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
iter.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public ObjectSet<Map.Entry<CLASS_TYPE, CLASS_VALUE_TYPE>> entrySet() {
|
||||
return (ObjectSet)ENTRY_SET();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o == this) return true;
|
||||
if(o instanceof Map) {
|
||||
if(size() != ((Map<?, ?>)o).size()) return false;
|
||||
if(o instanceof MAP) return ENTRY_SET().containsAll(((MAP KEY_VALUE_GENERIC_TYPE)o).ENTRY_SET());
|
||||
return ENTRY_SET().containsAll(((Map<?, ?>)o).entrySet());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iter = MAPS.fastIterator(this);
|
||||
while(iter.hasNext()) hash += iter.next().hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static class BasicEntry KEY_VALUE_GENERIC_TYPE implements MAP.Entry KEY_VALUE_GENERIC_TYPE {
|
||||
protected KEY_TYPE key;
|
||||
protected VALUE_TYPE value;
|
||||
|
||||
public BasicEntry() {}
|
||||
#if !TYPE_OBJECT
|
||||
public BasicEntry(CLASS_TYPE key, CLASS_VALUE_TYPE value) {
|
||||
this.key = OBJ_TO_KEY(key);
|
||||
this.value = OBJ_TO_VALUE(value);
|
||||
}
|
||||
|
||||
#endif
|
||||
public BasicEntry(KEY_TYPE key, VALUE_TYPE value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void set(KEY_TYPE key, VALUE_TYPE value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE ENTRY_KEY() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE ENTRY_VALUE() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE setValue(VALUE_TYPE value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof Map.Entry) {
|
||||
if(obj instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj;
|
||||
return KEY_EQUALS(key, entry.ENTRY_KEY()) && VALUE_EQUALS(value, entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
return KEY_EQUALS(this.key, key) && VALUE_EQUALS(this.value, value);
|
||||
#else if TYPE_OBJECT
|
||||
return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(this.key, key) && VALUE_EQUALS(this.value, CLASS_TO_VALUE(value));
|
||||
#else if VALUE_OBJECT
|
||||
return key instanceof CLASS_TYPE && KEY_EQUALS(this.key, CLASS_TO_KEY(key)) && VALUE_EQUALS(this.value, value);
|
||||
#else
|
||||
return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(this.key, CLASS_TO_KEY(key)) && VALUE_EQUALS(this.value, CLASS_TO_VALUE(value));
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return KEY_TO_HASH(key) ^ VALUE_TO_HASH(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(key) + "->" + VALUE_TO_STRING(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+999
@@ -0,0 +1,999 @@
|
||||
package speiger.src.collections.PACKAGE.maps.impl.customHash;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
|
||||
import speiger.src.collections.PACKAGE.maps.interfaces.SORTED_MAP;
|
||||
import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SORTED_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
import speiger.src.collections.PACKAGE.utils.STRATEGY;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
|
||||
#if !VALUE_OBJECT && !SAME_TYPE
|
||||
import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
|
||||
import speiger.src.collections.VALUE_PACKAGE.lists.VALUE_LIST_ITERATOR;
|
||||
#endif
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
|
||||
import speiger.src.collections.objects.lists.ObjectListIterator;
|
||||
import speiger.src.collections.objects.sets.AbstractObjectSet;
|
||||
import speiger.src.collections.objects.sets.ObjectSortedSet;
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
#endif
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
|
||||
public class LINKED_CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE implements SORTED_MAP KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
protected transient long[] links;
|
||||
protected int firstIndex = -1;
|
||||
protected int lastIndex = -1;
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(int minCapacity, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(int minCapacity, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
super(minCapacity, loadFactor, strategy);
|
||||
links = new long[nullIndex + 1];
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
public LINKED_CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys.length, loadFactor, strategy);
|
||||
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
|
||||
for(int i = 0,m=keys.length;i<m;i++) put(OBJ_TO_KEY(keys[i]), OBJ_TO_VALUE(values[i]));
|
||||
}
|
||||
|
||||
#endif
|
||||
public LINKED_CUSTOM_HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys.length, loadFactor, strategy);
|
||||
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
|
||||
for(int i = 0,m=keys.length;i<m;i++) put(keys[i], values[i]);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map.size(), loadFactor, strategy);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map.size(), loadFactor, strategy);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value) {
|
||||
if(strategy.equals(key, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
VALUE_TYPE lastValue = values[nullIndex];
|
||||
values[nullIndex] = value;
|
||||
moveToFirstIndex(nullIndex);
|
||||
return lastValue;
|
||||
}
|
||||
values[nullIndex] = value;
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], key)) {
|
||||
VALUE_TYPE lastValue = values[pos];
|
||||
values[pos] = value;
|
||||
moveToFirstIndex(pos);
|
||||
return lastValue;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = key;
|
||||
values[pos] = value;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value) {
|
||||
if(strategy.equals(key, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
VALUE_TYPE lastValue = values[nullIndex];
|
||||
values[nullIndex] = value;
|
||||
moveToLastIndex(nullIndex);
|
||||
return lastValue;
|
||||
}
|
||||
values[nullIndex] = value;
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], key)) {
|
||||
VALUE_TYPE lastValue = values[pos];
|
||||
values[pos] = value;
|
||||
moveToLastIndex(pos);
|
||||
return lastValue;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = key;
|
||||
values[pos] = value;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE key) {
|
||||
if(strategy.equals(FIRST_ENTRY_KEY(), key)) return false;
|
||||
if(strategy.equals(key, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], key)) {
|
||||
moveToFirstIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE key) {
|
||||
if(strategy.equals(LAST_ENTRY_KEY(), key)) return false;
|
||||
if(strategy.equals(key, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], key)) {
|
||||
moveToLastIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key) {
|
||||
int index = findIndex(key);
|
||||
if(index < 0) return getDefaultReturnValue();
|
||||
moveToFirstIndex(index);
|
||||
return values[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE getAndMoveToLast(KEY_TYPE key) {
|
||||
int index = findIndex(key);
|
||||
if(index < 0) return getDefaultReturnValue();
|
||||
moveToLastIndex(index);
|
||||
return values[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_ENTRY_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[firstIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_ENTRY_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = firstIndex;
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_ENTRY_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[lastIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_ENTRY_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = lastIndex;
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE FIRST_ENTRY_VALUE() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return values[firstIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE LAST_ENTRY_VALUE() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return values[lastIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> ENTRY_SET() {
|
||||
if(entrySet == null) entrySet = new MapEntrySet();
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SET KEY_GENERIC_TYPE keySet() {
|
||||
if(keySet == null) keySet = new KeySet();
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
|
||||
if(values == null) valuesC = new Values();
|
||||
return valuesC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
action.accept(keys[index], values[index]);
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
firstIndex = lastIndex = -1;
|
||||
}
|
||||
|
||||
protected void moveToFirstIndex(int startPos) {
|
||||
if(size == 1 || firstIndex == startPos) return;
|
||||
if(lastIndex == startPos) {
|
||||
lastIndex = (int)(links[startPos] >>> 32);
|
||||
links[lastIndex] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[startPos] = 0xFFFFFFFF00000000L | (firstIndex & 0xFFFFFFFFL);
|
||||
firstIndex = startPos;
|
||||
}
|
||||
|
||||
protected void moveToLastIndex(int startPos) {
|
||||
if(size == 1 || lastIndex == startPos) return;
|
||||
if(firstIndex == startPos) {
|
||||
firstIndex = (int)links[startPos];
|
||||
links[lastIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
|
||||
lastIndex = startPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeAdded(int pos) {
|
||||
if(size == 0) {
|
||||
firstIndex = lastIndex = pos;
|
||||
links[pos] = -1L;
|
||||
}
|
||||
else {
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
|
||||
lastIndex = pos;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeRemoved(int pos) {
|
||||
if(size == 0) firstIndex = lastIndex = -1;
|
||||
else if(firstIndex == pos) {
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else if(lastIndex == pos) {
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[pos] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[pos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
if(size == 1) {
|
||||
firstIndex = lastIndex = to;
|
||||
links[to] = -1L;
|
||||
}
|
||||
else if(firstIndex == from) {
|
||||
firstIndex = to;
|
||||
links[(int)links[from]] ^= ((links[(int)links[from]] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else if(lastIndex == from) {
|
||||
lastIndex = to;
|
||||
links[(int)(links[from] >>> 32)] ^= ((links[(int)(links[from] >>> 32)] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else {
|
||||
long link = links[from];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = link;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rehash(int newSize) {
|
||||
int newMask = newSize - 1;
|
||||
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
|
||||
VALUE_TYPE[] newValues = NEW_VALUE_ARRAY(newSize + 1);
|
||||
long[] newLinks = new long[newSize + 1];
|
||||
int newPrev = -1;
|
||||
for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) pos = newSize;
|
||||
else {
|
||||
pos = HashUtil.mix(strategy.hashCode(keys[i])) & newMask;
|
||||
while(!strategy.equals(newKeys[pos], EMPTY_KEY_VALUE)) pos = ++pos & newMask;
|
||||
}
|
||||
newKeys[pos] = keys[i];
|
||||
newValues[pos] = values[i];
|
||||
if(prev != -1) {
|
||||
newLinks[newPrev] ^= ((newLinks[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
newLinks[pos] ^= ((newLinks[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
newPrev = pos;
|
||||
}
|
||||
else {
|
||||
newPrev = firstIndex = pos;
|
||||
newLinks[pos] = -1L;
|
||||
}
|
||||
i = (int)links[prev = i];
|
||||
}
|
||||
links = newLinks;
|
||||
lastIndex = newPrev;
|
||||
if(newPrev != -1) newLinks[newPrev] |= 0xFFFFFFFFL;
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
private class MapEntrySet extends AbstractObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> implements SORTED_MAP.FastSortedSet KEY_VALUE_GENERIC_TYPE {
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public boolean addAndMoveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.moveToFirst(o.ENTRY_KEY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(MAP.Entry KEY_VALUE_GENERIC_TYPE o) {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.moveToLast(o.ENTRY_KEY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE first() {
|
||||
return new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE last() {
|
||||
return new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirst() {
|
||||
BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(FIRST_ENTRY_KEY(), FIRST_ENTRY_VALUE());
|
||||
POLL_FIRST_ENTRY_KEY();
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLast() {
|
||||
BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(LAST_ENTRY_KEY(), LAST_ENTRY_VALUE());
|
||||
POLL_LAST_ENTRY_KEY();
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) {
|
||||
return new EntryIterator(fromElement.ENTRY_KEY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator() {
|
||||
return new FastEntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator(KEY_TYPE fromElement) {
|
||||
return new FastEntryIterator(fromElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
action.accept(new BasicEntryKV_BRACES(keys[index], values[index]));
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastForEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
entry.set(keys[index], values[index]);
|
||||
action.accept(entry);
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean contains(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) return LINKED_CUSTOM_HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
|
||||
return LINKED_CUSTOM_HASH_MAP.this.containsKey(((Map.Entry<?, ?>)o).getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean remove(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
return LINKED_CUSTOM_HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
return LINKED_CUSTOM_HASH_MAP.this.remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
LINKED_CUSTOM_HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<MAP.Entry KEY_VALUE_GENERIC_TYPE> comparator() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public ObjectSortedSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> subSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement, MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public ObjectSortedSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> headSet(MAP.Entry KEY_VALUE_GENERIC_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public ObjectSortedSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> tailSet(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean contains(Object e) {
|
||||
return containsKey(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
return containsKey(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.moveToFirst(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.moveToLast(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
|
||||
return new KeyIterator(fromElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
LINKED_CUSTOM_HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() {
|
||||
return FIRST_ENTRY_KEY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() {
|
||||
return POLL_FIRST_ENTRY_KEY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() {
|
||||
return LAST_ENTRY_KEY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() {
|
||||
return POLL_LAST_ENTRY_KEY();
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
action.accept(keys[index]);
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
action.accept(keys[index]);
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean contains(Object e) {
|
||||
return containsValue(e);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(VALUE_TYPE e) {
|
||||
return containsValue(e);
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(VALUE_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return LINKED_CUSTOM_HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
LINKED_CUSTOM_HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
action.accept(values[index]);
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
#else
|
||||
@Override
|
||||
public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
|
||||
int index = firstIndex;
|
||||
while(index != -1){
|
||||
action.accept(values[index]);
|
||||
index = (int)links[index];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private class FastEntryIterator extends MapIterator implements ObjectListIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
MapEntry entry = new MapEntry(nextEntry());
|
||||
|
||||
public FastEntryIterator() {}
|
||||
public FastEntryIterator(KEY_TYPE from) {
|
||||
super(from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
entry.index = nextEntry();
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
|
||||
entry.index = previousEntry();
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private class EntryIterator extends MapIterator implements ObjectListIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
MapEntry entry;
|
||||
|
||||
public EntryIterator() {}
|
||||
public EntryIterator(KEY_TYPE from) {
|
||||
super(from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
return entry = new MapEntry(nextEntry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() {
|
||||
return entry = new MapEntry(previousEntry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
entry.index = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(MAP.Entry KEY_VALUE_GENERIC_TYPE entry) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private class KeyIterator extends MapIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
|
||||
public KeyIterator() {}
|
||||
public KeyIterator(KEY_TYPE from) {
|
||||
super(from);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
return keys[previousEntry()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return keys[nextEntry()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private class ValueIterator extends MapIterator implements VALUE_LIST_ITERATOR VALUE_GENERIC_TYPE {
|
||||
public ValueIterator() {}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_PREVIOUS() {
|
||||
return values[previousEntry()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_NEXT() {
|
||||
return values[nextEntry()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
}
|
||||
|
||||
private class MapIterator {
|
||||
int previous = -1;
|
||||
int next = -1;
|
||||
int current = -1;
|
||||
int index = 0;
|
||||
|
||||
MapIterator() {
|
||||
next = firstIndex;
|
||||
}
|
||||
|
||||
MapIterator(KEY_TYPE from) {
|
||||
if(strategy.equals(from, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
next = (int) links[nullIndex];
|
||||
previous = nullIndex;
|
||||
}
|
||||
else throw new NoSuchElementException("The null element is not in the set");
|
||||
}
|
||||
else if(keys[lastIndex] == from) {
|
||||
previous = lastIndex;
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(from)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], from)) {
|
||||
next = (int)links[pos];
|
||||
previous = pos;
|
||||
break;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
if(previous == -1 && next == -1)
|
||||
throw new NoSuchElementException("The element was not found");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return next != -1;
|
||||
}
|
||||
|
||||
public boolean hasPrevious() {
|
||||
return previous != -1;
|
||||
}
|
||||
|
||||
public int nextIndex() {
|
||||
ensureIndexKnown();
|
||||
return index;
|
||||
}
|
||||
|
||||
public int previousIndex() {
|
||||
ensureIndexKnown();
|
||||
return index - 1;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(current == -1) throw new IllegalStateException();
|
||||
ensureIndexKnown();
|
||||
if(current == previous) {
|
||||
index--;
|
||||
previous = (int)(links[current] >>> 32);
|
||||
}
|
||||
else next = (int)links[current];
|
||||
size--;
|
||||
if(previous == -1) firstIndex = next;
|
||||
else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
|
||||
if (next == -1) lastIndex = previous;
|
||||
else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
if(current == nullIndex) {
|
||||
current = -1;
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else {
|
||||
int slot, last, startPos = current;
|
||||
current = -1;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
values[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(strategy.hashCode(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
values[last] = values[startPos];
|
||||
if(next == startPos) next = last;
|
||||
if(previous == startPos) previous = last;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int previousEntry() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
current = previous;
|
||||
previous = (int)(links[current] >> 32);
|
||||
next = current;
|
||||
if(index >= 0) index--;
|
||||
return current;
|
||||
}
|
||||
|
||||
public int nextEntry() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
current = next;
|
||||
next = (int)(links[current]);
|
||||
previous = current;
|
||||
if(index >= 0) index++;
|
||||
return current;
|
||||
}
|
||||
|
||||
private void ensureIndexKnown() {
|
||||
if(index == -1) {
|
||||
if(previous == -1) {
|
||||
index = 0;
|
||||
}
|
||||
else if(next == -1) {
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
index = 1;
|
||||
for(int pos = firstIndex;pos != previous;pos = (int)links[pos], index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+782
@@ -0,0 +1,782 @@
|
||||
package speiger.src.collections.PACKAGE.maps.impl.customHash;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
|
||||
import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST;
|
||||
import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
|
||||
import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.STRATEGY;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
#if !SAME_TYPE && !VALUE_OBJECT
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
|
||||
import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
import speiger.src.collections.objects.sets.AbstractObjectSet;
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
|
||||
public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
protected transient KEY_TYPE[] keys;
|
||||
protected transient VALUE_TYPE[] values;
|
||||
protected transient boolean containsNull;
|
||||
protected transient int minCapacity;
|
||||
protected transient int nullIndex;
|
||||
protected transient int maxFill;
|
||||
protected transient int mask;
|
||||
protected transient FastEntrySet KEY_VALUE_GENERIC_TYPE entrySet;
|
||||
protected transient SET KEY_GENERIC_TYPE keySet;
|
||||
protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
|
||||
|
||||
protected int size;
|
||||
protected final float loadFactor;
|
||||
protected final STRATEGY KEY_SUPER_GENERIC_TYPE strategy;
|
||||
|
||||
public CUSTOM_HASH_MAP(STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(int minCapacity, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(int minCapacity, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
|
||||
if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
|
||||
this.loadFactor = loadFactor;
|
||||
this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
|
||||
this.strategy = strategy;
|
||||
mask = nullIndex - 1;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = NEW_KEY_ARRAY(nullIndex + 1);
|
||||
values = NEW_VALUE_ARRAY(nullIndex + 1);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
public CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys.length, loadFactor, strategy);
|
||||
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
|
||||
for(int i = 0,m=keys.length;i<m;i++) put(OBJ_TO_KEY(keys[i]), OBJ_TO_VALUE(values[i]));
|
||||
}
|
||||
|
||||
#endif
|
||||
public CUSTOM_HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(keys.length, loadFactor, strategy);
|
||||
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
|
||||
for(int i = 0,m=keys.length;i<m;i++) put(keys[i], values[i]);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map.size(), loadFactor, strategy);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(map.size(), loadFactor, strategy);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) {
|
||||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] = value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) {
|
||||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
return values[slot];
|
||||
}
|
||||
|
||||
#if VALUE_PRIMITIVES
|
||||
@Override
|
||||
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) {
|
||||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] += value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean containsKey(KEY_TYPE key) {
|
||||
return findIndex(key) >= 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean containsKey(Object key) {
|
||||
return findIndex(key) >= 0;
|
||||
}
|
||||
|
||||
#if !VALUE_OBJECT
|
||||
@Override
|
||||
public boolean containsValue(VALUE_TYPE value) {
|
||||
if(VALUE_EQUALS(value, values[nullIndex])) return true;
|
||||
for(int i = nullIndex-1;i >= 0;i--)
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && VALUE_EQUALS(values[i], value)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean containsValue(Object value) {
|
||||
if((value == null && VALUE_EQUALS(values[nullIndex], getDefaultReturnValue())) || EQUALS_VALUE_TYPE(values[nullIndex], value)) return true;
|
||||
for(int i = nullIndex-1;i >= 0;i--)
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) return getDefaultReturnValue();
|
||||
return removeIndex(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public CLASS_VALUE_TYPE remove(Object key) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
|
||||
return removeIndex(slot);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
|
||||
if(strategy.equals(key, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull && VALUE_EQUALS(value, values[nullIndex])) {
|
||||
removeNullIndex();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
|
||||
if(strategy.equals(current, key) && VALUE_EQUALS(value, values[pos])) {
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
while(true) {
|
||||
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
|
||||
else if(strategy.equals(current, key) && VALUE_EQUALS(value, values[pos])) {
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
Objects.requireNonNull(value);
|
||||
if(key == null) {
|
||||
if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
|
||||
removeNullIndex();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
KEY_TYPE keyType = CLASS_TO_KEY(key);
|
||||
int pos = HashUtil.mix(strategy.hashCode(keyType)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
|
||||
if(strategy.equals(current, keyType) && EQUALS_VALUE_TYPE(values[pos], value)) {
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
while(true) {
|
||||
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
|
||||
else if(strategy.equals(current, keyType) && EQUALS_VALUE_TYPE(values[pos], value)){
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
|
||||
int slot = findIndex(key);
|
||||
return slot < 0 ? getDefaultReturnValue() : values[slot];
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLASS_VALUE_TYPE get(Object key) {
|
||||
int slot = findIndex(key);
|
||||
return VALUE_TO_OBJ(slot < 0 ? getDefaultReturnValue() : values[slot]);
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) {
|
||||
int slot = findIndex(key);
|
||||
return slot < 0 ? defaultValue : values[slot];
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
|
||||
int slot = findIndex(key);
|
||||
return slot < 0 ? defaultValue : values[slot];
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> ENTRY_SET() {
|
||||
if(entrySet == null) entrySet = new MapEntrySet();
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SET KEY_GENERIC_TYPE keySet() {
|
||||
if(keySet == null) keySet = new KeySet();
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
|
||||
if(valuesC == null) valuesC = new Values();
|
||||
return valuesC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
|
||||
if(size() <= 0) return;
|
||||
if(containsNull) action.accept(keys[nullIndex], values[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--) {
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i], values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(size == 0) return;
|
||||
size = 0;
|
||||
containsNull = false;
|
||||
Arrays.fill(keys, EMPTY_KEY_VALUE);
|
||||
Arrays.fill(values, EMPTY_VALUE);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
protected int findIndex(KEY_TYPE key) {
|
||||
if(KEY_EQUALS_NULL(key)) return containsNull ? nullIndex : -(nullIndex + 1);
|
||||
int pos = HashUtil.mix(strategy.hashCode(key)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(!strategy.equals(current, EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(current, key)) return pos;
|
||||
while(!strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE))
|
||||
if(strategy.equals(current, key)) return pos;
|
||||
}
|
||||
return -(pos + 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
protected int findIndex(Object key) {
|
||||
if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
|
||||
KEY_TYPE keyType = CLASS_TO_KEY(key);
|
||||
int pos = HashUtil.mix(strategy.hashCode(keyType)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(!strategy.equals(current, EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(current, keyType)) return pos;
|
||||
while(!strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE))
|
||||
if(strategy.equals(current, keyType)) return pos;
|
||||
}
|
||||
return -(pos + 1);
|
||||
}
|
||||
|
||||
protected VALUE_TYPE removeIndex(int pos) {
|
||||
VALUE_TYPE value = values[pos];
|
||||
size--;
|
||||
onNodeRemoved(pos);
|
||||
shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
protected VALUE_TYPE removeNullIndex() {
|
||||
VALUE_TYPE value = values[nullIndex];
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
size--;
|
||||
onNodeRemoved(nullIndex);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
protected void insert(int slot, KEY_TYPE key, VALUE_TYPE value) {
|
||||
if(slot == nullIndex) containsNull = true;
|
||||
keys[slot] = key;
|
||||
values[slot] = value;
|
||||
onNodeAdded(slot);
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
}
|
||||
|
||||
protected void rehash(int newSize) {
|
||||
int newMask = newSize - 1;
|
||||
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));
|
||||
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];
|
||||
newValues[pos] = values[i];
|
||||
}
|
||||
newValues[newSize] = values[nullIndex];
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
values = newValues;
|
||||
}
|
||||
|
||||
protected void onNodeAdded(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeRemoved(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
|
||||
}
|
||||
|
||||
protected void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
values[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(strategy.hashCode(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
values[last] = values[startPos];
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
|
||||
protected class MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry<CLASS_TYPE, CLASS_VALUE_TYPE> {
|
||||
public int index = -1;
|
||||
|
||||
public MapEntry() {}
|
||||
public MapEntry(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE ENTRY_KEY() {
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE ENTRY_VALUE() {
|
||||
return values[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE setValue(VALUE_TYPE value) {
|
||||
VALUE_TYPE oldValue = values[index];
|
||||
values[index] = value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof Map.Entry) {
|
||||
if(obj instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj;
|
||||
return KEY_EQUALS(keys[index], entry.ENTRY_KEY()) && VALUE_EQUALS(values[index], entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
return KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], value);
|
||||
#else if TYPE_OBJECT
|
||||
return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
|
||||
#else if VALUE_OBJECT
|
||||
return key instanceof CLASS_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], value);
|
||||
#else
|
||||
return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return strategy.hashCode(keys[index]) ^ VALUE_TO_HASH(values[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
private final class MapEntrySet extends AbstractObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> implements MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE {
|
||||
@Override
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator() {
|
||||
return new FastEntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
if(containsNull) action.accept(new BasicEntryKV_BRACES(keys[nullIndex], values[nullIndex]));
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(!strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(new BasicEntryKV_BRACES(keys[i], values[i]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastForEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
|
||||
if(containsNull) {
|
||||
entry.set(keys[nullIndex], values[nullIndex]);
|
||||
action.accept(entry);
|
||||
}
|
||||
for(int i = nullIndex-1;i>=0;i--) {
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) {
|
||||
entry.set(keys[i], values[i]);
|
||||
action.accept(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return CUSTOM_HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
CUSTOM_HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) return CUSTOM_HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
|
||||
return CUSTOM_HASH_MAP.this.containsKey(((Map.Entry<?, ?>)o).getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
return CUSTOM_HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
return CUSTOM_HASH_MAP.this.remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE {
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object e) {
|
||||
return containsKey(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
return containsKey(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return CUSTOM_HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
CUSTOM_HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(keys[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i]);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(keys[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(keys[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object e) {
|
||||
return containsValue(e);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(VALUE_TYPE e) {
|
||||
return containsValue(e);
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(VALUE_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return CUSTOM_HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
CUSTOM_HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(values[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(values[i]);
|
||||
}
|
||||
#else
|
||||
@Override
|
||||
public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(values[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) action.accept(values[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private class FastEntryIterator extends MapIterator implements ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
MapEntry entry = new MapEntry();
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
entry.index = nextEntry();
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
private class EntryIterator extends MapIterator implements ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
MapEntry entry;
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
return entry = new MapEntry(nextEntry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
entry.index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyIterator extends MapIterator implements ITERATOR KEY_GENERIC_TYPE {
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return keys[nextEntry()];
|
||||
}
|
||||
}
|
||||
|
||||
private class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE {
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_NEXT() {
|
||||
return values[nextEntry()];
|
||||
}
|
||||
}
|
||||
|
||||
private class MapIterator {
|
||||
int pos = nullIndex;
|
||||
int lastReturned = -1;
|
||||
int nextIndex = Integer.MIN_VALUE;
|
||||
boolean returnNull = containsNull;
|
||||
LIST KEY_GENERIC_TYPE wrapped = null;
|
||||
|
||||
public boolean hasNext() {
|
||||
if(nextIndex == Integer.MIN_VALUE) {
|
||||
if(returnNull) {
|
||||
returnNull = false;
|
||||
nextIndex = nullIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(true) {
|
||||
if(--pos < 0) {
|
||||
if(wrapped == null || wrapped.size() <= -pos - 1) break;
|
||||
nextIndex = -pos - 1;
|
||||
break;
|
||||
}
|
||||
if(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)){
|
||||
nextIndex = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextIndex != Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public int nextEntry() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
if(nextIndex < 0){
|
||||
lastReturned = Integer.MAX_VALUE;
|
||||
int value = findIndex(wrapped.GET_KEY(nextIndex));
|
||||
if(value < 0) throw new IllegalStateException("Entry ["+nextIndex+"] was removed during Iteration");
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
int value = (lastReturned = nextIndex);
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(lastReturned == -1) throw new IllegalStateException();
|
||||
if(lastReturned == nullIndex) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else if(pos >= 0) shiftKeys(pos);
|
||||
else {
|
||||
CUSTOM_HASH_MAP.this.remove(wrapped.GET_KEY(-pos - 1));
|
||||
return;
|
||||
}
|
||||
size--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
private void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
values[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(strategy.hashCode(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
if(startPos < last) {
|
||||
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
|
||||
wrapped.add(keys[startPos]);
|
||||
}
|
||||
keys[last] = current;
|
||||
values[last] = values[startPos];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1001
File diff suppressed because it is too large
Load Diff
+777
@@ -0,0 +1,777 @@
|
||||
package speiger.src.collections.PACKAGE.maps.impl.hash;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
|
||||
import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST;
|
||||
import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP;
|
||||
import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
#endif
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
#if !SAME_TYPE && !VALUE_OBJECT
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
|
||||
import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
import speiger.src.collections.objects.sets.AbstractObjectSet;
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
|
||||
public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
protected transient KEY_TYPE[] keys;
|
||||
protected transient VALUE_TYPE[] values;
|
||||
protected transient boolean containsNull;
|
||||
protected transient int minCapacity;
|
||||
protected transient int nullIndex;
|
||||
protected transient int maxFill;
|
||||
protected transient int mask;
|
||||
protected transient FastEntrySet KEY_VALUE_GENERIC_TYPE entrySet;
|
||||
protected transient SET KEY_GENERIC_TYPE keySet;
|
||||
protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
|
||||
|
||||
protected int size;
|
||||
protected final float loadFactor;
|
||||
|
||||
public HASH_MAP() {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_MAP(int minCapacity) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_MAP(int minCapacity, float loadFactor) {
|
||||
if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
|
||||
if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
|
||||
this.loadFactor = loadFactor;
|
||||
this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
|
||||
mask = nullIndex - 1;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = NEW_KEY_ARRAY(nullIndex + 1);
|
||||
values = NEW_VALUE_ARRAY(nullIndex + 1);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
public HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values) {
|
||||
this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_MAP(CLASS_TYPE[] keys, CLASS_VALUE_TYPE[] values, float loadFactor) {
|
||||
this(keys.length, loadFactor);
|
||||
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
|
||||
for(int i = 0,m=keys.length;i<m;i++) put(OBJ_TO_KEY(keys[i]), OBJ_TO_VALUE(values[i]));
|
||||
}
|
||||
|
||||
#endif
|
||||
public HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values) {
|
||||
this(keys, values, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_MAP(KEY_TYPE[] keys, VALUE_TYPE[] values, float loadFactor) {
|
||||
this(keys.length, loadFactor);
|
||||
if(keys.length != values.length) throw new IllegalStateException("Input Arrays are not equal size");
|
||||
for(int i = 0,m=keys.length;i<m;i++) put(keys[i], values[i]);
|
||||
}
|
||||
|
||||
public HASH_MAP(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map) {
|
||||
this(map, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_MAP(Map<? extends CLASS_TYPE, ? extends CLASS_VALUE_TYPE> map, float loadFactor) {
|
||||
this(map.size(), loadFactor);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
public HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map) {
|
||||
this(map, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_MAP(MAP KEY_VALUE_GENERIC_TYPE map, float loadFactor) {
|
||||
this(map.size(), loadFactor);
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) {
|
||||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] = value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) {
|
||||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
return values[slot];
|
||||
}
|
||||
|
||||
#if VALUE_PRIMITIVES
|
||||
@Override
|
||||
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) {
|
||||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] += value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean containsKey(KEY_TYPE key) {
|
||||
return findIndex(key) >= 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean containsKey(Object key) {
|
||||
return findIndex(key) >= 0;
|
||||
}
|
||||
|
||||
#if !VALUE_OBJECT
|
||||
@Override
|
||||
public boolean containsValue(VALUE_TYPE value) {
|
||||
if(VALUE_EQUALS(value, values[nullIndex])) return true;
|
||||
for(int i = nullIndex-1;i >= 0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i]) && VALUE_EQUALS(values[i], value)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean containsValue(Object value) {
|
||||
if((value == null && VALUE_EQUALS(values[nullIndex], getDefaultReturnValue())) || EQUALS_VALUE_TYPE(values[nullIndex], value)) return true;
|
||||
for(int i = nullIndex-1;i >= 0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i]) && ((value == null && values[i] == getDefaultReturnValue()) || EQUALS_VALUE_TYPE(values[i], value))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE REMOVE_KEY(KEY_TYPE key) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) return getDefaultReturnValue();
|
||||
return removeIndex(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public CLASS_VALUE_TYPE remove(Object key) {
|
||||
int slot = findIndex(key);
|
||||
if(slot < 0) return VALUE_TO_OBJ(getDefaultReturnValue());
|
||||
return removeIndex(slot);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE key, VALUE_TYPE value) {
|
||||
if(KEY_EQUALS_NULL(key)) {
|
||||
if(containsNull && VALUE_EQUALS(value, values[nullIndex])) {
|
||||
removeNullIndex();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NULL(current)) return false;
|
||||
if(KEY_EQUALS(current, key) && VALUE_EQUALS(value, values[pos])) {
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
while(true) {
|
||||
if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
|
||||
else if(KEY_EQUALS(current, key) && VALUE_EQUALS(value, values[pos])) {
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
Objects.requireNonNull(value);
|
||||
if(key == null) {
|
||||
if(containsNull && EQUALS_VALUE_TYPE(values[nullIndex], value)) {
|
||||
removeNullIndex();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int pos = HashUtil.mix(key.hashCode()) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NULL(current)) return false;
|
||||
if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)) {
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
while(true) {
|
||||
if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
|
||||
else if(EQUALS_KEY_TYPE(current, key) && EQUALS_VALUE_TYPE(values[pos], value)){
|
||||
removeIndex(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE GET_VALUE(KEY_TYPE key) {
|
||||
int slot = findIndex(key);
|
||||
return slot < 0 ? getDefaultReturnValue() : values[slot];
|
||||
}
|
||||
|
||||
@Override
|
||||
public CLASS_VALUE_TYPE get(Object key) {
|
||||
int slot = findIndex(key);
|
||||
return VALUE_TO_OBJ(slot < 0 ? getDefaultReturnValue() : values[slot]);
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) {
|
||||
int slot = findIndex(key);
|
||||
return slot < 0 ? defaultValue : values[slot];
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue) {
|
||||
int slot = findIndex(key);
|
||||
return slot < 0 ? defaultValue : values[slot];
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> ENTRY_SET() {
|
||||
if(entrySet == null) entrySet = new MapEntrySet();
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SET KEY_GENERIC_TYPE keySet() {
|
||||
if(keySet == null) keySet = new KeySet();
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
|
||||
if(valuesC == null) valuesC = new Values();
|
||||
return valuesC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action) {
|
||||
if(size() <= 0) return;
|
||||
if(containsNull) action.accept(keys[nullIndex], values[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--) {
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(keys[i], values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(size == 0) return;
|
||||
size = 0;
|
||||
containsNull = false;
|
||||
Arrays.fill(keys, EMPTY_KEY_VALUE);
|
||||
Arrays.fill(values, EMPTY_VALUE);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
protected int findIndex(KEY_TYPE key) {
|
||||
if(KEY_EQUALS_NULL(key)) return containsNull ? nullIndex : -(nullIndex + 1);
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(key)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NOT_NULL(current)) {
|
||||
if(KEY_EQUALS(current, key)) return pos;
|
||||
while(KEY_EQUALS_NOT_NULL((current = keys[pos = (++pos & mask)])))
|
||||
if(KEY_EQUALS(current, key)) return pos;
|
||||
}
|
||||
return -(pos + 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
protected int findIndex(Object key) {
|
||||
if(key == null) return containsNull ? nullIndex : -(nullIndex + 1);
|
||||
int pos = HashUtil.mix(key.hashCode()) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NOT_NULL(current)) {
|
||||
if(EQUALS_KEY_TYPE(current, key)) return pos;
|
||||
while(KEY_EQUALS_NOT_NULL((current = keys[pos = (++pos & mask)])))
|
||||
if(EQUALS_KEY_TYPE(current, key)) return pos;
|
||||
}
|
||||
return -(pos + 1);
|
||||
}
|
||||
|
||||
protected VALUE_TYPE removeIndex(int pos) {
|
||||
VALUE_TYPE value = values[pos];
|
||||
size--;
|
||||
onNodeRemoved(pos);
|
||||
shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
protected VALUE_TYPE removeNullIndex() {
|
||||
VALUE_TYPE value = values[nullIndex];
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
size--;
|
||||
onNodeRemoved(nullIndex);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
protected void insert(int slot, KEY_TYPE key, VALUE_TYPE value) {
|
||||
if(slot == nullIndex) containsNull = true;
|
||||
keys[slot] = key;
|
||||
values[slot] = value;
|
||||
onNodeAdded(slot);
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
}
|
||||
|
||||
protected void rehash(int newSize) {
|
||||
int newMask = newSize - 1;
|
||||
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]));
|
||||
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];
|
||||
newValues[pos] = values[i];
|
||||
}
|
||||
newValues[newSize] = values[nullIndex];
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
values = newValues;
|
||||
}
|
||||
|
||||
protected void onNodeAdded(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeRemoved(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
|
||||
}
|
||||
|
||||
protected void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(KEY_EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
values[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
values[last] = values[startPos];
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
|
||||
protected class MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry<CLASS_TYPE, CLASS_VALUE_TYPE> {
|
||||
public int index = -1;
|
||||
|
||||
public MapEntry() {}
|
||||
public MapEntry(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE ENTRY_KEY() {
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE ENTRY_VALUE() {
|
||||
return values[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE setValue(VALUE_TYPE value) {
|
||||
VALUE_TYPE oldValue = values[index];
|
||||
values[index] = value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof Map.Entry) {
|
||||
if(obj instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj;
|
||||
return KEY_EQUALS(keys[index], entry.ENTRY_KEY()) && VALUE_EQUALS(values[index], entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
#if TYPE_OBJECT && VALUE_OBJECT
|
||||
return KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], value);
|
||||
#else if TYPE_OBJECT
|
||||
return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], key) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
|
||||
#else if VALUE_OBJECT
|
||||
return key instanceof CLASS_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], value);
|
||||
#else
|
||||
return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(keys[index], CLASS_TO_KEY(key)) && VALUE_EQUALS(values[index], CLASS_TO_VALUE(value));
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return KEY_TO_HASH(keys[index]) ^ VALUE_TO_HASH(values[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return KEY_TO_STRING(keys[index]) + "->" + VALUE_TO_STRING(values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
private final class MapEntrySet extends AbstractObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> implements MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE {
|
||||
@Override
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator() {
|
||||
return new FastEntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
if(containsNull) action.accept(new BasicEntryKV_BRACES(keys[nullIndex], values[nullIndex]));
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(new BasicEntryKV_BRACES(keys[i], values[i]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastForEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES();
|
||||
if(containsNull) {
|
||||
entry.set(keys[nullIndex], values[nullIndex]);
|
||||
action.accept(entry);
|
||||
}
|
||||
for(int i = nullIndex-1;i>=0;i--) {
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) {
|
||||
entry.set(keys[i], values[i]);
|
||||
action.accept(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) return HASH_MAP.this.containsKey(((MAP.Entry KEY_VALUE_GENERIC_TYPE)o).ENTRY_KEY());
|
||||
return HASH_MAP.this.containsKey(((Map.Entry<?, ?>)o).getKey());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
return HASH_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>)o;
|
||||
return HASH_MAP.this.remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE {
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object e) {
|
||||
return containsKey(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
return containsKey(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int oldSize = size;
|
||||
remove(o);
|
||||
return size != oldSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(keys[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(keys[i]);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(keys[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(keys[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object e) {
|
||||
return containsValue(e);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(VALUE_TYPE e) {
|
||||
return containsValue(e);
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(VALUE_TYPE o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return HASH_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
HASH_MAP.this.clear();
|
||||
}
|
||||
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer VALUE_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(values[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(values[i]);
|
||||
}
|
||||
#else
|
||||
@Override
|
||||
public void forEach(VALUE_CONSUMER VALUE_SUPER_GENERIC_TYPE action) {
|
||||
if(containsNull) action.accept(values[nullIndex]);
|
||||
for(int i = nullIndex-1;i>=0;i--)
|
||||
if(KEY_EQUALS_NOT_NULL(keys[i])) action.accept(values[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private class FastEntryIterator extends MapIterator implements ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
MapEntry entry = new MapEntry();
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
entry.index = nextEntry();
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
private class EntryIterator extends MapIterator implements ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
MapEntry entry;
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
return entry = new MapEntry(nextEntry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
entry.index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyIterator extends MapIterator implements ITERATOR KEY_GENERIC_TYPE {
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return keys[nextEntry()];
|
||||
}
|
||||
}
|
||||
|
||||
private class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE {
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_NEXT() {
|
||||
return values[nextEntry()];
|
||||
}
|
||||
}
|
||||
|
||||
private class MapIterator {
|
||||
int pos = nullIndex;
|
||||
int lastReturned = -1;
|
||||
int nextIndex = Integer.MIN_VALUE;
|
||||
boolean returnNull = containsNull;
|
||||
LIST KEY_GENERIC_TYPE wrapped = null;
|
||||
|
||||
public boolean hasNext() {
|
||||
if(nextIndex == Integer.MIN_VALUE) {
|
||||
if(returnNull) {
|
||||
returnNull = false;
|
||||
nextIndex = nullIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(true) {
|
||||
if(--pos < 0) {
|
||||
if(wrapped == null || wrapped.size() <= -pos - 1) break;
|
||||
nextIndex = -pos - 1;
|
||||
break;
|
||||
}
|
||||
if(KEY_EQUALS_NOT_NULL(keys[pos])){
|
||||
nextIndex = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextIndex != Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public int nextEntry() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
if(nextIndex < 0){
|
||||
lastReturned = Integer.MAX_VALUE;
|
||||
int value = findIndex(wrapped.GET_KEY(nextIndex));
|
||||
if(value < 0) throw new IllegalStateException("Entry ["+nextIndex+"] was removed during Iteration");
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
int value = (lastReturned = nextIndex);
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(lastReturned == -1) throw new IllegalStateException();
|
||||
if(lastReturned == nullIndex) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
values[nullIndex] = EMPTY_VALUE;
|
||||
}
|
||||
else if(pos >= 0) shiftKeys(pos);
|
||||
else {
|
||||
HASH_MAP.this.remove(wrapped.GET_KEY(-pos - 1));
|
||||
return;
|
||||
}
|
||||
size--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
private void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(KEY_EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
values[last] = EMPTY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
if(startPos < last) {
|
||||
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
|
||||
wrapped.add(keys[startPos]);
|
||||
}
|
||||
keys[last] = current;
|
||||
values[last] = values[startPos];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1649
File diff suppressed because it is too large
Load Diff
+335
@@ -0,0 +1,335 @@
|
||||
package speiger.src.collections.PACKAGE.maps.impl.misc;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
#if VALUE_OBJECT
|
||||
import java.util.Objects;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR;
|
||||
#if !VALUE_OBJECT
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
#endif
|
||||
import speiger.src.collections.objects.maps.abstracts.ABSTRACT_MAP;
|
||||
import speiger.src.collections.objects.maps.interfaces.MAP;
|
||||
import speiger.src.collections.objects.sets.AbstractObjectSet;
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
//import sun.misc.SharedSecrets;
|
||||
|
||||
public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
protected final Class<T> keyType;
|
||||
protected transient final T[] keys;
|
||||
protected transient final VALUE_TYPE[] values;
|
||||
protected transient final long[] present;
|
||||
protected int size = 0;
|
||||
protected transient ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> entrySet;
|
||||
protected transient ObjectSet<T> keySet;
|
||||
protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE valuesC;
|
||||
|
||||
public ENUM_MAP(Class<T> keyType) {
|
||||
this.keyType = keyType;
|
||||
keys = getKeyUniverse(keyType);
|
||||
values = NEW_VALUE_ARRAY(keys.length);
|
||||
present = new long[((keys.length - 1) >> 6) + 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE put(T key, VALUE_TYPE value) {
|
||||
int index = key.ordinal();
|
||||
if(isSet(index)) {
|
||||
VALUE_TYPE result = values[index];
|
||||
values[index] = value;
|
||||
return result;
|
||||
}
|
||||
set(index);
|
||||
values[index] = value;
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE putIfAbsent(T key, VALUE_TYPE value) {
|
||||
int index = key.ordinal();
|
||||
if(isSet(index)) return values[index];
|
||||
set(index);
|
||||
values[index] = value;
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
|
||||
#if VALUE_PRIMITIVES
|
||||
@Override
|
||||
public VALUE_TYPE addTo(T key, VALUE_TYPE value) {
|
||||
int index = key.ordinal();
|
||||
if(isSet(index)) {
|
||||
VALUE_TYPE result = values[index];
|
||||
values[index] += value;
|
||||
return result;
|
||||
}
|
||||
set(index);
|
||||
values[index] = value;
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return isSet(((T)key).ordinal());
|
||||
}
|
||||
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
for(int i = 0;i<values.length;i++)
|
||||
if(VALUE_EQUALS(value, values[i])) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean containsValue(VALUE_TYPE value) {
|
||||
for(int i = 0;i<values.length;i++)
|
||||
if(VALUE_EQUALS(value, values[i])) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public VALUE_TYPE rem(T key) {
|
||||
int index = key.ordinal();
|
||||
if(!isSet(index)) return getDefaultReturnValue();
|
||||
clear(index);
|
||||
VALUE_TYPE result = values[index];
|
||||
values[index] = EMPTY_VALUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public boolean remove(Object key, Object value) {
|
||||
int index = ((T)key).ordinal();
|
||||
if(!isSet(index) || VALUE_EQUALS_NOT(value, values[index])) return false;
|
||||
clear(index);
|
||||
values[index] = EMPTY_VALUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean remove(T key, VALUE_TYPE value) {
|
||||
int index = key.ordinal();
|
||||
if(!isSet(index) || VALUE_EQUALS_NOT(value, values[index])) return false;
|
||||
clear(index);
|
||||
values[index] = EMPTY_VALUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public VALUE_TYPE GET_VALUE(T key) {
|
||||
int index = key.ordinal();
|
||||
return isSet(index) ? values[index] : getDefaultReturnValue();
|
||||
}
|
||||
|
||||
#if VALUE_OBJECT
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(Object key, VALUE_TYPE defaultValue) {
|
||||
int index = ((T)key).ordinal();
|
||||
return isSet(index) ? values[index] : defaultValue;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public VALUE_TYPE getOrDefault(T key, VALUE_TYPE defaultValue) {
|
||||
int index = key.ordinal();
|
||||
return isSet(index) ? values[index] : defaultValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> ENTRY_SET() {
|
||||
if(entrySet == null) entrySet = new EntrySet();
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectSet<T> keySet() {
|
||||
if(keySet == null) keySet = new KeySet();
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values() {
|
||||
if(valuesC == null) valuesC = new Values();
|
||||
return valuesC;
|
||||
}
|
||||
|
||||
protected void onNodeAdded(int index) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeRemoved(int index) {
|
||||
|
||||
}
|
||||
|
||||
protected void set(int index) {
|
||||
present[index >> 6] |= (1L << index);
|
||||
onNodeAdded(index);
|
||||
}
|
||||
protected void clear(int index) {
|
||||
present[index >> 6] &= ~(1L << index);
|
||||
onNodeRemoved(index);
|
||||
}
|
||||
protected boolean isSet(int index) { return (present[index >> 6] & (1L << index)) != 0; }
|
||||
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
|
||||
return keyType.getEnumConstants();
|
||||
// return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(keyType);
|
||||
}
|
||||
|
||||
class EntrySet extends AbstractObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if(o instanceof Map.Entry) return containsKey(((Map.Entry<?, ?>)o).getKey());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(o instanceof Map.Entry) {
|
||||
if(o instanceof MAP.Entry) {
|
||||
MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o;
|
||||
return ENUM_MAP.this.remove(entry.getKey(), entry.ENTRY_VALUE());
|
||||
}
|
||||
Map.Entry<?, ?> entry = (java.util.Map.Entry<?, ?>)o;
|
||||
return ENUM_MAP.this.remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ENUM_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ENUM_MAP.this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class KeySet extends AbstractObjectSet<T> {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return containsKey(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int size = size();
|
||||
ENUM_MAP.this.remove(o);
|
||||
return size != size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectIterator<T> iterator() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ENUM_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ENUM_MAP.this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class Values extends VALUE_ABSTRACT_COLLECTION VALUE_GENERIC_TYPE {
|
||||
|
||||
@Override
|
||||
public boolean add(VALUE_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object e) { return containsValue(e); }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(VALUE_TYPE e) { return containsValue(e); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public VALUE_ITERATOR VALUE_GENERIC_TYPE iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ENUM_MAP.this.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ENUM_MAP.this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class EntryIterator extends MapIterator implements ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE next() {
|
||||
int index = nextEntry();
|
||||
return new BasicEntry<>(keys[index], values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
class KeyIterator extends MapIterator implements ObjectIterator<T> {
|
||||
@Override
|
||||
public T next() {
|
||||
return keys[nextEntry()];
|
||||
}
|
||||
}
|
||||
|
||||
class ValueIterator extends MapIterator implements VALUE_ITERATOR VALUE_GENERIC_TYPE {
|
||||
@Override
|
||||
public VALUE_TYPE VALUE_NEXT() {
|
||||
return values[nextEntry()];
|
||||
}
|
||||
}
|
||||
|
||||
class MapIterator {
|
||||
int index;
|
||||
int lastReturnValue = -1;
|
||||
int nextIndex = -1;
|
||||
|
||||
public boolean hasNext() {
|
||||
if(nextIndex == -1 && index < values.length) {
|
||||
while(index < values.length && !isSet(index++));
|
||||
nextIndex = index-1;
|
||||
if(!isSet(nextIndex)) nextIndex = -1;
|
||||
}
|
||||
return nextIndex != -1;
|
||||
}
|
||||
|
||||
public int nextEntry() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
lastReturnValue = nextIndex;
|
||||
return nextIndex;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(lastReturnValue == -1) throw new IllegalStateException();
|
||||
clear(lastReturnValue);
|
||||
values[lastReturnValue] = EMPTY_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1701
File diff suppressed because it is too large
Load Diff
+1763
File diff suppressed because it is too large
Load Diff
+198
@@ -0,0 +1,198 @@
|
||||
package speiger.src.collections.PACKAGE.maps.interfaces;
|
||||
|
||||
import java.util.Map;
|
||||
#if VALUE_OBJECT && !TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
#endif
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER;
|
||||
import speiger.src.collections.PACKAGE.functions.function.FUNCTION;
|
||||
import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
#if !SAME_TYPE
|
||||
import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_UNARY_OPERATOR;
|
||||
#endif
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
#endif
|
||||
|
||||
public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_TYPE>, FUNCTION KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
public VALUE_TYPE getDefaultReturnValue();
|
||||
public MAP KEY_VALUE_GENERIC_TYPE setDefaultReturnValue(VALUE_TYPE v);
|
||||
|
||||
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value);
|
||||
public VALUE_TYPE putIfAbsent(KEY_TYPE key, VALUE_TYPE value);
|
||||
#if VALUE_PRIMITIVES
|
||||
public VALUE_TYPE addTo(KEY_TYPE key, VALUE_TYPE value);
|
||||
#endif
|
||||
|
||||
public void putAll(MAP KEY_VALUE_GENERIC_TYPE m);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public boolean containsKey(KEY_TYPE key);
|
||||
|
||||
@Override
|
||||
public default boolean containsKey(Object key) {
|
||||
return key instanceof CLASS_TYPE && containsKey(CLASS_TO_KEY(key));
|
||||
}
|
||||
|
||||
#endif
|
||||
#if !VALUE_OBJECT
|
||||
public boolean containsValue(VALUE_TYPE value);
|
||||
|
||||
@Override
|
||||
public default boolean containsValue(Object value) {
|
||||
return value instanceof CLASS_VALUE_TYPE && containsValue(CLASS_TO_VALUE(value));
|
||||
}
|
||||
|
||||
#endif
|
||||
public VALUE_TYPE REMOVE_KEY(KEY_TYPE key);
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE remove(Object key) {
|
||||
#if TYPE_OBJECT
|
||||
return VALUE_TO_OBJ(REMOVE_KEY((CLASS_TYPE)key));
|
||||
#else
|
||||
return key instanceof CLASS_TYPE ? VALUE_TO_OBJ(REMOVE_KEY(CLASS_TO_KEY(key))) : VALUE_TO_OBJ(getDefaultReturnValue());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
public boolean remove(KEY_TYPE key, VALUE_TYPE value);
|
||||
|
||||
@Override
|
||||
public default boolean remove(Object key, Object value) {
|
||||
#if TYPE_OBJECT
|
||||
return value instanceof CLASS_VALUE_TYPE && remove((KEY_TYPE)key, CLASS_TO_VALUE(value));
|
||||
#else if VALUE_OBJECT
|
||||
return key instanceof CLASS_TYPE && remove(CLASS_TO_KEY(key), (VALUE_TYPE)value);
|
||||
#else
|
||||
return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && remove(CLASS_TO_KEY(key), CLASS_TO_VALUE(value));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
public boolean replace(KEY_TYPE key, VALUE_TYPE oldValue, VALUE_TYPE newValue);
|
||||
public VALUE_TYPE replace(KEY_TYPE key, VALUE_TYPE value);
|
||||
public void REPLACE_VALUES(UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
|
||||
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
|
||||
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction);
|
||||
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
|
||||
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction);
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
@Override
|
||||
public default boolean replace(CLASS_TYPE key, CLASS_VALUE_TYPE oldValue, CLASS_VALUE_TYPE newValue) {
|
||||
return replace(OBJ_TO_KEY(key), OBJ_TO_VALUE(oldValue), OBJ_TO_VALUE(newValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE replace(CLASS_TYPE key, CLASS_VALUE_TYPE value) {
|
||||
return VALUE_TO_OBJ(replace(OBJ_TO_KEY(key), OBJ_TO_VALUE(value)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VALUE_TYPE GET_VALUE(KEY_TYPE key);
|
||||
public VALUE_TYPE getOrDefault(KEY_TYPE key, VALUE_TYPE defaultValue);
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE get(Object key) {
|
||||
#if TYPE_OBJECT
|
||||
return VALUE_TO_OBJ(GET_VALUE((CLASS_TYPE)key));
|
||||
#else
|
||||
return VALUE_TO_OBJ(key instanceof CLASS_TYPE ? GET_VALUE(CLASS_TO_KEY(key)) : getDefaultReturnValue());
|
||||
#endif
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE getOrDefault(Object key, CLASS_VALUE_TYPE defaultValue) {
|
||||
#if TYPE_OBJECT
|
||||
CLASS_VALUE_TYPE value = VALUE_TO_OBJ(GET_VALUE((CLASS_TYPE)key));
|
||||
#else
|
||||
CLASS_VALUE_TYPE value = VALUE_TO_OBJ(key instanceof CLASS_TYPE ? GET_VALUE(CLASS_TO_KEY(key)) : getDefaultReturnValue());
|
||||
#endif
|
||||
return VALUE_EQUALS_NOT(value, getDefaultReturnValue()) || containsKey(key) ? value : defaultValue;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public default void replaceAll(BiFunction<? super CLASS_TYPE, ? super CLASS_VALUE_TYPE, ? extends CLASS_VALUE_TYPE> mappingFunction) {
|
||||
REPLACE_VALUES(mappingFunction instanceof UNARY_OPERATOR ? (UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE)mappingFunction : (K, V) -> OBJ_TO_VALUE(mappingFunction.apply(KEY_TO_OBJ(K), VALUE_TO_OBJ(V))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE compute(CLASS_TYPE key, BiFunction<? super CLASS_TYPE, ? super CLASS_VALUE_TYPE, ? extends CLASS_VALUE_TYPE> mappingFunction) {
|
||||
return VALUE_TO_OBJ(COMPUTE(OBJ_TO_KEY(key), mappingFunction instanceof UNARY_OPERATOR ? (UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE)mappingFunction : (K, V) -> OBJ_TO_VALUE(mappingFunction.apply(KEY_TO_OBJ(K), VALUE_TO_OBJ(V)))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE computeIfAbsent(CLASS_TYPE key, Function<? super CLASS_TYPE, ? extends CLASS_VALUE_TYPE> mappingFunction) {
|
||||
return VALUE_TO_OBJ(COMPUTE_IF_ABSENT(OBJ_TO_KEY(key), mappingFunction instanceof FUNCTION ? (FUNCTION KEY_VALUE_GENERIC_TYPE)mappingFunction : K -> OBJ_TO_VALUE(mappingFunction.apply(KEY_TO_OBJ(K)))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE computeIfPresent(CLASS_TYPE key, BiFunction<? super CLASS_TYPE, ? super CLASS_VALUE_TYPE, ? extends CLASS_VALUE_TYPE> mappingFunction) {
|
||||
return VALUE_TO_OBJ(COMPUTE_IF_PRESENT(OBJ_TO_KEY(key), mappingFunction instanceof UNARY_OPERATOR ? (UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE)mappingFunction : (K, V) -> OBJ_TO_VALUE(mappingFunction.apply(KEY_TO_OBJ(K), VALUE_TO_OBJ(V)))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE merge(CLASS_TYPE key, CLASS_VALUE_TYPE value, BiFunction<? super CLASS_VALUE_TYPE, ? super CLASS_VALUE_TYPE, ? extends CLASS_VALUE_TYPE> mappingFunction) {
|
||||
return VALUE_TO_OBJ(MERGE(OBJ_TO_KEY(key), OBJ_TO_VALUE(value), mappingFunction instanceof VALUE_UNARY_OPERATOR ? (VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE)mappingFunction : (K, V) -> OBJ_TO_VALUE(mappingFunction.apply(VALUE_TO_OBJ(K), VALUE_TO_OBJ(V)))));
|
||||
}
|
||||
|
||||
public void forEach(BI_CONSUMER KEY_VALUE_GENERIC_TYPE action);
|
||||
|
||||
@Override
|
||||
public default void forEach(BiConsumer<? super CLASS_TYPE, ? super CLASS_VALUE_TYPE> action) {
|
||||
forEach(action instanceof BI_CONSUMER ? (BI_CONSUMER KEY_VALUE_GENERIC_TYPE)action : (K, V) -> action.accept(KEY_TO_OBJ(K), VALUE_TO_OBJ(V)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SET KEY_GENERIC_TYPE keySet();
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values();
|
||||
@Override
|
||||
public ObjectSet<Map.Entry<CLASS_TYPE, CLASS_VALUE_TYPE>> entrySet();
|
||||
public ObjectSet<Entry KEY_VALUE_GENERIC_TYPE> ENTRY_SET();
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE put(CLASS_TYPE key, CLASS_VALUE_TYPE value) {
|
||||
return VALUE_TO_OBJ(put(OBJ_TO_KEY(key), OBJ_TO_VALUE(value)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public default CLASS_VALUE_TYPE putIfAbsent(CLASS_TYPE key, CLASS_VALUE_TYPE value) {
|
||||
return VALUE_TO_OBJ(put(OBJ_TO_KEY(key), OBJ_TO_VALUE(value)));
|
||||
}
|
||||
#endif
|
||||
public interface FastEntrySet KEY_VALUE_GENERIC_TYPE extends ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE>
|
||||
{
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator();
|
||||
public default void fastForEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
forEach(action);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Entry KEY_VALUE_GENERIC_TYPE extends Map.Entry<CLASS_TYPE, CLASS_VALUE_TYPE>
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
public KEY_TYPE ENTRY_KEY();
|
||||
public default CLASS_TYPE getKey() { return KEY_TO_OBJ(ENTRY_KEY()); }
|
||||
#endif
|
||||
|
||||
#if !VALUE_OBJECT
|
||||
public VALUE_TYPE ENTRY_VALUE();
|
||||
public VALUE_TYPE setValue(VALUE_TYPE value);
|
||||
public default CLASS_VALUE_TYPE getValue() { return VALUE_TO_OBJ(ENTRY_VALUE()); }
|
||||
public default CLASS_VALUE_TYPE setValue(CLASS_VALUE_TYPE value) { return VALUE_TO_OBJ(setValue(OBJ_TO_VALUE(value))); }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package speiger.src.collections.PACKAGE.maps.interfaces;
|
||||
|
||||
import java.util.NavigableMap;
|
||||
import speiger.src.collections.PACKAGE.sets.NAVIGABLE_SET;
|
||||
|
||||
public interface NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE extends SORTED_MAP KEY_VALUE_GENERIC_TYPE, NavigableMap<CLASS_TYPE, CLASS_VALUE_TYPE>
|
||||
{
|
||||
@Override
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE descendingMap();
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE navigableKeySet();
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingKeySet();
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE firstEntry();
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE lastEntry();
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE pollFirstEntry();
|
||||
@Override
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE pollLastEntry();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, boolean fromInclusive, KEY_TYPE toKey, boolean toInclusive);
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey, boolean inclusive);
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey, boolean inclusive);
|
||||
|
||||
@Override
|
||||
public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey) { return subMap(fromKey, true, toKey, false); }
|
||||
@Override
|
||||
public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey) { return headMap(toKey, false); }
|
||||
@Override
|
||||
public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey) { return tailMap(fromKey, true); }
|
||||
|
||||
public void setDefaultMaxValue(KEY_TYPE e);
|
||||
public KEY_TYPE getDefaultMaxValue();
|
||||
|
||||
public void setDefaultMinValue(KEY_TYPE e);
|
||||
public KEY_TYPE getDefaultMinValue();
|
||||
|
||||
public KEY_TYPE lowerKey(KEY_TYPE key);
|
||||
public KEY_TYPE higherKey(KEY_TYPE key);
|
||||
public KEY_TYPE floorKey(KEY_TYPE key);
|
||||
public KEY_TYPE ceilingKey(KEY_TYPE key);
|
||||
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(KEY_TYPE key);
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(KEY_TYPE key);
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(KEY_TYPE key);
|
||||
public MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(KEY_TYPE key);
|
||||
|
||||
@Override
|
||||
public default CLASS_TYPE lowerKey(CLASS_TYPE key) { return KEY_TO_OBJ(lowerKey(OBJ_TO_KEY(key)));}
|
||||
@Override
|
||||
public default CLASS_TYPE floorKey(CLASS_TYPE key) { return KEY_TO_OBJ(floorKey(OBJ_TO_KEY(key)));}
|
||||
@Override
|
||||
public default CLASS_TYPE ceilingKey(CLASS_TYPE key) { return KEY_TO_OBJ(ceilingKey(OBJ_TO_KEY(key)));}
|
||||
@Override
|
||||
public default CLASS_TYPE higherKey(CLASS_TYPE key) { return KEY_TO_OBJ(higherKey(OBJ_TO_KEY(key)));}
|
||||
|
||||
@Override
|
||||
default MAP.Entry KEY_VALUE_GENERIC_TYPE lowerEntry(CLASS_TYPE key) { return lowerEntry(OBJ_TO_KEY(key)); }
|
||||
@Override
|
||||
default MAP.Entry KEY_VALUE_GENERIC_TYPE floorEntry(CLASS_TYPE key) { return floorEntry(OBJ_TO_KEY(key)); }
|
||||
@Override
|
||||
default MAP.Entry KEY_VALUE_GENERIC_TYPE ceilingEntry(CLASS_TYPE key) { return ceilingEntry(OBJ_TO_KEY(key)); }
|
||||
@Override
|
||||
default MAP.Entry KEY_VALUE_GENERIC_TYPE higherEntry(CLASS_TYPE key) { return higherEntry(OBJ_TO_KEY(key)); }
|
||||
|
||||
@Override
|
||||
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, boolean fromInclusive, CLASS_TYPE toKey, boolean toInclusive) { return subMap(OBJ_TO_KEY(fromKey), fromInclusive, OBJ_TO_KEY(toKey), toInclusive); }
|
||||
@Override
|
||||
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey, boolean inclusive) { return headMap(OBJ_TO_KEY(toKey), inclusive); }
|
||||
@Override
|
||||
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey, boolean inclusive) { return tailMap(OBJ_TO_KEY(fromKey), inclusive); }
|
||||
@Override
|
||||
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, CLASS_TYPE toKey) { return subMap(OBJ_TO_KEY(fromKey), true, OBJ_TO_KEY(toKey), false); }
|
||||
@Override
|
||||
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey) { return headMap(OBJ_TO_KEY(toKey), false); }
|
||||
@Override
|
||||
default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(OBJ_TO_KEY(fromKey), true); }
|
||||
#else
|
||||
@Override
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, boolean fromInclusive, CLASS_TYPE toKey, boolean toInclusive);
|
||||
@Override
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey, boolean inclusive);
|
||||
@Override
|
||||
public NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey, boolean inclusive);
|
||||
@Override
|
||||
public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, CLASS_TYPE toKey) { return subMap(fromKey, true, toKey, false); }
|
||||
@Override
|
||||
public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey) { return headMap(toKey, false); }
|
||||
@Override
|
||||
public default NAVIGABLE_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(fromKey, true); }
|
||||
#endif
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package speiger.src.collections.PACKAGE.maps.interfaces;
|
||||
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#endif
|
||||
import java.util.SortedMap;
|
||||
|
||||
import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
import speiger.src.collections.objects.sets.ObjectSortedSet;
|
||||
import speiger.src.collections.objects.collections.ObjectBidirectionalIterator;
|
||||
|
||||
public interface SORTED_MAP KEY_VALUE_GENERIC_TYPE extends SortedMap<CLASS_TYPE, CLASS_VALUE_TYPE>, MAP KEY_VALUE_GENERIC_TYPE
|
||||
{
|
||||
public VALUE_TYPE putAndMoveToFirst(KEY_TYPE key, VALUE_TYPE value);
|
||||
public VALUE_TYPE putAndMoveToLast(KEY_TYPE key, VALUE_TYPE value);
|
||||
|
||||
public boolean moveToFirst(KEY_TYPE key);
|
||||
public boolean moveToLast(KEY_TYPE key);
|
||||
|
||||
public VALUE_TYPE getAndMoveToFirst(KEY_TYPE key);
|
||||
public VALUE_TYPE getAndMoveToLast(KEY_TYPE key);
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator();
|
||||
|
||||
@Override
|
||||
public SET KEY_GENERIC_TYPE keySet();
|
||||
@Override
|
||||
public VALUE_COLLECTION VALUE_GENERIC_TYPE values();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(KEY_TYPE fromKey, KEY_TYPE toKey);
|
||||
public SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(KEY_TYPE toKey);
|
||||
public SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(KEY_TYPE fromKey);
|
||||
|
||||
public KEY_TYPE FIRST_ENTRY_KEY();
|
||||
public KEY_TYPE POLL_FIRST_ENTRY_KEY();
|
||||
public KEY_TYPE LAST_ENTRY_KEY();
|
||||
public KEY_TYPE POLL_LAST_ENTRY_KEY();
|
||||
|
||||
public VALUE_TYPE FIRST_ENTRY_VALUE();
|
||||
public VALUE_TYPE LAST_ENTRY_VALUE();
|
||||
|
||||
public default CLASS_TYPE firstKey() { return KEY_TO_OBJ(FIRST_ENTRY_KEY()); }
|
||||
public default CLASS_TYPE lastKey() { return KEY_TO_OBJ(LAST_ENTRY_KEY()); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_MAP KEY_VALUE_GENERIC_TYPE subMap(CLASS_TYPE fromKey, CLASS_TYPE toKey) { return subMap(OBJ_TO_KEY(fromKey), OBJ_TO_KEY(toKey)); }
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_MAP KEY_VALUE_GENERIC_TYPE headMap(CLASS_TYPE toKey) { return headMap(OBJ_TO_KEY(toKey)); }
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_MAP KEY_VALUE_GENERIC_TYPE tailMap(CLASS_TYPE fromKey) { return tailMap(OBJ_TO_KEY(fromKey)); }
|
||||
#else
|
||||
public KEY_TYPE POLL_FIRST_ENTRY_KEY();
|
||||
public KEY_TYPE POLL_LAST_ENTRY_KEY();
|
||||
|
||||
public VALUE_TYPE FIRST_ENTRY_VALUE();
|
||||
public VALUE_TYPE LAST_ENTRY_VALUE();
|
||||
#endif
|
||||
|
||||
interface FastSortedSet KEY_VALUE_GENERIC_TYPE extends MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE, ObjectSortedSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> {
|
||||
@Override
|
||||
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator();
|
||||
public ObjectBidirectionalIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator(KEY_TYPE fromElement);
|
||||
}
|
||||
}
|
||||
+275
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+220
@@ -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_KEY_BRACES ARRAY_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array) {
|
||||
return wrap(array, array.length);
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_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_KEY_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_KEY_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 ? COMPAREABLE_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(KEY_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(KEY_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(firstIndex != -1 && 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;i>=0;i--) {
|
||||
if(COMPAREABLE_TO_KEY(array[i], value) < 0)
|
||||
value = array[index = i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = index;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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+199
@@ -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_KEY_BRACES HEAP_PRIORITY_QUEUE KEY_GENERIC_TYPE wrap(KEY_TYPE[] array) {
|
||||
return wrap(array, array.length);
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_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_KEY_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_KEY_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(KEY_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(KEY_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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
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();
|
||||
public default KEY_TYPE LAST_KEY() { return PEEK(size()-1); }
|
||||
|
||||
#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()); }
|
||||
public default CLASS_TYPE last() { return peek(size()-1); }
|
||||
#endif
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
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 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 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
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
|
||||
public abstract class ABSTRACT_SET KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION KEY_GENERIC_TYPE implements SET KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public abstract ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 1;
|
||||
ITERATOR KEY_GENERIC_TYPE i = iterator();
|
||||
while(i.hasNext())
|
||||
hashCode = 31 * hashCode + KEY_TO_HASH(i.NEXT());
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this)
|
||||
return true;
|
||||
if (!(o instanceof Set))
|
||||
return false;
|
||||
Set<?> l = (Set<?>)o;
|
||||
if(l.size() != size()) return false;
|
||||
#if !TYPE_OBJECT
|
||||
if(l instanceof SET)
|
||||
{
|
||||
ITERATOR e1 = iterator();
|
||||
ITERATOR e2 = ((SET)l).iterator();
|
||||
while (e1.hasNext() && e2.hasNext()) {
|
||||
if(!(KEY_EQUALS(e1.NEXT(), e2.NEXT())))
|
||||
return false;
|
||||
}
|
||||
return !(e1.hasNext() || e2.hasNext());
|
||||
}
|
||||
#endif
|
||||
Iterator<CLASS_TYPE> e1 = iterator();
|
||||
Iterator<?> e2 = l.iterator();
|
||||
while (e1.hasNext() && e2.hasNext()) {
|
||||
if(!Objects.equals(e1.next(), e2.next()))
|
||||
return false;
|
||||
}
|
||||
return !(e1.hasNext() || e2.hasNext());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
import java.util.function.Consumer;
|
||||
#endif
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
#if PRIMITIVES
|
||||
import java.util.function.JAVA_PREDICATE;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.utils.ARRAYS;
|
||||
|
||||
public class ARRAY_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
protected transient KEY_TYPE[] data;
|
||||
protected int size = 0;
|
||||
|
||||
public ARRAY_SET() {
|
||||
data = EMPTY_KEY_ARRAY;
|
||||
}
|
||||
|
||||
public ARRAY_SET(int capacity) {
|
||||
data = NEW_KEY_ARRAY(capacity);
|
||||
}
|
||||
|
||||
public ARRAY_SET(KEY_TYPE[] array) {
|
||||
this(array, array.length);
|
||||
}
|
||||
|
||||
public ARRAY_SET(KEY_TYPE[] array, int length) {
|
||||
data = Arrays.copyOf(array, length);
|
||||
size = length;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ARRAY_SET(Collection<? extends CLASS_TYPE> c) {
|
||||
this(c.size());
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
public ARRAY_SET(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
this(c.size());
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ARRAY_SET(Set<? extends CLASS_TYPE> s) {
|
||||
this(s.size());
|
||||
for(CLASS_TYPE e : s)
|
||||
data[size++] = OBJ_TO_KEY(e);
|
||||
}
|
||||
|
||||
public ARRAY_SET(SET KEY_GENERIC_TYPE s) {
|
||||
this(s.size());
|
||||
for(KEY_TYPE e : s)
|
||||
data[size++] = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index == -1) {
|
||||
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
|
||||
data[size++] = o;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index == -1) {
|
||||
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
|
||||
System.arraycopy(data, 0, data, 1, size++);
|
||||
data[0] = o;
|
||||
return true;
|
||||
}
|
||||
else if(index != 0) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, 0, data, 1, index);
|
||||
data[0] = o;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index == -1) {
|
||||
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
|
||||
data[size++] = o;
|
||||
return true;
|
||||
}
|
||||
else if(index != size - 1) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, index+1, data, index, size - index);
|
||||
data[size-1] = o;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index > 0) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, 0, data, 1, index);
|
||||
data[0] = o;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index != -1 && index != size - 1) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, index+1, data, index, size - index - 1);
|
||||
data[size-1] = o;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
return findIndex(e) != -1;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(Object e) {
|
||||
return findIndex(e) != -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return data[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return data[size - 1];
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index != -1) {
|
||||
size--;
|
||||
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
|
||||
#if TYPE_OBJECT
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int index = findIndex(o);
|
||||
if(index != -1) {
|
||||
size--;
|
||||
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
|
||||
#if TYPE_OBJECT
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
KEY_TYPE result = data[0];
|
||||
System.arraycopy(data, 1, data, 0, --size);
|
||||
#if TYPE_OBJECT
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
size--;
|
||||
#if TYPE_OBJECT
|
||||
KEY_TYPE result = data[size];
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
return result;
|
||||
#else
|
||||
return data[size];
|
||||
#endif
|
||||
}
|
||||
#if PRIMITIVES
|
||||
@Override
|
||||
public boolean remIf(JAVA_PREDICATE KEY_GENERIC_TYPE filter) {
|
||||
Objects.requireNonNull(filter);
|
||||
boolean modified = false;
|
||||
int j = 0;
|
||||
for(int i = 0;i<size;i++) {
|
||||
if(!filter.test(data[i])) data[j++] = data[i];
|
||||
else modified = true;
|
||||
}
|
||||
size = j;
|
||||
return modified;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(Consumer KEY_SUPER_GENERIC_TYPE action) {
|
||||
Objects.requireNonNull(action);
|
||||
for(int i = 0;i<size;action.accept(data[i++]));
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void forEach(CONSUMER KEY_GENERIC_TYPE action) {
|
||||
Objects.requireNonNull(action);
|
||||
for(int i = 0;i<size;action.accept(data[i++]));
|
||||
}
|
||||
|
||||
#endif
|
||||
#if !TYPE_OBJECT
|
||||
protected int findIndex(KEY_TYPE o) {
|
||||
for(int i = size-1;i>=0;i--)
|
||||
if(KEY_EQUALS(data[i], o)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
protected int findIndex(Object o) {
|
||||
for(int i = size-1;i>=0;i--)
|
||||
if(EQUALS_KEY_TYPE(data[i], o)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
|
||||
int index = findIndex(fromElement);
|
||||
if(index != -1) return new SetIterator(index);
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) {
|
||||
int fromIndex = findIndex(fromElement);
|
||||
int toIndex = findIndex(toElement);
|
||||
if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
|
||||
return new SubSet(fromIndex, toIndex - fromIndex + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) {
|
||||
int toIndex = findIndex(toElement);
|
||||
if(toIndex == -1) throw new NoSuchElementException();
|
||||
return new SubSet(0, toIndex+1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) {
|
||||
int fromIndex = findIndex(fromElement);
|
||||
if(fromIndex == -1) throw new NoSuchElementException();
|
||||
return new SubSet(fromIndex, size - fromIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private class SubSet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE {
|
||||
int offset;
|
||||
int length;
|
||||
|
||||
SubSet(int offset, int length) {
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
int end() { return offset+length; }
|
||||
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index == -1) {
|
||||
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
|
||||
if(end() != size) System.arraycopy(data, end(), data, end()+1, size-(offset+length));
|
||||
data[end()] = o;
|
||||
size++;
|
||||
length++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index == -1) {
|
||||
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
|
||||
System.arraycopy(data, offset, data, offset+1, size-offset);
|
||||
data[offset] = o;
|
||||
size++;
|
||||
length++;
|
||||
return true;
|
||||
}
|
||||
else if(index != 0) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, offset, data, offset+1, index-offset);
|
||||
data[offset] = o;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index == -1) {
|
||||
if(data.length == size) data = Arrays.copyOf(data, size == 0 ? 2 : size * 2);
|
||||
System.arraycopy(data, end()+1, data, end(), size-end());
|
||||
data[end()] = o;
|
||||
size++;
|
||||
length++;
|
||||
return true;
|
||||
}
|
||||
else if(index != 0) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, offset+1, data, offset, index-offset);
|
||||
data[offset+length] = o;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index > offset) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, offset, data, offset+1, index-offset);
|
||||
data[offset] = o;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index != -1 && index < end()-1) {
|
||||
o = data[index];
|
||||
System.arraycopy(data, index+1, data, index, end()-index-1);
|
||||
data[end()-1] = o;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE e) {
|
||||
return findIndex(e) != -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean contains(Object e) {
|
||||
return findIndex(e) != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() {
|
||||
if(length == 0) throw new NoSuchElementException();
|
||||
return data[offset];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() {
|
||||
if(length == 0) throw new NoSuchElementException();
|
||||
return data[end()-1];
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
int index = findIndex(o);
|
||||
if(index != -1) {
|
||||
size--;
|
||||
length--;
|
||||
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
int index = findIndex(o);
|
||||
if(index != -1) {
|
||||
size--;
|
||||
length--;
|
||||
if(index != size) System.arraycopy(data, index+1, data, index, size - index);
|
||||
#if TYPE_OBJECT
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() {
|
||||
if(length == 0) throw new NoSuchElementException();
|
||||
size--;
|
||||
length--;
|
||||
KEY_TYPE result = data[offset];
|
||||
System.arraycopy(data, offset+1, data, offset, size-offset);
|
||||
#if TYPE_OBJECT
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() {
|
||||
if(length == 0) throw new NoSuchElementException();
|
||||
KEY_TYPE result = data[offset+length];
|
||||
size--;
|
||||
length--;
|
||||
System.arraycopy(data, end()+1, data, end(), size-end());
|
||||
#if TYPE_OBJECT
|
||||
data[size] = EMPTY_KEY_VALUE;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
|
||||
int index = findIndex(fromElement);
|
||||
if(index != -1) return new SetIterator(index);
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) {
|
||||
int fromIndex = findIndex(fromElement);
|
||||
int toIndex = findIndex(toElement);
|
||||
if(fromIndex == -1 || toIndex == -1) throw new NoSuchElementException();
|
||||
return new SubSet(fromIndex, toIndex - fromIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) {
|
||||
int toIndex = findIndex(toElement);
|
||||
if(toIndex == -1) throw new NoSuchElementException();
|
||||
return new SubSet(0, toIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) {
|
||||
int fromIndex = findIndex(fromElement);
|
||||
if(fromIndex == -1) throw new NoSuchElementException();
|
||||
return new SubSet(fromIndex, size - fromIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return length;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
protected int findIndex(KEY_TYPE o) {
|
||||
for(int i = length-1;i>=0;i--)
|
||||
if(KEY_EQUALS(data[offset+i], o)) return i + offset;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
protected int findIndex(Object o) {
|
||||
for(int i = length-1;i>=0;i--)
|
||||
if(EQUALS_KEY_TYPE(data[offset+i], o)) return i + offset;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
int index;
|
||||
int lastReturned = -1;
|
||||
|
||||
public SetIterator(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
lastReturned = index;
|
||||
return data[index++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return index > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
lastReturned = index;
|
||||
return data[index--];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return index-1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(lastReturned == -1)
|
||||
throw new IllegalStateException();
|
||||
SubSet.this.remove(data[lastReturned]);
|
||||
if(lastReturned < index)
|
||||
index--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void set(Object e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(Object e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public int skip(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int steps = Math.min(amount, (size() - 1) - index);
|
||||
index += steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int back(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int steps = Math.min(amount, index);
|
||||
index -= steps;
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
int index;
|
||||
int lastReturned = -1;
|
||||
|
||||
public SetIterator(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
lastReturned = index;
|
||||
return data[index++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return index > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
lastReturned = index;
|
||||
return data[index--];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return index-1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(lastReturned == -1)
|
||||
throw new IllegalStateException();
|
||||
ARRAY_SET.this.remove(data[lastReturned]);
|
||||
if(lastReturned < index)
|
||||
index--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void set(Object e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(Object e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public int skip(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int steps = Math.min(amount, (size() - 1) - index);
|
||||
index += steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int back(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int steps = Math.min(amount, index);
|
||||
index -= steps;
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
+556
@@ -0,0 +1,556 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#endif
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.STRATEGY;
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class LINKED_CUSTOM_HASH_SET KEY_GENERIC_TYPE extends CUSTOM_HASH_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
protected long[] links;
|
||||
protected int firstIndex = -1;
|
||||
protected int lastIndex = -1;
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(int minCapacity, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(int minCapacity, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
super(minCapacity, loadFactor, strategy);
|
||||
links = new long[nullIndex + 1];
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(KEY_TYPE[] array, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(array, 0, array.length, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(KEY_TYPE[] array, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(array, 0, array.length, loadFactor, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(KEY_TYPE[] array, int offset, int length, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(array, offset, length, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(length < 0 ? 0 : length, strategy);
|
||||
SanityChecks.checkArrayCapacity(array.length, offset, length);
|
||||
for(int i = 0;i<length;i++) add(array[offset+i]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LINKED_CUSTOM_HASH_SET(Collection<? extends CLASS_TYPE> collection, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LINKED_CUSTOM_HASH_SET(Collection<? extends CLASS_TYPE> collection, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection.size(), loadFactor, strategy);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection.size(), strategy);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(Iterator<CLASS_TYPE> iterator, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(Iterator<CLASS_TYPE> iterator, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
#if !TYPE_OBJECT
|
||||
this(ITERATORS.wrap(iterator), loadFactor, strategy);
|
||||
#else
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor, strategy);
|
||||
while(iterator.hasNext()) add(iterator.next());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public LINKED_CUSTOM_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public LINKED_CUSTOM_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor, strategy);
|
||||
while(iterator.hasNext()) add(iterator.NEXT());
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) {
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return false;
|
||||
}
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], o)) {
|
||||
moveToFirstIndex(pos);
|
||||
return false;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) {
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return false;
|
||||
}
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], o)) {
|
||||
moveToLastIndex(pos);
|
||||
return false;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) {
|
||||
if(strategy.equals(FIRST_KEY(), o)) return false;
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], o)) {
|
||||
moveToFirstIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) {
|
||||
if(strategy.equals(LAST_KEY(), o)) return false;
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], o)) {
|
||||
moveToLastIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFirstIndex(int startPos) {
|
||||
if(size == 1 || firstIndex == startPos) return;
|
||||
if(lastIndex == startPos) {
|
||||
lastIndex = (int)(links[startPos] >>> 32);
|
||||
links[lastIndex] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[startPos] = 0xFFFFFFFF00000000L | (firstIndex & 0xFFFFFFFFL);
|
||||
firstIndex = startPos;
|
||||
}
|
||||
|
||||
protected void moveToLastIndex(int startPos) {
|
||||
if(size == 1 || lastIndex == startPos) return;
|
||||
if(firstIndex == startPos) {
|
||||
firstIndex = (int)links[startPos];
|
||||
links[lastIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
|
||||
lastIndex = startPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[firstIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = firstIndex;
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[lastIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = lastIndex;
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(strategy.equals(result, EMPTY_KEY_VALUE)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeAdded(int pos) {
|
||||
if(size == 0) {
|
||||
firstIndex = lastIndex = pos;
|
||||
links[pos] = -1L;
|
||||
}
|
||||
else {
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
|
||||
lastIndex = pos;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeRemoved(int pos) {
|
||||
if(size == 0) firstIndex = lastIndex = -1;
|
||||
else if(firstIndex == pos) {
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else if(lastIndex == pos) {
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[pos] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[pos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
if(size == 1) {
|
||||
firstIndex = lastIndex = to;
|
||||
links[to] = -1L;
|
||||
}
|
||||
else if(firstIndex == from) {
|
||||
firstIndex = to;
|
||||
links[(int)links[from]] ^= ((links[(int)links[from]] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else if(lastIndex == from) {
|
||||
lastIndex = to;
|
||||
links[(int)(links[from] >>> 32)] ^= ((links[(int)(links[from] >>> 32)] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else {
|
||||
long link = links[from];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = link;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rehash(int newSize) {
|
||||
int newMask = newSize - 1;
|
||||
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
|
||||
long[] newLinks = new long[newSize + 1];
|
||||
int newPrev = -1;
|
||||
for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
|
||||
if(strategy.equals(keys[i], EMPTY_KEY_VALUE)) pos = newSize;
|
||||
else {
|
||||
pos = HashUtil.mix(strategy.hashCode(keys[i])) & newMask;
|
||||
while(!strategy.equals(newKeys[pos], EMPTY_KEY_VALUE)) pos = ++pos & newMask;
|
||||
}
|
||||
newKeys[pos] = keys[i];
|
||||
if(prev != -1) {
|
||||
newLinks[newPrev] ^= ((newLinks[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
newLinks[pos] ^= ((newLinks[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
newPrev = pos;
|
||||
}
|
||||
else {
|
||||
newPrev = firstIndex = pos;
|
||||
newLinks[pos] = -1L;
|
||||
}
|
||||
i = (int)links[prev = i];
|
||||
}
|
||||
links = newLinks;
|
||||
lastIndex = newPrev;
|
||||
if(newPrev != -1) newLinks[newPrev] |= 0xFFFFFFFFL;
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
firstIndex = lastIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
|
||||
return new SetIterator(fromElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
int previous = -1;
|
||||
int next = -1;
|
||||
int current = -1;
|
||||
int index = 0;
|
||||
|
||||
SetIterator() {
|
||||
next = firstIndex;
|
||||
}
|
||||
|
||||
SetIterator(KEY_TYPE from) {
|
||||
if(strategy.equals(from, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) {
|
||||
next = (int) links[nullIndex];
|
||||
previous = nullIndex;
|
||||
}
|
||||
else throw new NoSuchElementException("The null element is not in the set");
|
||||
}
|
||||
else if(strategy.equals(keys[lastIndex], from)) {
|
||||
previous = lastIndex;
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(from)) & mask;
|
||||
while(!strategy.equals(keys[pos], EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(keys[pos], from)) {
|
||||
next = (int)links[pos];
|
||||
previous = pos;
|
||||
break;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
if(previous == -1 && next == -1)
|
||||
throw new NoSuchElementException("The element was not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return previous != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
ensureIndexKnown();
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
ensureIndexKnown();
|
||||
return index - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(current == -1) throw new IllegalStateException();
|
||||
ensureIndexKnown();
|
||||
if(current == previous) {
|
||||
index--;
|
||||
previous = (int)(links[current] >>> 32);
|
||||
}
|
||||
else next = (int)links[current];
|
||||
size--;
|
||||
if(previous == -1) firstIndex = next;
|
||||
else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
|
||||
if (next == -1) lastIndex = previous;
|
||||
else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
if(current == nullIndex) {
|
||||
current = -1;
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else {
|
||||
int slot, last, startPos = current;
|
||||
current = -1;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(strategy.hashCode(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
if(next == startPos) next = last;
|
||||
if(previous == startPos) previous = last;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
current = previous;
|
||||
previous = (int)(links[current] >> 32);
|
||||
next = current;
|
||||
if(index >= 0) index--;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
current = next;
|
||||
next = (int)(links[current]);
|
||||
previous = current;
|
||||
if(index >= 0) index++;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
private void ensureIndexKnown() {
|
||||
if(index == -1) {
|
||||
if(previous == -1) {
|
||||
index = 0;
|
||||
}
|
||||
else if(next == -1) {
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
index = 1;
|
||||
for(int pos = firstIndex;pos != previous;pos = (int)links[pos], index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void set(Object e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(Object e) { throw new UnsupportedOperationException(); }
|
||||
#else
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+558
@@ -0,0 +1,558 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#endif
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Objects;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class LINKED_HASH_SET KEY_GENERIC_TYPE extends HASH_SET KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
protected long[] links;
|
||||
protected int firstIndex = -1;
|
||||
protected int lastIndex = -1;
|
||||
|
||||
public LINKED_HASH_SET() {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(int minCapacity) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(int minCapacity, float loadFactor) {
|
||||
super(minCapacity, loadFactor);
|
||||
links = new long[nullIndex + 1];
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array) {
|
||||
this(array, 0, array.length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array, float loadFactor) {
|
||||
this(array, 0, array.length, loadFactor);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array, int offset, int length) {
|
||||
this(array, offset, length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor) {
|
||||
this(length < 0 ? 0 : length);
|
||||
SanityChecks.checkArrayCapacity(array.length, offset, length);
|
||||
for(int i = 0;i<length;i++) add(array[offset+i]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LINKED_HASH_SET(Collection<? extends CLASS_TYPE> collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LINKED_HASH_SET(Collection<? extends CLASS_TYPE> collection, float loadFactor) {
|
||||
this(collection.size(), loadFactor);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, float loadFactor) {
|
||||
this(collection.size());
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(Iterator<CLASS_TYPE> iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(Iterator<CLASS_TYPE> iterator, float loadFactor) {
|
||||
#if !TYPE_OBJECT
|
||||
this(ITERATORS.wrap(iterator), loadFactor);
|
||||
#else
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.next());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public LINKED_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public LINKED_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, float loadFactor) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.NEXT());
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) {
|
||||
if(KEY_EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return false;
|
||||
}
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
while(KEY_EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(KEY_EQUALS(keys[pos], o)) {
|
||||
moveToFirstIndex(pos);
|
||||
return false;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) {
|
||||
if(KEY_EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return false;
|
||||
}
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
while(KEY_EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(KEY_EQUALS(keys[pos], o)) {
|
||||
moveToLastIndex(pos);
|
||||
return false;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) {
|
||||
if(KEY_EQUALS(FIRST_KEY(), o)) return false;
|
||||
if(KEY_EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToFirstIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
while(KEY_EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(KEY_EQUALS(keys[pos], o)) {
|
||||
moveToFirstIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) {
|
||||
if(KEY_EQUALS(LAST_KEY(), o)) return false;
|
||||
if(KEY_EQUALS_NULL(o)) {
|
||||
if(containsNull) {
|
||||
moveToLastIndex(nullIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
while(KEY_EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(KEY_EQUALS(keys[pos], o)) {
|
||||
moveToLastIndex(pos);
|
||||
return true;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void moveToFirstIndex(int startPos) {
|
||||
if(size == 1 || firstIndex == startPos) return;
|
||||
if(lastIndex == startPos) {
|
||||
lastIndex = (int)(links[startPos] >>> 32);
|
||||
links[lastIndex] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[firstIndex] ^= ((links[firstIndex] ^ ((startPos & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[startPos] = 0xFFFFFFFF00000000L | (firstIndex & 0xFFFFFFFFL);
|
||||
firstIndex = startPos;
|
||||
}
|
||||
|
||||
protected void moveToLastIndex(int startPos) {
|
||||
if(size == 1 || lastIndex == startPos) return;
|
||||
if(firstIndex == startPos) {
|
||||
firstIndex = (int)links[startPos];
|
||||
links[lastIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else {
|
||||
long link = links[startPos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (startPos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[startPos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
|
||||
lastIndex = startPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[firstIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = firstIndex;
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(KEY_EQUALS_NULL(result)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
return keys[lastIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() {
|
||||
if(size == 0) throw new NoSuchElementException();
|
||||
int pos = lastIndex;
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[lastIndex] |= 0xFFFFFFFFL;
|
||||
KEY_TYPE result = keys[pos];
|
||||
size--;
|
||||
if(KEY_EQUALS_NULL(result)) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeAdded(int pos) {
|
||||
if(size == 0) {
|
||||
firstIndex = lastIndex = pos;
|
||||
links[pos] = -1L;
|
||||
}
|
||||
else {
|
||||
links[lastIndex] ^= ((links[lastIndex] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[pos] = ((lastIndex & 0xFFFFFFFFL) << 32) | 0xFFFFFFFFL;
|
||||
lastIndex = pos;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeRemoved(int pos) {
|
||||
if(size == 0) firstIndex = lastIndex = -1;
|
||||
else if(firstIndex == pos) {
|
||||
firstIndex = (int)links[pos];
|
||||
if(0 <= firstIndex) links[firstIndex] |= 0xFFFFFFFF00000000L;
|
||||
}
|
||||
else if(lastIndex == pos) {
|
||||
lastIndex = (int)(links[pos] >>> 32);
|
||||
if(0 <= lastIndex) links[pos] |= 0xFFFFFFFFL;
|
||||
}
|
||||
else {
|
||||
long link = links[pos];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (link & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ (link & 0xFFFFFFFF00000000L)) & 0xFFFFFFFF00000000L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
if(size == 1) {
|
||||
firstIndex = lastIndex = to;
|
||||
links[to] = -1L;
|
||||
}
|
||||
else if(firstIndex == from) {
|
||||
firstIndex = to;
|
||||
links[(int)links[from]] ^= ((links[(int)links[from]] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else if(lastIndex == from) {
|
||||
lastIndex = to;
|
||||
links[(int)(links[from] >>> 32)] ^= ((links[(int)(links[from] >>> 32)] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[to] = links[from];
|
||||
}
|
||||
else {
|
||||
long link = links[from];
|
||||
int prev = (int)(link >>> 32);
|
||||
int next = (int)link;
|
||||
links[prev] ^= ((links[prev] ^ (to & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
links[next] ^= ((links[next] ^ ((to & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
links[to] = link;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rehash(int newSize) {
|
||||
int newMask = newSize - 1;
|
||||
KEY_TYPE[] newKeys = NEW_KEY_ARRAY(newSize + 1);
|
||||
long[] newLinks = new long[newSize + 1];
|
||||
int newPrev = -1;
|
||||
for(int j = size, i = firstIndex, pos = 0, prev = -1;j != 0;) {
|
||||
if(KEY_EQUALS_NULL(keys[i])) pos = newSize;
|
||||
else {
|
||||
pos = HashUtil.mix(KEY_TO_HASH(keys[i])) & newMask;
|
||||
while(KEY_EQUALS_NOT_NULL(newKeys[pos])) pos = ++pos & newMask;
|
||||
}
|
||||
newKeys[pos] = keys[i];
|
||||
if(prev != -1) {
|
||||
newLinks[newPrev] ^= ((newLinks[newPrev] ^ (pos & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
newLinks[pos] ^= ((newLinks[pos] ^ ((newPrev & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
newPrev = pos;
|
||||
}
|
||||
else {
|
||||
newPrev = firstIndex = pos;
|
||||
newLinks[pos] = -1L;
|
||||
}
|
||||
i = (int)links[prev = i];
|
||||
}
|
||||
links = newLinks;
|
||||
lastIndex = newPrev;
|
||||
if(newPrev != -1) newLinks[newPrev] |= 0xFFFFFFFFL;
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
firstIndex = lastIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) {
|
||||
return new SetIterator(fromElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() { return null; }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { throw new UnsupportedOperationException(); }
|
||||
|
||||
private class SetIterator implements LIST_ITERATOR KEY_GENERIC_TYPE {
|
||||
int previous = -1;
|
||||
int next = -1;
|
||||
int current = -1;
|
||||
int index = 0;
|
||||
|
||||
SetIterator() {
|
||||
next = firstIndex;
|
||||
}
|
||||
|
||||
SetIterator(KEY_TYPE from) {
|
||||
if(KEY_EQUALS_NULL(from)) {
|
||||
if(containsNull) {
|
||||
next = (int) links[nullIndex];
|
||||
previous = nullIndex;
|
||||
}
|
||||
else throw new NoSuchElementException("The null element is not in the set");
|
||||
}
|
||||
else if(KEY_EQUALS(keys[lastIndex], from)) {
|
||||
previous = lastIndex;
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(from)) & mask;
|
||||
while(KEY_EQUALS_NOT_NULL(keys[pos])) {
|
||||
if(KEY_EQUALS(keys[pos], from)) {
|
||||
next = (int)links[pos];
|
||||
previous = pos;
|
||||
break;
|
||||
}
|
||||
pos = ++pos & mask;
|
||||
}
|
||||
if(previous == -1 && next == -1)
|
||||
throw new NoSuchElementException("The element was not found");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return previous != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
ensureIndexKnown();
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
ensureIndexKnown();
|
||||
return index - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(current == -1) throw new IllegalStateException();
|
||||
ensureIndexKnown();
|
||||
if(current == previous) {
|
||||
index--;
|
||||
previous = (int)(links[current] >>> 32);
|
||||
}
|
||||
else next = (int)links[current];
|
||||
size--;
|
||||
if(previous == -1) firstIndex = next;
|
||||
else links[previous] ^= ((links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL);
|
||||
|
||||
if (next == -1) lastIndex = previous;
|
||||
else links[next] ^= ((links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L);
|
||||
if(current == nullIndex) {
|
||||
current = -1;
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else {
|
||||
int slot, last, startPos = current;
|
||||
current = -1;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(KEY_EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
if(next == startPos) next = last;
|
||||
if(previous == startPos) previous = last;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
if(!hasPrevious()) throw new NoSuchElementException();
|
||||
current = previous;
|
||||
previous = (int)(links[current] >> 32);
|
||||
next = current;
|
||||
if(index >= 0) index--;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
current = next;
|
||||
next = (int)(links[current]);
|
||||
previous = current;
|
||||
if(index >= 0) index++;
|
||||
return keys[current];
|
||||
}
|
||||
|
||||
private void ensureIndexKnown() {
|
||||
if(index == -1) {
|
||||
if(previous == -1) {
|
||||
index = 0;
|
||||
}
|
||||
else if(next == -1) {
|
||||
index = size;
|
||||
}
|
||||
else {
|
||||
index = 1;
|
||||
for(int pos = firstIndex;pos != previous;pos = (int)links[pos], index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public void set(Object e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(Object e) { throw new UnsupportedOperationException(); }
|
||||
#else
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.NavigableSet;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
|
||||
public interface NAVIGABLE_SET KEY_GENERIC_TYPE extends NavigableSet<CLASS_TYPE>, SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
public KEY_TYPE lower(KEY_TYPE e);
|
||||
|
||||
public KEY_TYPE floor(KEY_TYPE e);
|
||||
|
||||
public KEY_TYPE ceiling(KEY_TYPE e);
|
||||
|
||||
public KEY_TYPE higher(KEY_TYPE e);
|
||||
|
||||
public void setDefaultMaxValue(KEY_TYPE e);
|
||||
|
||||
public KEY_TYPE getDefaultMaxValue();
|
||||
|
||||
public void setDefaultMinValue(KEY_TYPE e);
|
||||
|
||||
public KEY_TYPE getDefaultMinValue();
|
||||
|
||||
@Override
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { return subSet(fromElement, true, toElement, false); }
|
||||
|
||||
@Override
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { return headSet(toElement, false); }
|
||||
|
||||
@Override
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { return tailSet(fromElement, true); }
|
||||
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive);
|
||||
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive);
|
||||
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive);
|
||||
|
||||
#else
|
||||
@Override
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { return subSet(fromElement, true, toElement, false); }
|
||||
|
||||
@Override
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { return headSet(toElement, false); }
|
||||
|
||||
@Override
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { return tailSet(fromElement, true); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive);
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive);
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive);
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator();
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE lower(CLASS_TYPE e) { return KEY_TO_OBJ(lower(OBJ_TO_KEY(e))); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE floor(CLASS_TYPE e) { return KEY_TO_OBJ(floor(OBJ_TO_KEY(e))); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE ceiling(CLASS_TYPE e) { return KEY_TO_OBJ(ceiling(OBJ_TO_KEY(e))); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE higher(CLASS_TYPE e) { return KEY_TO_OBJ(higher(OBJ_TO_KEY(e))); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
default CLASS_TYPE first() { return SORTED_SET.super.first(); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
default CLASS_TYPE last() { return SORTED_SET.super.last(); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE pollFirst() { return KEY_TO_OBJ(POLL_FIRST_KEY()); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE pollLast() { return KEY_TO_OBJ(POLL_LAST_KEY()); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, boolean fromInclusive, CLASS_TYPE toElement, boolean toInclusive) { return subSet(OBJ_TO_KEY(fromElement), fromInclusive, OBJ_TO_KEY(toElement), toInclusive); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement, boolean inclusive) { return headSet(OBJ_TO_KEY(toElement), inclusive); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement, boolean inclusive) { return tailSet(OBJ_TO_KEY(fromElement), inclusive); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement) { return SORTED_SET.super.subSet(fromElement, toElement); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement) { return SORTED_SET.super.headSet(toElement); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement) { return SORTED_SET.super.tailSet(fromElement); }
|
||||
#endif
|
||||
}
|
||||
+391
@@ -0,0 +1,391 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.STRATEGY;
|
||||
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
import speiger.src.collections.utils.ITrimmable;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class CUSTOM_HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements ITrimmable
|
||||
{
|
||||
protected transient KEY_TYPE[] keys;
|
||||
protected transient boolean containsNull;
|
||||
protected transient int minCapacity;
|
||||
protected transient int nullIndex;
|
||||
protected transient int maxFill;
|
||||
protected transient int mask;
|
||||
|
||||
protected int size;
|
||||
protected final float loadFactor;
|
||||
protected final STRATEGY KEY_SUPER_GENERIC_TYPE strategy;
|
||||
|
||||
public CUSTOM_HASH_SET(STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(int minCapacity, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(int minCapacity, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
|
||||
if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
|
||||
this.loadFactor = loadFactor;
|
||||
this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
|
||||
mask = nullIndex - 1;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = NEW_KEY_ARRAY(nullIndex + 1);
|
||||
this.strategy = strategy;
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(KEY_TYPE[] array, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(array, 0, array.length, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(KEY_TYPE[] array, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(array, 0, array.length, loadFactor, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(KEY_TYPE[] array, int offset, int length, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(array, offset, length, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(length < 0 ? 0 : length, strategy);
|
||||
SanityChecks.checkArrayCapacity(array.length, offset, length);
|
||||
for(int i = 0;i<length;i++) add(array[offset+i]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public CUSTOM_HASH_SET(Collection<? extends CLASS_TYPE> collection, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public CUSTOM_HASH_SET(Collection<? extends CLASS_TYPE> collection, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection.size(), loadFactor, strategy);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(collection.size(), strategy);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(Iterator<CLASS_TYPE> iterator, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(Iterator<CLASS_TYPE> iterator, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
#if !TYPE_OBJECT
|
||||
this(ITERATORS.wrap(iterator), loadFactor, strategy);
|
||||
#else
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor, strategy);
|
||||
while(iterator.hasNext()) add(iterator.next());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public CUSTOM_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR, strategy);
|
||||
}
|
||||
|
||||
public CUSTOM_HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, float loadFactor, STRATEGY KEY_SUPER_GENERIC_TYPE strategy) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor, strategy);
|
||||
while(iterator.hasNext()) add(iterator.NEXT());
|
||||
}
|
||||
|
||||
#endif
|
||||
public STRATEGY KEY_SUPER_GENERIC_TYPE getStrategy() {
|
||||
return strategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) {
|
||||
if(containsNull) return false;
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(!strategy.equals(current, EMPTY_KEY_VALUE)) {
|
||||
if(strategy.equals(current, o)) return false;
|
||||
while(!strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE))
|
||||
if(strategy.equals(current, o)) return false;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean addAll(Collection<? extends CLASS_TYPE> c) {
|
||||
if(loadFactor <= 0.5F) ensureCapacity(c.size());
|
||||
else ensureCapacity(c.size() + size());
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
if(loadFactor <= 0.5F) ensureCapacity(c.size());
|
||||
else ensureCapacity(c.size() + size());
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
#if TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if(strategy.equals((KEY_TYPE)o, EMPTY_KEY_VALUE)) return containsNull;
|
||||
int pos = HashUtil.mix(strategy.hashCode((KEY_TYPE)o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
|
||||
if(strategy.equals(current, (KEY_TYPE)o)) return true;
|
||||
while(true) {
|
||||
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
|
||||
else if(strategy.equals(current, (KEY_TYPE)o)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(strategy.equals((KEY_TYPE)o, EMPTY_KEY_VALUE)) return (containsNull ? removeNullIndex() : false);
|
||||
int pos = HashUtil.mix(strategy.hashCode((KEY_TYPE)o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
|
||||
if(strategy.equals(current, (KEY_TYPE)o)) return removeIndex(pos);
|
||||
while(true) {
|
||||
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
|
||||
else if(strategy.equals(current, (KEY_TYPE)o)) return removeIndex(pos);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) {
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) return containsNull;
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
|
||||
if(strategy.equals(current, o)) return true;
|
||||
while(true) {
|
||||
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
|
||||
else if(strategy.equals(current, o)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
if(strategy.equals(o, EMPTY_KEY_VALUE)) return (containsNull ? removeNullIndex() : false);
|
||||
int pos = HashUtil.mix(strategy.hashCode(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(strategy.equals(current, EMPTY_KEY_VALUE)) return false;
|
||||
if(strategy.equals(current, o)) return removeIndex(pos);
|
||||
while(true) {
|
||||
if(strategy.equals((current = keys[pos = (++pos & mask)]), EMPTY_KEY_VALUE)) return false;
|
||||
else if(strategy.equals(current, o)) return removeIndex(pos);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean trim(int size) {
|
||||
int newSize = HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor));
|
||||
if(newSize >= nullIndex || size >= Math.min((int)Math.ceil(newSize * loadFactor), newSize - 1)) return false;
|
||||
try {
|
||||
rehash(newSize);
|
||||
}
|
||||
catch(OutOfMemoryError e) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ensureCapacity(int newCapacity) {
|
||||
int size = HashUtil.arraySize(newCapacity, loadFactor);
|
||||
if(size > nullIndex) rehash(size);
|
||||
}
|
||||
|
||||
protected boolean removeIndex(int pos) {
|
||||
size--;
|
||||
onNodeRemoved(pos);
|
||||
shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean removeNullIndex() {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
size--;
|
||||
onNodeRemoved(nullIndex);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onNodeAdded(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeRemoved(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
|
||||
}
|
||||
|
||||
protected void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(strategy.hashCode(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
|
||||
protected void rehash(int newSize) {
|
||||
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));
|
||||
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];
|
||||
}
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(size == 0) return;
|
||||
size = 0;
|
||||
containsNull = false;
|
||||
Arrays.fill(keys, EMPTY_KEY_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
|
||||
int pos = nullIndex;
|
||||
int lastReturned = -1;
|
||||
int nextIndex = Integer.MIN_VALUE;
|
||||
boolean returnNull = containsNull;
|
||||
LIST KEY_GENERIC_TYPE wrapped = null;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if(nextIndex == Integer.MIN_VALUE) {
|
||||
if(returnNull) {
|
||||
returnNull = false;
|
||||
nextIndex = nullIndex;
|
||||
}
|
||||
else {
|
||||
while(true) {
|
||||
if(--pos < 0) {
|
||||
if(wrapped == null || wrapped.size() <= -pos - 1) break;
|
||||
nextIndex = -pos - 1;
|
||||
break;
|
||||
}
|
||||
if(KEY_EQUALS_NOT_NULL(keys[pos])){
|
||||
nextIndex = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextIndex != Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
if(nextIndex < 0){
|
||||
lastReturned = Integer.MAX_VALUE;
|
||||
KEY_TYPE value = wrapped.GET_KEY(nextIndex);
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
KEY_TYPE value = keys[(lastReturned = nextIndex)];
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(lastReturned == -1) throw new IllegalStateException();
|
||||
if(lastReturned == nullIndex) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else if(pos >= 0) shiftKeys(pos);
|
||||
else {
|
||||
CUSTOM_HASH_SET.this.remove(wrapped.GET_KEY(-pos - 1));
|
||||
return;
|
||||
}
|
||||
size--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
private void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(strategy.equals((current = keys[startPos]), EMPTY_KEY_VALUE)) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(strategy.hashCode(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
if(startPos < last) {
|
||||
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
|
||||
wrapped.add(keys[startPos]);
|
||||
}
|
||||
keys[last] = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.lists.ARRAY_LIST;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
#endif
|
||||
import speiger.src.collections.utils.HashUtil;
|
||||
import speiger.src.collections.utils.ITrimmable;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
public class HASH_SET KEY_GENERIC_TYPE extends ABSTRACT_SET KEY_GENERIC_TYPE implements ITrimmable
|
||||
{
|
||||
protected transient KEY_TYPE[] keys;
|
||||
protected transient boolean containsNull;
|
||||
protected transient int minCapacity;
|
||||
protected transient int nullIndex;
|
||||
protected transient int maxFill;
|
||||
protected transient int mask;
|
||||
|
||||
protected int size;
|
||||
protected final float loadFactor;
|
||||
|
||||
public HASH_SET() {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(int minCapacity) {
|
||||
this(minCapacity, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(int minCapacity, float loadFactor) {
|
||||
if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed");
|
||||
if(loadFactor <= 0 || loadFactor >= 1F) throw new IllegalStateException("Load Factor is not between 0 and 1");
|
||||
this.loadFactor = loadFactor;
|
||||
this.minCapacity = nullIndex = HashUtil.arraySize(minCapacity, loadFactor);
|
||||
mask = nullIndex - 1;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = NEW_KEY_ARRAY(nullIndex + 1);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array) {
|
||||
this(array, 0, array.length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array, float loadFactor) {
|
||||
this(array, 0, array.length, loadFactor);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array, int offset, int length) {
|
||||
this(array, offset, length, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(KEY_TYPE[] array, int offset, int length, float loadFactor) {
|
||||
this(length < 0 ? 0 : length);
|
||||
SanityChecks.checkArrayCapacity(array.length, offset, length);
|
||||
for(int i = 0;i<length;i++) add(array[offset+i]);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public HASH_SET(Collection<? extends CLASS_TYPE> collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public HASH_SET(Collection<? extends CLASS_TYPE> collection, float loadFactor) {
|
||||
this(collection.size(), loadFactor);
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public HASH_SET(COLLECTION KEY_GENERIC_TYPE collection) {
|
||||
this(collection, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(COLLECTION KEY_GENERIC_TYPE collection, float loadFactor) {
|
||||
this(collection.size());
|
||||
addAll(collection);
|
||||
}
|
||||
|
||||
public HASH_SET(Iterator<CLASS_TYPE> iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(Iterator<CLASS_TYPE> iterator, float loadFactor) {
|
||||
#if !TYPE_OBJECT
|
||||
this(ITERATORS.wrap(iterator), loadFactor);
|
||||
#else
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.next());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
this(iterator, HashUtil.DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
public HASH_SET(ITERATOR KEY_GENERIC_TYPE iterator, float loadFactor) {
|
||||
this(HashUtil.DEFAULT_MIN_CAPACITY, loadFactor);
|
||||
while(iterator.hasNext()) add(iterator.NEXT());
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) {
|
||||
if(KEY_EQUALS_NULL(o)) {
|
||||
if(containsNull) return false;
|
||||
containsNull = true;
|
||||
onNodeAdded(nullIndex);
|
||||
}
|
||||
else {
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NOT_NULL(current)) {
|
||||
if(KEY_EQUALS(current, o)) return false;
|
||||
while(KEY_EQUALS_NOT_NULL((current = keys[pos = (++pos & mask)])))
|
||||
if(KEY_EQUALS(current, o)) return false;
|
||||
}
|
||||
keys[pos] = o;
|
||||
onNodeAdded(pos);
|
||||
}
|
||||
if(size++ >= maxFill) rehash(HashUtil.arraySize(size+1, loadFactor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean addAll(Collection<? extends CLASS_TYPE> c) {
|
||||
if(loadFactor <= 0.5F) ensureCapacity(c.size());
|
||||
else ensureCapacity(c.size() + size());
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
if(loadFactor <= 0.5F) ensureCapacity(c.size());
|
||||
else ensureCapacity(c.size() + size());
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if(o == null) return containsNull;
|
||||
int pos = HashUtil.mix(o.hashCode()) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NULL(current)) return false;
|
||||
if(EQUALS_KEY_TYPE(current, o)) return true;
|
||||
while(true) {
|
||||
if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
|
||||
else if(EQUALS_KEY_TYPE(current, o)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if(o == null) return (containsNull ? removeNullIndex() : false);
|
||||
int pos = HashUtil.mix(o.hashCode()) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NULL(current)) return false;
|
||||
if(EQUALS_KEY_TYPE(current, o)) return removeIndex(pos);
|
||||
while(true) {
|
||||
if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
|
||||
else if(EQUALS_KEY_TYPE(current, o)) return removeIndex(pos);
|
||||
}
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) {
|
||||
if(KEY_EQUALS_NULL(o)) return containsNull;
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NULL(current)) return false;
|
||||
if(KEY_EQUALS(current, o)) return true;
|
||||
while(true) {
|
||||
if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
|
||||
else if(KEY_EQUALS(current, o)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) {
|
||||
if(KEY_EQUALS_NULL(o)) return (containsNull ? removeNullIndex() : false);
|
||||
int pos = HashUtil.mix(KEY_TO_HASH(o)) & mask;
|
||||
KEY_TYPE current = keys[pos];
|
||||
if(KEY_EQUALS_NULL(current)) return false;
|
||||
if(KEY_EQUALS(current, o)) return removeIndex(pos);
|
||||
while(true) {
|
||||
if(KEY_EQUALS_NULL((current = keys[pos = (++pos & mask)]))) return false;
|
||||
else if(KEY_EQUALS(current, o)) return removeIndex(pos);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean trim(int size) {
|
||||
int newSize = HashUtil.nextPowerOfTwo((int)Math.ceil(size / loadFactor));
|
||||
if(newSize >= nullIndex || size >= Math.min((int)Math.ceil(newSize * loadFactor), newSize - 1)) return false;
|
||||
try {
|
||||
rehash(newSize);
|
||||
}
|
||||
catch(OutOfMemoryError e) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ensureCapacity(int newCapacity) {
|
||||
int size = HashUtil.arraySize(newCapacity, loadFactor);
|
||||
if(size > nullIndex) rehash(size);
|
||||
}
|
||||
|
||||
protected boolean removeIndex(int pos) {
|
||||
size--;
|
||||
onNodeRemoved(pos);
|
||||
shiftKeys(pos);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean removeNullIndex() {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
size--;
|
||||
onNodeRemoved(nullIndex);
|
||||
if(nullIndex > minCapacity && size < maxFill / 4 && nullIndex > HashUtil.DEFAULT_MIN_CAPACITY) rehash(nullIndex / 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void onNodeAdded(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeRemoved(int pos) {
|
||||
|
||||
}
|
||||
|
||||
protected void onNodeMoved(int from, int to) {
|
||||
|
||||
}
|
||||
|
||||
protected void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(KEY_EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
keys[last] = current;
|
||||
onNodeMoved(startPos, last);
|
||||
}
|
||||
}
|
||||
|
||||
protected void rehash(int newSize) {
|
||||
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]));
|
||||
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];
|
||||
}
|
||||
nullIndex = newSize;
|
||||
mask = newMask;
|
||||
maxFill = Math.min((int)Math.ceil(nullIndex * loadFactor), nullIndex - 1);
|
||||
keys = newKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return new SetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(size == 0) return;
|
||||
size = 0;
|
||||
containsNull = false;
|
||||
Arrays.fill(keys, EMPTY_KEY_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private class SetIterator implements ITERATOR KEY_GENERIC_TYPE {
|
||||
int pos = nullIndex;
|
||||
int lastReturned = -1;
|
||||
int nextIndex = Integer.MIN_VALUE;
|
||||
boolean returnNull = containsNull;
|
||||
LIST KEY_GENERIC_TYPE wrapped = null;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if(nextIndex == Integer.MIN_VALUE) {
|
||||
if(returnNull) {
|
||||
returnNull = false;
|
||||
nextIndex = nullIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(true) {
|
||||
if(--pos < 0) {
|
||||
if(wrapped == null || wrapped.size() <= -pos - 1) break;
|
||||
nextIndex = -pos - 1;
|
||||
break;
|
||||
}
|
||||
if(KEY_EQUALS_NOT_NULL(keys[pos])){
|
||||
nextIndex = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextIndex != Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
if(!hasNext()) throw new NoSuchElementException();
|
||||
if(nextIndex < 0){
|
||||
lastReturned = Integer.MAX_VALUE;
|
||||
KEY_TYPE value = wrapped.GET_KEY(nextIndex);
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
KEY_TYPE value = keys[(lastReturned = nextIndex)];
|
||||
nextIndex = Integer.MIN_VALUE;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(lastReturned == -1) throw new IllegalStateException();
|
||||
if(lastReturned == nullIndex) {
|
||||
containsNull = false;
|
||||
keys[nullIndex] = EMPTY_KEY_VALUE;
|
||||
}
|
||||
else if(pos >= 0) shiftKeys(pos);
|
||||
else {
|
||||
HASH_SET.this.remove(wrapped.GET_KEY(-pos - 1));
|
||||
return;
|
||||
}
|
||||
size--;
|
||||
lastReturned = -1;
|
||||
}
|
||||
|
||||
private void shiftKeys(int startPos) {
|
||||
int slot, last;
|
||||
KEY_TYPE current;
|
||||
while(true) {
|
||||
startPos = ((last = startPos) + 1) & mask;
|
||||
while(true){
|
||||
if(KEY_EQUALS_NULL((current = keys[startPos]))) {
|
||||
keys[last] = EMPTY_KEY_VALUE;
|
||||
return;
|
||||
}
|
||||
slot = HashUtil.mix(KEY_TO_HASH(current)) & mask;
|
||||
if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break;
|
||||
startPos = ++startPos & mask;
|
||||
}
|
||||
if(startPos < last) {
|
||||
if(wrapped == null) wrapped = new ARRAY_LISTBRACES(2);
|
||||
wrapped.add(keys[startPos]);
|
||||
}
|
||||
keys[last] = current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
|
||||
public interface SET KEY_GENERIC_TYPE extends Set<CLASS_TYPE>, COLLECTION KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public boolean remove(KEY_TYPE o);
|
||||
|
||||
@Override
|
||||
public default boolean REMOVE_KEY(KEY_TYPE o) {
|
||||
return remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public default boolean add(CLASS_TYPE e) {
|
||||
return COLLECTION.super.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public default boolean contains(Object o) {
|
||||
return COLLECTION.super.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public default boolean remove(Object o) {
|
||||
return COLLECTION.super.remove(o);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package speiger.src.collections.PACKAGE.sets;
|
||||
|
||||
import java.util.SortedSet;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
#else
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
|
||||
public interface SORTED_SET KEY_GENERIC_TYPE extends SET KEY_GENERIC_TYPE, SortedSet<CLASS_TYPE>
|
||||
{
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o);
|
||||
public boolean addAndMoveToLast(KEY_TYPE o);
|
||||
|
||||
public boolean moveToFirst(KEY_TYPE o);
|
||||
public boolean moveToLast(KEY_TYPE o);
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator();
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator();
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement);
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement);
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement);
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement);
|
||||
|
||||
public KEY_TYPE FIRST_KEY();
|
||||
public KEY_TYPE POLL_FIRST_KEY();
|
||||
public KEY_TYPE LAST_KEY();
|
||||
public KEY_TYPE POLL_LAST_KEY();
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement) { return subSet(OBJ_TO_KEY(fromElement), OBJ_TO_KEY(toElement)); }
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement) { return headSet(OBJ_TO_KEY(toElement)); }
|
||||
@Override
|
||||
@Deprecated
|
||||
public default SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement) { return tailSet(OBJ_TO_KEY(fromElement)); }
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public default CLASS_TYPE first() { return KEY_TO_OBJ(FIRST_KEY()); }
|
||||
@Override
|
||||
@Deprecated
|
||||
default CLASS_TYPE last() { return KEY_TO_OBJ(LAST_KEY()); }
|
||||
#else
|
||||
public CLASS_TYPE pollFirst();
|
||||
public CLASS_TYPE pollLast();
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(CLASS_TYPE fromElement, CLASS_TYPE toElement);
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(CLASS_TYPE toElement);
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(CLASS_TYPE fromElement);
|
||||
#endif
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+404
@@ -0,0 +1,404 @@
|
||||
package speiger.src.collections.PACKAGE.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Predicate;
|
||||
#if PRIMITIVES
|
||||
import java.util.function.JAVA_PREDICATE;
|
||||
#endif
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.ABSTRACT_COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.objects.utils.ObjectArrays;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.utils.ARRAYS;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A Helper class for Collections
|
||||
*/
|
||||
public class COLLECTIONS
|
||||
{
|
||||
public static final COLLECTION NO_GENERIC_TYPE EMPTY = new EmptyCollectionBRACES();
|
||||
|
||||
/**
|
||||
* Returns a Immutable EmptyCollection instance that is automatically casted.
|
||||
* @return an empty collection
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES COLLECTION KEY_GENERIC_TYPE emptyCollection() {
|
||||
#if TYPE_OBJECT
|
||||
return (COLLECTION<KEY_TYPE>)EMPTY;
|
||||
#else
|
||||
return EMPTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Immutable Collection instance based on the instance given.
|
||||
* @param l that should be made immutable/unmodifyable
|
||||
* @return a unmodifiable collection wrapper. If the Collection already a unmodifyable wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES COLLECTION KEY_GENERIC_TYPE unmodifiableCollection(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
return c instanceof UnmodifiableCollection ? c : new UnmodifiableCollectionBRACES(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a synchronized Collection instance based on the instance given.
|
||||
* @param l that should be synchronized
|
||||
* @return a synchronized collection wrapper. If the Collection already a synchronized wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES COLLECTION KEY_GENERIC_TYPE synchronizedCollection(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
return c instanceof SynchronizedCollection ? c : new SynchronizedCollectionBRACES(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a synchronized Collection instance based on the instance given.
|
||||
* @param l that should be synchronized
|
||||
* @param mutex is the controller of the synchronization block.
|
||||
* @return a synchronized collection wrapper. If the Collection already a synchronized wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES COLLECTION KEY_GENERIC_TYPE synchronizedCollection(COLLECTION KEY_GENERIC_TYPE c, Object mutex) {
|
||||
return c instanceof SynchronizedCollection ? c : new SynchronizedCollectionBRACES(c, mutex);
|
||||
}
|
||||
|
||||
public static class SynchronizedCollection KEY_GENERIC_TYPE implements COLLECTION KEY_GENERIC_TYPE {
|
||||
COLLECTION KEY_GENERIC_TYPE c;
|
||||
protected Object mutex;
|
||||
|
||||
SynchronizedCollection(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
this.c = c;
|
||||
mutex = this;
|
||||
}
|
||||
|
||||
SynchronizedCollection(COLLECTION KEY_GENERIC_TYPE c, Object mutex) {
|
||||
this.c = c;
|
||||
this.mutex = mutex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) { synchronized(mutex) { return c.add(o); } }
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends CLASS_TYPE> c) { synchronized(mutex) { return this.c.addAll(c); } }
|
||||
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return this.c.addAll(c); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) { synchronized(mutex) { return c.contains(o); } }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(Object o) { synchronized(mutex) { return c.contains(o); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAll(Collection<?> c) { synchronized(mutex) { return this.c.containsAll(c); } }
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAny(Collection<?> c) { synchronized(mutex) { return this.c.containsAny(c); } }
|
||||
|
||||
@Override
|
||||
public boolean containsAll(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return this.c.containsAll(c); } }
|
||||
|
||||
@Override
|
||||
public boolean containsAny(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return this.c.containsAny(c); } }
|
||||
|
||||
@Override
|
||||
public int size() { synchronized(mutex) { return c.size(); } }
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() { synchronized(mutex) { return c.isEmpty(); } }
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return c.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean remove(Object o) { synchronized(mutex) { return c.remove(o); } }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeAll(Collection<?> c) { synchronized(mutex) { return this.c.removeAll(c); } }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean retainAll(Collection<?> c) { synchronized(mutex) { return this.c.retainAll(c); } }
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean REMOVE_KEY(KEY_TYPE o) { synchronized(mutex) { return c.REMOVE_KEY(o); } }
|
||||
#endif
|
||||
@Override
|
||||
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return this.c.removeAll(c); } }
|
||||
@Override
|
||||
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return this.c.retainAll(c); } }
|
||||
#if PRIMITIVES
|
||||
@Override
|
||||
public boolean remIf(JAVA_PREDICATE filter){ synchronized(mutex) { return c.remIf(filter); } }
|
||||
#endif
|
||||
@Override
|
||||
public void clear() { synchronized(mutex) { c.clear(); } }
|
||||
|
||||
@Override
|
||||
public Object[] toArray() { synchronized(mutex) { return c.toArray(); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) { synchronized(mutex) { return c.toArray(a); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY() { synchronized(mutex) { return c.TO_ARRAY(); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) { synchronized(mutex) { return c.TO_ARRAY(a); } }
|
||||
#else
|
||||
@Override
|
||||
public <E> E[] toArray(E[] a) { synchronized(mutex) { return c.toArray(a); } }
|
||||
#endif
|
||||
}
|
||||
|
||||
public static class UnmodifiableCollection KEY_GENERIC_TYPE implements COLLECTION KEY_GENERIC_TYPE {
|
||||
COLLECTION KEY_GENERIC_TYPE c;
|
||||
|
||||
UnmodifiableCollection(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends CLASS_TYPE> c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) {
|
||||
return c.contains(o);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return c.contains(o);
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean containsAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
return this.c.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAny(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
return this.c.containsAny(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAny(Collection<?> c) {
|
||||
return this.c.containsAny(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return this.c.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return c.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return c.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return ITERATORS.unmodifiable(c.iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean remove(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeIf(Predicate<? super CLASS_TYPE> filter) { throw new UnsupportedOperationException(); }
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean REMOVE_KEY(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
@Override
|
||||
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
#if PRIMITIVES
|
||||
@Override
|
||||
public boolean remIf(JAVA_PREDICATE filter){ throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
@Override
|
||||
public void clear() { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return c.toArray();
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return c.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY() {
|
||||
return c.TO_ARRAY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
|
||||
return c.TO_ARRAY(a);
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public <E> E[] toArray(E[] a) {
|
||||
return c.toArray(a);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
public static class EmptyCollection KEY_GENERIC_TYPE extends ABSTRACT_COLLECTION KEY_GENERIC_TYPE {
|
||||
@Override
|
||||
public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAll(COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAny(COLLECTION KEY_GENERIC_TYPE c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAny(Collection<?> c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o == this) return true;
|
||||
if(!(o instanceof Collection)) return false;
|
||||
return ((Collection<?>)o).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean remove(Object o) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
@Primitive
|
||||
public boolean removeIf(Predicate<? super CLASS_TYPE> filter) { throw new UnsupportedOperationException(); }
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean REMOVE_KEY(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
@Override
|
||||
public boolean removeAll(COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public boolean retainAll(COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
#if PRIMITIVES
|
||||
@Override
|
||||
public boolean remIf(JAVA_PREDICATE filter){ throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return ObjectArrays.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY() {
|
||||
return ARRAYS.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] TO_ARRAY(KEY_TYPE[] a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
#else
|
||||
@Override
|
||||
public <E> E[] toArray(E[] a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public ITERATOR KEY_GENERIC_TYPE iterator() {
|
||||
return ITERATORS.emptyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package speiger.src.collections.PACKAGE.utils;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.collections.utils.IArray;
|
||||
|
||||
/**
|
||||
* Type-Specific Helper class to get the underlying array of array implementations.
|
||||
* @see speiger.src.collections.PACKAGE.lists.ARRAY_LIST
|
||||
*/
|
||||
public interface IARRAY KEY_GENERIC_TYPE extends IArray
|
||||
{
|
||||
/**
|
||||
* Provides the Underlying Array in the Implementation
|
||||
* @return underlying Array
|
||||
* @throws ClassCastException if the return type does not match the underlying array. (Only for Object Implementations)
|
||||
*/
|
||||
public KEY_TYPE[] elements();
|
||||
|
||||
/**
|
||||
* Provides the Underlying Array in the Implementation. This function exists purely because of Synchronization wrappers to help run Synchronized Code
|
||||
* @param action the action that handles the array
|
||||
* @throws NullPointerException if action is null
|
||||
* @throws ClassCastException if the return type does not match the underlying array. (Only for Object Implementations)
|
||||
*/
|
||||
public default void elements(Consumer<KEY_TYPE[]> action) {
|
||||
Objects.requireNonNull(action);
|
||||
action.accept(elements());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
package speiger.src.collections.PACKAGE.utils;
|
||||
|
||||
import java.util.Iterator;
|
||||
import speiger.src.collections.PACKAGE.collections.ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
|
||||
/**
|
||||
* A Helper class for Iterators
|
||||
*/
|
||||
public class ITERATORS
|
||||
{
|
||||
public static final EmptyIterator NO_GENERIC_TYPE EMPTY = new EmptyIteratorBRACES();
|
||||
|
||||
/**
|
||||
* Returns a Immutable EmptyIterator instance that is automatically casted.
|
||||
* @return an empty iterator
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES EmptyIterator KEY_GENERIC_TYPE emptyIterator() {
|
||||
#if TYPE_OBJECT
|
||||
return (EmptyIterator<KEY_TYPE>)EMPTY;
|
||||
#else
|
||||
return EMPTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES BI_ITERATOR KEY_GENERIC_TYPE invert(BI_ITERATOR KEY_GENERIC_TYPE it) {
|
||||
return new BI_ITERATOR KEY_GENERIC_TYPE() {
|
||||
@Override
|
||||
public KEY_TYPE NEXT() { return it.PREVIOUS(); }
|
||||
@Override
|
||||
public boolean hasNext() { return it.hasPrevious(); }
|
||||
@Override
|
||||
public boolean hasPrevious() { return it.hasNext(); }
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() { return it.NEXT(); }
|
||||
@Override
|
||||
public void remove() { it.remove(); }
|
||||
};
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES LIST_ITERATOR KEY_GENERIC_TYPE invert(LIST_ITERATOR KEY_GENERIC_TYPE it) {
|
||||
return new LIST_ITERATOR KEY_GENERIC_TYPE() {
|
||||
@Override
|
||||
public KEY_TYPE NEXT() { return it.PREVIOUS(); }
|
||||
@Override
|
||||
public boolean hasNext() { return it.hasPrevious(); }
|
||||
@Override
|
||||
public boolean hasPrevious() { return it.hasNext(); }
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() { return it.NEXT(); }
|
||||
@Override
|
||||
public void remove() { it.remove(); }
|
||||
@Override
|
||||
public int nextIndex() { return it.previousIndex(); }
|
||||
@Override
|
||||
public int previousIndex() { return it.nextIndex(); }
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { it.set(e); }
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { it.add(e); }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Immutable Iterator instance based on the instance given.
|
||||
* @param l that should be made immutable/unmodifyable
|
||||
* @return a unmodifiable iterator wrapper. If the Iterator already a unmodifyable wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE unmodifiable(ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
return iterator instanceof UnmodifiableIterator ? iterator : new UnmodifiableIteratorBRACES(iterator);
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES BI_ITERATOR KEY_GENERIC_TYPE unmodifiable(BI_ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
return iterator instanceof UnmodifiableBiIterator ? iterator : new UnmodifiableBiIteratorBRACES(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Immutable ListIterator instance based on the instance given.
|
||||
* @param l that should be made immutable/unmodifyable
|
||||
* @return a unmodifiable listiterator wrapper. If the ListIterator already a unmodifyable wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES LIST_ITERATOR KEY_GENERIC_TYPE unmodifiable(LIST_ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
return iterator instanceof UnmodifiableListIterator ? iterator : new UnmodifiableListIteratorBRACES(iterator);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
public static ITERATOR wrap(Iterator<CLASS_TYPE> iterator) {
|
||||
return iterator instanceof ITERATOR ? (ITERATOR)iterator : new IteratorWrapper(iterator);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Returns a Array Wrapping iterator
|
||||
* @param a the array that should be wrapped
|
||||
* @return a Iterator that is wrapping a array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES ArrayIterator KEY_GENERIC_TYPE wrap(KEY_TYPE[] a) {
|
||||
return wrap(a, 0, a.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Array Wrapping iterator
|
||||
* @param a the array that should be wrapped.
|
||||
* @param start the index to be started from.
|
||||
* @param end the index that should be ended.
|
||||
* @return a Iterator that is wrapping a array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES ArrayIterator KEY_GENERIC_TYPE wrap(KEY_TYPE[] a, int start, int end) {
|
||||
return new ArrayIteratorBRACES(a, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, Iterator<? extends CLASS_TYPE> i) {
|
||||
return unwrap(a, i, 0, a.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @param offset the array offset where the start should be
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, Iterator<? extends CLASS_TYPE> i, int offset) {
|
||||
return unwrap(a, i, offset, a.length - offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @param offset the array offset where the start should be
|
||||
* @param max the maximum values that should be extracted from the source
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
* @throws IllegalStateException if max is smaller the 0 or if the maximum index is larger then the array
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, Iterator<? extends CLASS_TYPE> i, int offset, int max) {
|
||||
if(max < 0) throw new IllegalStateException("The max size is smaller then 0");
|
||||
if(offset + max > a.length) throw new IllegalStateException("largest array index exceeds array size");
|
||||
int index = 0;
|
||||
for(;index<max && i.hasNext();index++) a[index+offset] = OBJ_TO_KEY(i.next());
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Primitive iterator variant of the {@link #unwrap(KEY_TYPE[], Iterator)} function
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, ITERATOR KEY_GENERIC_TYPE i) {
|
||||
return unwrap(a, i, 0, a.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Primitive iterator variant of the {@link #unwrap(KEY_TYPE[], Iterator, int)} function
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @param offset the array offset where the start should be
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, ITERATOR KEY_GENERIC_TYPE i, int offset) {
|
||||
return unwrap(a, i, offset, a.length - offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Primitive iterator variant of the {@link #unwrap(KEY_TYPE[], Iterator, int, int)} function
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @param offset the array offset where the start should be
|
||||
* @param max the maximum values that should be extracted from the source
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
* @throws IllegalStateException if max is smaller the 0 or if the maximum index is larger then the array
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(KEY_TYPE[] a, ITERATOR KEY_GENERIC_TYPE i, int offset, int max) {
|
||||
if(max < 0) throw new IllegalStateException("The max size is smaller then 0");
|
||||
if(offset + max > a.length) throw new IllegalStateException("largest array index exceeds array size");
|
||||
int index = 0;
|
||||
for(;index<max && i.hasNext();index++) a[index+offset] = i.NEXT();
|
||||
return index;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
* A Function to convert a Primitive Iterator to a Object array.
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(CLASS_TYPE[] a, ITERATOR KEY_GENERIC_TYPE i) {
|
||||
return unwrap(a, i, 0, a.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Function to convert a Primitive Iterator to a Object array.
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @param offset the array offset where the start should be
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(CLASS_TYPE[] a, ITERATOR KEY_GENERIC_TYPE i, int offset) {
|
||||
return unwrap(a, i, offset, a.length - offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Function to convert a Primitive Iterator to a Object array.
|
||||
* Iterates over a iterator and inserts the values into the array and returns the amount that was inserted
|
||||
* @param a where the elements should be inserted
|
||||
* @param i the source iterator
|
||||
* @param offset the array offset where the start should be
|
||||
* @param max the maximum values that should be extracted from the source
|
||||
* @return the amount of elements that were inserted into the array.
|
||||
* @throws IllegalStateException if max is smaller the 0 or if the maximum index is larger then the array
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES int unwrap(CLASS_TYPE[] a, ITERATOR KEY_GENERIC_TYPE i, int offset, int max) {
|
||||
if(max < 0) throw new IllegalStateException("The max size is smaller then 0");
|
||||
if(offset + max > a.length) throw new IllegalStateException("largest array index exceeds array size");
|
||||
int index = 0;
|
||||
for(;index<max && i.hasNext();index++) a[index+offset] = KEY_TO_OBJ(i.NEXT());
|
||||
return index;
|
||||
}
|
||||
|
||||
private static class IteratorWrapper implements ITERATOR
|
||||
{
|
||||
Iterator<CLASS_TYPE> iter;
|
||||
|
||||
public IteratorWrapper(Iterator<CLASS_TYPE> iter) {
|
||||
this.iter = iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return OBJ_TO_KEY(iter.next());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public CLASS_TYPE next() {
|
||||
return iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
private static class UnmodifiableListIterator KEY_GENERIC_TYPE implements LIST_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
LIST_ITERATOR KEY_GENERIC_TYPE iter;
|
||||
|
||||
UnmodifiableListIterator(LIST_ITERATOR KEY_GENERIC_TYPE iter) {
|
||||
this.iter = iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return iter.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return iter.nextIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return iter.previousIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
return iter.PREVIOUS();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return iter.NEXT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private static class UnmodifiableBiIterator KEY_GENERIC_TYPE implements BI_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
BI_ITERATOR KEY_GENERIC_TYPE iter;
|
||||
|
||||
UnmodifiableBiIterator(BI_ITERATOR KEY_GENERIC_TYPE iter) {
|
||||
this.iter = iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return iter.NEXT();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return iter.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
return iter.PREVIOUS();
|
||||
}
|
||||
}
|
||||
|
||||
private static class UnmodifiableIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
ITERATOR KEY_GENERIC_TYPE iterator;
|
||||
|
||||
UnmodifiableIterator(ITERATOR KEY_GENERIC_TYPE iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return iterator.NEXT();
|
||||
}
|
||||
}
|
||||
|
||||
private static class EmptyIterator KEY_GENERIC_TYPE implements LIST_ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return EMPTY_KEY_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE PREVIOUS() {
|
||||
return EMPTY_KEY_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void set(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
private static class ArrayIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE
|
||||
{
|
||||
KEY_TYPE[] a;
|
||||
int from;
|
||||
int to;
|
||||
|
||||
ArrayIterator(KEY_TYPE[] a, int from, int to) {
|
||||
this.a = a;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return from < to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KEY_TYPE NEXT() {
|
||||
return a[from++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skip(int amount) {
|
||||
if(amount < 0) throw new IllegalStateException("Negative Numbers are not allowed");
|
||||
int left = Math.min(amount, to - from);
|
||||
from += left;
|
||||
return amount - left;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package speiger.src.collections.PACKAGE.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.RandomAccess;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.collections.PACKAGE.collections.COLLECTION;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.lists.LIST;
|
||||
import speiger.src.collections.PACKAGE.lists.LIST_ITERATOR;
|
||||
|
||||
/**
|
||||
* A Helper class for Lists
|
||||
*/
|
||||
public class LISTS
|
||||
{
|
||||
public static final EmptyList NO_GENERIC_TYPE EMPTY = new EmptyListBRACES();
|
||||
|
||||
/**
|
||||
* Returns a Immutable EmptyList instance that is automatically casted.
|
||||
* @return an empty list
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES EmptyList KEY_GENERIC_TYPE emptyList() {
|
||||
#if TYPE_OBJECT
|
||||
return (EmptyList<KEY_TYPE>)EMPTY;
|
||||
#else
|
||||
return EMPTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Immutable List instance based on the instance given.
|
||||
* @param l that should be made immutable/unmodifyable
|
||||
* @return a unmodifiable list wrapper. If the list is implementing RandomAccess that is also transferred. If the List already a unmodifyable wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE unmodifiableList(LIST KEY_GENERIC_TYPE l) {
|
||||
return l instanceof UnmodifiableList ? l : l instanceof RandomAccess ? new UnmodifiableRandomListBRACES(l) : new UnmodifiableListBRACES(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a synchronized List instance based on the instance given.
|
||||
* @param l that should be synchronized
|
||||
* @return a synchronized list wrapper. If the list is implementing RandomAccess or IARRAY that is also transferred. If the List already a synchronized wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE synchronizedList(LIST KEY_GENERIC_TYPE l) {
|
||||
return l instanceof SynchronizedList ? l : (l instanceof IARRAY ? new SynchronizedArrayListBRACES(l) : (l instanceof RandomAccess ? new SynchronizedRandomAccessListBRACES(l) : new SynchronizedListBRACES(l)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a synchronized List instance based on the instance given.
|
||||
* @param l that should be synchronized
|
||||
* @param mutex is the controller of the synchronization block.
|
||||
* @return a synchronized list wrapper. If the list is implementing RandomAccess or IARRAY that is also transferred. If the List already a synchronized wrapper then it just returns itself.
|
||||
*/
|
||||
public static GENERIC_KEY_BRACES LIST KEY_GENERIC_TYPE synchronizedList(LIST KEY_GENERIC_TYPE l, Object mutex) {
|
||||
return l instanceof SynchronizedList ? l : (l instanceof IARRAY ? new SynchronizedArrayListBRACES(l, mutex) : (l instanceof RandomAccess ? new SynchronizedRandomAccessListBRACES(l, mutex) : new SynchronizedListBRACES(l, mutex)));
|
||||
}
|
||||
|
||||
public static class SynchronizedArrayList KEY_GENERIC_TYPE extends SynchronizedList KEY_GENERIC_TYPE implements IARRAY KEY_GENERIC_TYPE
|
||||
{
|
||||
IARRAY KEY_GENERIC_TYPE l;
|
||||
|
||||
SynchronizedArrayList(LIST KEY_GENERIC_TYPE l) {
|
||||
super(l);
|
||||
this.l = (IARRAY KEY_GENERIC_TYPE)l;
|
||||
}
|
||||
|
||||
SynchronizedArrayList(LIST KEY_GENERIC_TYPE l, Object mutex) {
|
||||
super(l, mutex);
|
||||
this.l = (IARRAY KEY_GENERIC_TYPE)l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureCapacity(int size) { synchronized(mutex) { l.ensureCapacity(size); } }
|
||||
|
||||
@Override
|
||||
public boolean trim(int size) { synchronized(mutex) { return l.trim(size); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] elements() { synchronized(mutex) { return l.elements(); } }
|
||||
|
||||
@Override
|
||||
public void elements(Consumer<KEY_TYPE[]> action) {
|
||||
Objects.requireNonNull(action);
|
||||
synchronized(mutex) {
|
||||
action.accept(elements());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SynchronizedRandomAccessList KEY_GENERIC_TYPE extends SynchronizedList KEY_GENERIC_TYPE implements RandomAccess
|
||||
{
|
||||
SynchronizedRandomAccessList(LIST KEY_GENERIC_TYPE l) {
|
||||
super(l);
|
||||
}
|
||||
|
||||
SynchronizedRandomAccessList(LIST KEY_GENERIC_TYPE l, Object mutex) {
|
||||
super(l, mutex);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SynchronizedList KEY_GENERIC_TYPE extends COLLECTIONS.SynchronizedCollection KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE
|
||||
{
|
||||
LIST KEY_GENERIC_TYPE l;
|
||||
|
||||
SynchronizedList(LIST KEY_GENERIC_TYPE l) {
|
||||
super(l);
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
SynchronizedList(LIST KEY_GENERIC_TYPE l, Object mutex) {
|
||||
super(l, mutex);
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) { synchronized(mutex) { return l.addAll(index, c); } }
|
||||
|
||||
@Override
|
||||
public void add(int index, CLASS_TYPE element) { synchronized(mutex) { l.add(index, element); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void add(int index, KEY_TYPE e) { synchronized(mutex) { l.add(index, e); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { synchronized(mutex) { return l.addAll(index, c); } }
|
||||
|
||||
@Override
|
||||
public boolean addAll(LIST KEY_GENERIC_TYPE c) { synchronized(mutex) { return l.addAll(c); } }
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { synchronized(mutex) { return l.addAll(index, c); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE GET_KEY(int index) { synchronized(mutex) { return l.GET_KEY(index); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) { synchronized(mutex) { l.forEach(action); } }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void forEach(Consumer<? super KEY_TYPE> action) { synchronized(mutex) { l.forEach(action); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public KEY_TYPE set(int index, KEY_TYPE e) { synchronized(mutex) { return l.set(index, e); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE REMOVE(int index) { synchronized(mutex) { return l.REMOVE(index); } }
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public int indexOf(Object e) { synchronized(mutex) { return l.indexOf(e); } }
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public int lastIndexOf(Object e) { synchronized(mutex) { return l.lastIndexOf(e); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public int indexOf(KEY_TYPE e) { synchronized(mutex) { return l.indexOf(e); } }
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(KEY_TYPE e) { synchronized(mutex) { return l.lastIndexOf(e); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public void addElements(int from, KEY_TYPE[] a, int offset, int length) { synchronized(mutex) { addElements(from, a, offset, length); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) { synchronized(mutex) { return l.getElements(from, a, offset, length); } }
|
||||
|
||||
@Override
|
||||
public void removeElements(int from, int to) { synchronized(mutex) { l.removeElements(from, to); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public KEY_TYPE[] extractElements(int from, int to) { synchronized(mutex) { return l.extractElements(from, to); } }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public <K> K[] extractElements(int from, int to, Class<K> clz) { synchronized(mutex) { return l.extractElements(from, to, clz); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() {
|
||||
return l.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
|
||||
return l.listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST KEY_GENERIC_TYPE subList(int from, int to) {
|
||||
return synchronizedList(l.subList(from, to));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void size(int size) { synchronized(mutex) { l.size(size); } }
|
||||
}
|
||||
|
||||
public static class UnmodifiableRandomList KEY_GENERIC_TYPE extends UnmodifiableList KEY_GENERIC_TYPE implements RandomAccess
|
||||
{
|
||||
UnmodifiableRandomList(LIST KEY_GENERIC_TYPE l) {
|
||||
super(l);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnmodifiableList KEY_GENERIC_TYPE extends COLLECTIONS.UnmodifiableCollection KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE
|
||||
{
|
||||
final LIST KEY_GENERIC_TYPE l;
|
||||
|
||||
UnmodifiableList(LIST KEY_GENERIC_TYPE l) {
|
||||
super(l);
|
||||
this.l = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(int index, CLASS_TYPE element) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void add(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAll(LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE GET_KEY(int index) { return l.GET_KEY(index); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) { l.forEach(action); }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public void forEach(Consumer<? super KEY_TYPE> action) { l.forEach(action); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public KEY_TYPE set(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE REMOVE(int index) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public int indexOf(Object e) { return l.indexOf(e); }
|
||||
|
||||
@Override
|
||||
@Primitive
|
||||
public int lastIndexOf(Object e) { return l.lastIndexOf(e); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public int indexOf(KEY_TYPE e) { return l.indexOf(e); }
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(KEY_TYPE e) { return l.lastIndexOf(e); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public void addElements(int from, KEY_TYPE[] a, int offset, int length) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) {
|
||||
return l.getElements(from, a, offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeElements(int from, int to) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public KEY_TYPE[] extractElements(int from, int to) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public <K> K[] extractElements(int from, int to, Class<K> clz) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() {
|
||||
return ITERATORS.unmodifiable(l.listIterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
|
||||
return ITERATORS.unmodifiable(l.listIterator(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST KEY_GENERIC_TYPE subList(int from, int to) {
|
||||
return unmodifiableList(l.subList(from, to));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void size(int size) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
public static class EmptyList KEY_GENERIC_TYPE extends COLLECTIONS.EmptyCollection KEY_GENERIC_TYPE implements LIST KEY_GENERIC_TYPE
|
||||
{
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends CLASS_TYPE> c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void add(int index, CLASS_TYPE element) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void add(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public boolean addAll(int index, COLLECTION KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAll(LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, LIST KEY_GENERIC_TYPE c) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE GET_KEY(int index) { throw new IndexOutOfBoundsException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE set(int index, KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE REMOVE(int index) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public int indexOf(Object e) { return -1; }
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object e) { return -1; }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public int indexOf(KEY_TYPE e) { return -1; }
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(KEY_TYPE e) { return -1; }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public void addElements(int from, KEY_TYPE[] a, int offset, int length){ throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE[] getElements(int from, KEY_TYPE[] a, int offset, int length) { throw new IndexOutOfBoundsException(); }
|
||||
|
||||
@Override
|
||||
public void removeElements(int from, int to) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public KEY_TYPE[] extractElements(int from, int to) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#else
|
||||
@Override
|
||||
public <K> K[] extractElements(int from, int to, Class<K> clz) { throw new UnsupportedOperationException(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator() {
|
||||
return ITERATORS.emptyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST_ITERATOR KEY_GENERIC_TYPE listIterator(int index) {
|
||||
if(index != 0)
|
||||
throw new IndexOutOfBoundsException();
|
||||
return ITERATORS.emptyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LIST KEY_GENERIC_TYPE subList(int from, int to) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public void size(int size) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
package speiger.src.collections.PACKAGE.utils;
|
||||
|
||||
#if TYPE_OBJECT
|
||||
import java.util.Comparator;
|
||||
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.collections.BI_ITERATOR;
|
||||
#if !TYPE_OBJECT
|
||||
import speiger.src.collections.PACKAGE.functions.COMPARATOR;
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.sets.NAVIGABLE_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SORTED_SET;
|
||||
import speiger.src.collections.PACKAGE.utils.COLLECTIONS.EmptyCollection;
|
||||
import speiger.src.collections.PACKAGE.utils.COLLECTIONS.SynchronizedCollection;
|
||||
import speiger.src.collections.PACKAGE.utils.COLLECTIONS.UnmodifiableCollection;
|
||||
import speiger.src.collections.utils.ITrimmable;
|
||||
|
||||
public class SETS
|
||||
{
|
||||
public static final SET NO_GENERIC_TYPE EMPTY = new EmptySetBRACES();
|
||||
|
||||
public static GENERIC_KEY_BRACES SET KEY_GENERIC_TYPE empty() {
|
||||
#if TYPE_OBJECT
|
||||
return (SET<KEY_TYPE>)EMPTY;
|
||||
#else
|
||||
return EMPTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES SET KEY_GENERIC_TYPE synchronizedSet(SET KEY_GENERIC_TYPE s) {
|
||||
return s instanceof SynchronizedSet ? s : (s instanceof ITrimmable ? new SynchronizedTrimSetBRACES(s) : new SynchronizedSetBRACES(s));
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES SET KEY_GENERIC_TYPE synchronizedSet(SET KEY_GENERIC_TYPE s, Object mutex) {
|
||||
return s instanceof SynchronizedSet ? s : (s instanceof ITrimmable ? new SynchronizedTrimSetBRACES(s, mutex) : new SynchronizedSetBRACES(s, mutex));
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES SORTED_SET KEY_GENERIC_TYPE synchronizedSet(SORTED_SET KEY_GENERIC_TYPE s) {
|
||||
return s instanceof SynchronizedSortedSet ? s : (s instanceof ITrimmable ? new SynchronizedSortedTrimSetBRACES(s) : new SynchronizedSortedSetBRACES(s));
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES SORTED_SET KEY_GENERIC_TYPE synchronizedSet(SORTED_SET KEY_GENERIC_TYPE s, Object mutex) {
|
||||
return s instanceof SynchronizedSortedSet ? s : (s instanceof ITrimmable ? new SynchronizedSortedTrimSetBRACES(s, mutex) : new SynchronizedSortedSetBRACES(s, mutex));
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES NAVIGABLE_SET KEY_GENERIC_TYPE synchronizedSet(NAVIGABLE_SET KEY_GENERIC_TYPE s) {
|
||||
return s instanceof SynchronizedNavigableSet ? s : (s instanceof ITrimmable ? new SynchronizedNavigableTrimSetBRACES(s) : new SynchronizedNavigableSetBRACES(s));
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES NAVIGABLE_SET KEY_GENERIC_TYPE synchronizedSet(NAVIGABLE_SET KEY_GENERIC_TYPE s, Object mutex) {
|
||||
return s instanceof SynchronizedNavigableSet ? s : (s instanceof ITrimmable ? new SynchronizedNavigableTrimSetBRACES(s, mutex) : new SynchronizedNavigableSetBRACES(s, mutex));
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES SET KEY_GENERIC_TYPE unmodifiable(SET KEY_GENERIC_TYPE s) {
|
||||
return s instanceof SynchronizedSet ? s : new SynchronizedSetBRACES(s);
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES SORTED_SET KEY_GENERIC_TYPE unmodifiable(SORTED_SET KEY_GENERIC_TYPE s) {
|
||||
return s instanceof SynchronizedSortedSet ? s : new SynchronizedSortedSetBRACES(s);
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_BRACES NAVIGABLE_SET KEY_GENERIC_TYPE unmodifiable(NAVIGABLE_SET KEY_GENERIC_TYPE s) {
|
||||
return s instanceof UnmodifiableNavigableSet ? s : new UnmodifiableNavigableSetBRACES(s);
|
||||
}
|
||||
|
||||
public static class EmptySet KEY_GENERIC_TYPE extends EmptyCollection KEY_GENERIC_TYPE implements SET KEY_GENERIC_TYPE
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
}
|
||||
|
||||
public static class UnmodifiableNavigableSet KEY_GENERIC_TYPE extends UnmodifiableSortedSet KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
NAVIGABLE_SET KEY_GENERIC_TYPE n;
|
||||
|
||||
public UnmodifiableNavigableSet(NAVIGABLE_SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
n = c;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) { return n.contains(o); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean contains(Object o) { return n.contains(o); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE lower(KEY_TYPE e) { return n.lower(e); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE floor(KEY_TYPE e) { return n.floor(e); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE ceiling(KEY_TYPE e) { return n.ceiling(e); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE higher(KEY_TYPE e) { return n.higher(e); }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void setDefaultMaxValue(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE getDefaultMaxValue() { return n.getDefaultMaxValue(); }
|
||||
|
||||
@Override
|
||||
public void setDefaultMinValue(KEY_TYPE e) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE getDefaultMinValue() { return n.getDefaultMinValue(); }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { return unmodifiable(n.subSet(fromElement, fromInclusive, toElement, toInclusive)); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) { return unmodifiable(n.headSet(toElement, inclusive)); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) { return unmodifiable(n.tailSet(fromElement, inclusive)); }
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { return ITERATORS.unmodifiable(n.descendingIterator()); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() { return unmodifiable(n.descendingSet()); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { return unmodifiable(n.subSet(fromElement, toElement)); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { return unmodifiable(n.headSet(toElement)); }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { return unmodifiable(n.tailSet(fromElement)); }
|
||||
|
||||
}
|
||||
|
||||
public static class UnmodifiableSortedSet KEY_GENERIC_TYPE extends UnmodifiableSet KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
SORTED_SET KEY_GENERIC_TYPE s;
|
||||
public UnmodifiableSortedSet(SORTED_SET KEY_GENERIC_TYPE c)
|
||||
{
|
||||
super(c);
|
||||
s = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator() { return s.comparator(); }
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { return ITERATORS.unmodifiable(s.iterator()); }
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { return ITERATORS.unmodifiable(s.iterator(fromElement)); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { return unmodifiable(s.subSet(fromElement, toElement)); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { return unmodifiable(s.headSet(toElement)); }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { return unmodifiable(s.tailSet(fromElement)); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() { return s.FIRST_KEY(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() { throw new UnsupportedOperationException(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() { return s.LAST_KEY(); }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
public static class UnmodifiableSet KEY_GENERIC_TYPE extends UnmodifiableCollection KEY_GENERIC_TYPE implements SET KEY_GENERIC_TYPE
|
||||
{
|
||||
SET KEY_GENERIC_TYPE s;
|
||||
|
||||
public UnmodifiableSet(SET KEY_GENERIC_TYPE c)
|
||||
{
|
||||
super(c);
|
||||
s = c;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) { throw new UnsupportedOperationException(); }
|
||||
#endif
|
||||
}
|
||||
|
||||
public static class SynchronizedNavigableTrimSet KEY_GENERIC_TYPE extends SynchronizedNavigableSet KEY_GENERIC_TYPE implements ITrimmable
|
||||
{
|
||||
ITrimmable trim;
|
||||
|
||||
public SynchronizedNavigableTrimSet(NAVIGABLE_SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
trim = (ITrimmable)c;
|
||||
}
|
||||
|
||||
public SynchronizedNavigableTrimSet(NAVIGABLE_SET KEY_GENERIC_TYPE c, Object mutex) {
|
||||
super(c, mutex);
|
||||
trim = (ITrimmable)c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(int size) { synchronized(mutex) { return trim.trim(size); } }
|
||||
}
|
||||
|
||||
public static class SynchronizedNavigableSet KEY_GENERIC_TYPE extends SynchronizedSortedSet KEY_GENERIC_TYPE implements NAVIGABLE_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
NAVIGABLE_SET KEY_GENERIC_TYPE n;
|
||||
|
||||
public SynchronizedNavigableSet(NAVIGABLE_SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
n = c;
|
||||
}
|
||||
|
||||
public SynchronizedNavigableSet(NAVIGABLE_SET KEY_GENERIC_TYPE c, Object mutex) {
|
||||
super(c, mutex);
|
||||
n = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean contains(Object o) { synchronized(mutex) { return n.contains(o); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean contains(KEY_TYPE o) { synchronized(mutex) { return n.contains(o); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public KEY_TYPE lower(KEY_TYPE e) { synchronized(mutex) { return n.lower(e); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE floor(KEY_TYPE e) { synchronized(mutex) { return n.floor(e); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE ceiling(KEY_TYPE e) { synchronized(mutex) { return n.ceiling(e); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE higher(KEY_TYPE e) { synchronized(mutex) { return n.higher(e); } }
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void setDefaultMaxValue(KEY_TYPE e) { synchronized(mutex) { n.setDefaultMaxValue(e); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE getDefaultMaxValue() { synchronized(mutex) { return n.getDefaultMaxValue(); } }
|
||||
|
||||
@Override
|
||||
public void setDefaultMinValue(KEY_TYPE e) { synchronized(mutex) { n.setDefaultMinValue(e); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE getDefaultMinValue() { synchronized(mutex) { return n.getDefaultMinValue(); } }
|
||||
|
||||
#endif
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, boolean fromInclusive, KEY_TYPE toElement, boolean toInclusive) { synchronized(mutex) { return synchronizedSet(n.subSet(fromElement, fromInclusive, toElement, toInclusive), mutex); } }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement, boolean inclusive) { synchronized(mutex) { return synchronizedSet(n.headSet(toElement, inclusive), mutex); } }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement, boolean inclusive) { synchronized(mutex) { return synchronizedSet(n.tailSet(fromElement, inclusive), mutex); } }
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE descendingIterator() { synchronized(mutex) { return n.descendingIterator(); } }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE descendingSet() { synchronized(mutex) { return synchronizedSet(n.descendingSet(), mutex); } }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { synchronized(mutex) { return synchronizedSet(n.subSet(fromElement, toElement), mutex); } }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { synchronized(mutex) { return synchronizedSet(n.headSet(toElement), mutex); } }
|
||||
|
||||
@Override
|
||||
public NAVIGABLE_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { synchronized(mutex) { return synchronizedSet(n.tailSet(fromElement), mutex); } }
|
||||
}
|
||||
|
||||
public static class SynchronizedSortedTrimSet KEY_GENERIC_TYPE extends SynchronizedSortedSet KEY_GENERIC_TYPE implements ITrimmable
|
||||
{
|
||||
ITrimmable trim;
|
||||
|
||||
public SynchronizedSortedTrimSet(SORTED_SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
trim = (ITrimmable)c;
|
||||
}
|
||||
|
||||
public SynchronizedSortedTrimSet(SORTED_SET KEY_GENERIC_TYPE c, Object mutex) {
|
||||
super(c, mutex);
|
||||
trim = (ITrimmable)c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(int size) { synchronized(mutex) { return trim.trim(size); } }
|
||||
}
|
||||
|
||||
public static class SynchronizedSortedSet KEY_GENERIC_TYPE extends SynchronizedSet KEY_GENERIC_TYPE implements SORTED_SET KEY_GENERIC_TYPE
|
||||
{
|
||||
SORTED_SET KEY_GENERIC_TYPE s;
|
||||
|
||||
public SynchronizedSortedSet(SORTED_SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
s = c;
|
||||
}
|
||||
|
||||
public SynchronizedSortedSet(SORTED_SET KEY_GENERIC_TYPE c, Object mutex) {
|
||||
super(c, mutex);
|
||||
s = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToFirst(KEY_TYPE o) { synchronized(mutex) { return s.addAndMoveToFirst(o); } }
|
||||
|
||||
@Override
|
||||
public boolean addAndMoveToLast(KEY_TYPE o) { synchronized(mutex) { return s.addAndMoveToLast(o); } }
|
||||
|
||||
@Override
|
||||
public boolean moveToFirst(KEY_TYPE o) { synchronized(mutex) { return s.moveToFirst(o); } }
|
||||
|
||||
@Override
|
||||
public boolean moveToLast(KEY_TYPE o) { synchronized(mutex) { return s.moveToLast(o); } }
|
||||
|
||||
@Override
|
||||
public COMPARATOR KEY_GENERIC_TYPE comparator(){ synchronized(mutex) { return s.comparator(); } }
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator() { synchronized(mutex) { return s.iterator(); } }
|
||||
|
||||
@Override
|
||||
public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { synchronized(mutex) { return s.iterator(fromElement); } }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE subSet(KEY_TYPE fromElement, KEY_TYPE toElement) { synchronized(mutex) { return synchronizedSet(s.subSet(fromElement, toElement), mutex); } }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE headSet(KEY_TYPE toElement) { synchronized(mutex) { return synchronizedSet(s.headSet(toElement), mutex); } }
|
||||
|
||||
@Override
|
||||
public SORTED_SET KEY_GENERIC_TYPE tailSet(KEY_TYPE fromElement) { synchronized(mutex) { return synchronizedSet(s.tailSet(fromElement), mutex); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE FIRST_KEY() { synchronized(mutex) { return s.FIRST_KEY(); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_FIRST_KEY() { synchronized(mutex) { return s.POLL_FIRST_KEY(); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE LAST_KEY() { synchronized(mutex) { return s.LAST_KEY(); } }
|
||||
|
||||
@Override
|
||||
public KEY_TYPE POLL_LAST_KEY() { synchronized(mutex) { return s.POLL_LAST_KEY(); } }
|
||||
}
|
||||
|
||||
public static class SynchronizedTrimSet KEY_GENERIC_TYPE extends SynchronizedSet KEY_GENERIC_TYPE implements ITrimmable
|
||||
{
|
||||
ITrimmable trim;
|
||||
|
||||
public SynchronizedTrimSet(SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
trim = (ITrimmable)c;
|
||||
}
|
||||
|
||||
public SynchronizedTrimSet(SET KEY_GENERIC_TYPE c, Object mutex) {
|
||||
super(c, mutex);
|
||||
trim = (ITrimmable)c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(int size) { synchronized(mutex) { return trim.trim(size); } }
|
||||
}
|
||||
|
||||
public static class SynchronizedSet KEY_GENERIC_TYPE extends SynchronizedCollection KEY_GENERIC_TYPE implements SET KEY_GENERIC_TYPE
|
||||
{
|
||||
SET KEY_GENERIC_TYPE s;
|
||||
|
||||
public SynchronizedSet(SET KEY_GENERIC_TYPE c) {
|
||||
super(c);
|
||||
s = c;
|
||||
}
|
||||
|
||||
public SynchronizedSet(SET KEY_GENERIC_TYPE c, Object mutex) {
|
||||
super(c, mutex);
|
||||
s = c;
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public boolean remove(KEY_TYPE o) { synchronized(mutex) { return s.remove(o); } }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package speiger.src.collections.PACKAGE.utils;
|
||||
|
||||
public interface STRATEGY KEY_GENERIC_TYPE
|
||||
{
|
||||
public int hashCode(KEY_TYPE o);
|
||||
|
||||
public boolean equals(KEY_TYPE key, KEY_TYPE value);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package speiger.src.collections.PACKAGE.utils.maps;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.collections.objects.collections.ObjectIterable;
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
import speiger.src.collections.PACKAGE.maps.interfaces.MAP;
|
||||
import speiger.src.collections.objects.sets.ObjectSet;
|
||||
|
||||
public class MAPS
|
||||
{
|
||||
public static GENERIC_KEY_VALUE_BRACES ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterator(MAP KEY_VALUE_GENERIC_TYPE map) {
|
||||
ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> entries = map.ENTRY_SET();
|
||||
return entries instanceof MAP.FastEntrySet ? ((MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE)entries).fastIterator() : entries.iterator();
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_VALUE_BRACES ObjectIterable<MAP.Entry KEY_VALUE_GENERIC_TYPE> fastIterable(MAP KEY_VALUE_GENERIC_TYPE map) {
|
||||
ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> entries = map.ENTRY_SET();
|
||||
return map instanceof MAP.FastEntrySet ? new ObjectIterable<MAP.Entry KEY_VALUE_GENERIC_TYPE>(){
|
||||
@Override
|
||||
public ObjectIterator<MAP.Entry KEY_VALUE_GENERIC_TYPE> iterator() { return ((MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE)entries).fastIterator(); }
|
||||
@Override
|
||||
public void forEach(Consumer<? super MAP.Entry KEY_VALUE_GENERIC_TYPE> action) { ((MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE)entries).fastForEach(action); }
|
||||
} : entries;
|
||||
}
|
||||
|
||||
public static GENERIC_KEY_VALUE_BRACES void fastForEach(MAP KEY_VALUE_GENERIC_TYPE map, Consumer<MAP.Entry KEY_VALUE_GENERIC_TYPE> action) {
|
||||
ObjectSet<MAP.Entry KEY_VALUE_GENERIC_TYPE> entries = map.ENTRY_SET();
|
||||
if(entries instanceof MAP.FastEntrySet) ((MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE)entries).fastForEach(action);
|
||||
else entries.forEach(action);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user