Update FastUtilStackSetWrapper.java, HashStackSet.java, and 3 more files...

This commit is contained in:
Andrea Cavalli 2020-12-14 00:41:55 +01:00
parent 06a5e1c525
commit bb89ca6bdb
5 changed files with 125 additions and 27 deletions

View File

@ -1,17 +1,25 @@
package org.warp.commonutils.type; package org.warp.commonutils.type;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import java.util.Collection;
import org.jetbrains.annotations.NotNull;
import org.warp.commonutils.error.IndexOutOfBoundsException; import org.warp.commonutils.error.IndexOutOfBoundsException;
public class FastUtilStackSetWrapper<T> implements StackSet<T> { public class FastUtilStackSetWrapper<T> implements StackSet<T>, Collection<T> {
private final AddStrategy addStrategy; private final AddStrategy addStrategy;
private final ObjectLinkedOpenHashSet<T> linkedHashSet; private final ObjectLinkedOpenHashSet<T> linkedHashSet;
/**
* The first element will be the head
*/
public FastUtilStackSetWrapper(ObjectLinkedOpenHashSet<T> linkedHashSet) { public FastUtilStackSetWrapper(ObjectLinkedOpenHashSet<T> linkedHashSet) {
this(linkedHashSet, AddStrategy.getDefault()); this(linkedHashSet, AddStrategy.getDefault());
} }
/**
* The first element will be the head
*/
public FastUtilStackSetWrapper(ObjectLinkedOpenHashSet<T> linkedHashSet, AddStrategy addStrategy) { public FastUtilStackSetWrapper(ObjectLinkedOpenHashSet<T> linkedHashSet, AddStrategy addStrategy) {
this.addStrategy = addStrategy; this.addStrategy = addStrategy;
this.linkedHashSet = linkedHashSet; this.linkedHashSet = linkedHashSet;
@ -21,17 +29,79 @@ public class FastUtilStackSetWrapper<T> implements StackSet<T> {
public boolean push(T o) { public boolean push(T o) {
switch (addStrategy) { switch (addStrategy) {
case KEEP_POSITION: case KEEP_POSITION:
return linkedHashSet.add(o); if (linkedHashSet.contains(o)) {
return false;
}
return linkedHashSet.addAndMoveToFirst(o);
case OVERWRITE_POSITION: case OVERWRITE_POSITION:
return linkedHashSet.addAndMoveToLast(o); return linkedHashSet.addAndMoveToFirst(o);
default: default:
throw new UnsupportedOperationException("Unsupported strategy type: " + addStrategy); throw new UnsupportedOperationException("Unsupported strategy type: " + addStrategy);
} }
} }
@NotNull
@Override
public java.util.Iterator<T> iterator() {
return linkedHashSet.iterator();
}
@NotNull
@Override
public Object[] toArray() {
return linkedHashSet.toArray();
}
@NotNull
@Override
public <T1> T1[] toArray(@NotNull T1[] a) {
//noinspection SuspiciousToArrayCall
return linkedHashSet.toArray(a);
}
@Override
public boolean add(T t) {
return linkedHashSet.add(t);
}
@Override
public boolean remove(Object o) {
return linkedHashSet.remove(o);
}
@Override
public boolean containsAll(@NotNull Collection<?> c) {
return linkedHashSet.containsAll(c);
}
@Override
public boolean addAll(@NotNull Collection<? extends T> c) {
return linkedHashSet.addAll(c);
}
@Override
public boolean removeAll(@NotNull Collection<?> c) {
return linkedHashSet.removeAll(c);
}
@Override
public boolean retainAll(@NotNull Collection<?> c) {
return linkedHashSet.retainAll(c);
}
@Override
public void clear() {
linkedHashSet.clear();
}
@Override @Override
public T pop() { public T pop() {
return linkedHashSet.removeLast(); return linkedHashSet.removeFirst();
}
@Override
public int size() {
return linkedHashSet.size();
} }
@Override @Override
@ -39,24 +109,27 @@ public class FastUtilStackSetWrapper<T> implements StackSet<T> {
return linkedHashSet.isEmpty(); return linkedHashSet.isEmpty();
} }
@Override
public boolean contains(Object o) {
return linkedHashSet.contains(o);
}
@Override @Override
public T top() { public T top() {
return linkedHashSet.last(); return linkedHashSet.first();
} }
@Override @Override
public T peek(int i) { public T peek(int i) {
var size = linkedHashSet.size(); var size = linkedHashSet.size();
int positionFromBottom = size - 1 - i; if (i < 0 || i >= size) {
throw new IndexOutOfBoundsException(i, 0, size);
if (positionFromBottom < 0 || positionFromBottom >= size) {
throw new IndexOutOfBoundsException(positionFromBottom, 0, size);
} }
var it = linkedHashSet.iterator(); var it = linkedHashSet.iterator();
// Skip middle elements // Skip middle elements
if (positionFromBottom > 0) { if (i > 0) {
it.skip(positionFromBottom); it.skip(i);
} }
return it.next(); return it.next();
} }

View File

@ -1,6 +1,7 @@
package org.warp.commonutils.type; package org.warp.commonutils.type;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import java.util.Collection;
public class HashStackSet<T> extends FastUtilStackSetWrapper<T> { public class HashStackSet<T> extends FastUtilStackSetWrapper<T> {
@ -8,6 +9,10 @@ public class HashStackSet<T> extends FastUtilStackSetWrapper<T> {
super(new ObjectLinkedOpenHashSet<>()); super(new ObjectLinkedOpenHashSet<>());
} }
public HashStackSet(Collection<T> collection) {
super(new ObjectLinkedOpenHashSet<>(collection));
}
public HashStackSet(AddStrategy addStrategy) { public HashStackSet(AddStrategy addStrategy) {
super(new ObjectLinkedOpenHashSet<>(), addStrategy); super(new ObjectLinkedOpenHashSet<>(), addStrategy);
} }

View File

@ -8,6 +8,9 @@ public class JavaStackSetWrapper<T> implements StackSet<T> {
private final LinkedHashSet<T> linkedHashSet; private final LinkedHashSet<T> linkedHashSet;
/**
* The last element will be the head
*/
public JavaStackSetWrapper(LinkedHashSet<T> linkedHashSet) { public JavaStackSetWrapper(LinkedHashSet<T> linkedHashSet) {
this.linkedHashSet = linkedHashSet; this.linkedHashSet = linkedHashSet;
} }

View File

@ -1,59 +1,61 @@
package org.warp.commonutils.type; package org.warp.commonutils.type;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Predicate;
/** /**
* A stack but with the behavior of a Linked HashSet * A stack but with the behavior of a Linked HashSet
* *
* <p>A stack must provide the classical {@link #push(Object)} and * <p>A stack must provide the classical {@link #push(Object)} and
* {@link #pop()} operations, but may be also <em>peekable</em> * {@link #pop()} operations, but may be also <em>peekable</em> to some extent: it may provide just the {@link #top()}
* to some extent: it may provide just the {@link #top()} function, * function, or even a more powerful {@link #peek(int)} method that provides access to all elements on the stack
* or even a more powerful {@link #peek(int)} method that provides * (indexed from the top, which has index 0).
* access to all elements on the stack (indexed from the top, which
* has index 0).
*/ */
public interface StackSet<K> { public interface StackSet<K> {
/** Pushes the given object on the stack. /**
* Pushes the given object on the stack.
* *
* @param o the object that will become the new top of the stack. * @param o the object that will become the new top of the stack.
* @return true if added, false if already present * @return true if added, false if already present
*/ */
boolean push(K o); boolean push(K o);
/** Pops the top off the stack. /**
* Pops the top off the stack.
* *
* @return the top of the stack. * @return the top of the stack.
* @throws NoSuchElementException if the stack is empty. * @throws NoSuchElementException if the stack is empty.
*/ */
K pop(); K pop();
/** Checks whether the stack is empty. /**
* Checks whether the stack is empty.
* *
* @return true if the stack is empty. * @return true if the stack is empty.
*/ */
boolean isEmpty(); boolean isEmpty();
/** Peeks at the top of the stack (optional operation). /**
* Peeks at the top of the stack (optional operation).
* *
* <p>This default implementation returns {@link #peek(int) peek(0)}. * <p>This default implementation returns {@link #peek(int) peek(0)}.
* *
* @return the top of the stack. * @return the top of the stack.
* @throws NoSuchElementException if the stack is empty. * @throws NoSuchElementException if the stack is empty.
*/ */
default K top() {
default K top() {
return peek(0); return peek(0);
} }
/** Peeks at an element on the stack (optional operation). /**
* Peeks at an element on the stack (optional operation).
* *
* <p>This default implementation just throws an {@link UnsupportedOperationException}. * <p>This default implementation just throws an {@link UnsupportedOperationException}.
* *
@ -61,7 +63,6 @@ public interface StackSet<K> {
* @return the {@code i}-th element on the stack. * @return the {@code i}-th element on the stack.
* @throws IndexOutOfBoundsException if the designated element does not exist.. * @throws IndexOutOfBoundsException if the designated element does not exist..
*/ */
default K peek(int i) { default K peek(int i) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -117,6 +117,22 @@ public class TestStackSet {
} }
} }
@Test
public void testStackSetCopyOrder() {
for (StackSet<String> implementation : getImplementations()) {
implementation.push("testBottom");
implementation.push("testMiddle");
implementation.push("testTop");
if (implementation instanceof FastUtilStackSetWrapper) {
var copy = new HashStackSet<>((FastUtilStackSetWrapper<String>) implementation);
Assertions.assertEquals("testTop", copy.pop());
Assertions.assertEquals("testMiddle", copy.pop());
Assertions.assertEquals("testBottom", copy.pop());
Assertions.assertTrue(copy.isEmpty());
}
}
}
@Test @Test
public void testStackSetOneItemOnePop() { public void testStackSetOneItemOnePop() {
for (StackSet<String> implementation : getImplementations()) { for (StackSet<String> implementation : getImplementations()) {