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;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import java.util.Collection;
import org.jetbrains.annotations.NotNull;
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 ObjectLinkedOpenHashSet<T> linkedHashSet;
/**
* The first element will be the head
*/
public FastUtilStackSetWrapper(ObjectLinkedOpenHashSet<T> linkedHashSet) {
this(linkedHashSet, AddStrategy.getDefault());
}
/**
* The first element will be the head
*/
public FastUtilStackSetWrapper(ObjectLinkedOpenHashSet<T> linkedHashSet, AddStrategy addStrategy) {
this.addStrategy = addStrategy;
this.linkedHashSet = linkedHashSet;
@ -21,17 +29,79 @@ public class FastUtilStackSetWrapper<T> implements StackSet<T> {
public boolean push(T o) {
switch (addStrategy) {
case KEEP_POSITION:
return linkedHashSet.add(o);
if (linkedHashSet.contains(o)) {
return false;
}
return linkedHashSet.addAndMoveToFirst(o);
case OVERWRITE_POSITION:
return linkedHashSet.addAndMoveToLast(o);
return linkedHashSet.addAndMoveToFirst(o);
default:
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
public T pop() {
return linkedHashSet.removeLast();
return linkedHashSet.removeFirst();
}
@Override
public int size() {
return linkedHashSet.size();
}
@Override
@ -39,24 +109,27 @@ public class FastUtilStackSetWrapper<T> implements StackSet<T> {
return linkedHashSet.isEmpty();
}
@Override
public boolean contains(Object o) {
return linkedHashSet.contains(o);
}
@Override
public T top() {
return linkedHashSet.last();
return linkedHashSet.first();
}
@Override
public T peek(int i) {
var size = linkedHashSet.size();
int positionFromBottom = size - 1 - i;
if (positionFromBottom < 0 || positionFromBottom >= size) {
throw new IndexOutOfBoundsException(positionFromBottom, 0, size);
if (i < 0 || i >= size) {
throw new IndexOutOfBoundsException(i, 0, size);
}
var it = linkedHashSet.iterator();
// Skip middle elements
if (positionFromBottom > 0) {
it.skip(positionFromBottom);
if (i > 0) {
it.skip(i);
}
return it.next();
}

View File

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

View File

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

View File

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