mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
Added an implemention of ArrayDeque, as well as unit tests
I also used this opportunity to reduce code duplication around other queue/deque implementations.
This commit is contained in:
90
classpath/java/util/AbstractDeque.java
Normal file
90
classpath/java/util/AbstractDeque.java
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright (c) 2008-2014, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.util;
|
||||
|
||||
public abstract class AbstractDeque<T> extends AbstractQueue<T>
|
||||
implements Deque<T> {
|
||||
|
||||
@Override
|
||||
public void push(T e) {
|
||||
addFirst(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLast(T element) {
|
||||
if (! offerLast(element)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFirst(T element) {
|
||||
if (! offerFirst(element)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(T element) {
|
||||
return offerLast(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T poll() {
|
||||
return pollFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T pop() {
|
||||
return removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T removeFirst() {
|
||||
return remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object element) {
|
||||
return removeFirstOccurrence(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T removeLast() {
|
||||
T result = pollLast();
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getFirst() {
|
||||
return element();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getLast() {
|
||||
T result = peekLast();
|
||||
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peek() {
|
||||
return peekFirst();
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ public abstract class AbstractQueue<T> extends AbstractCollection<T> implements
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
if (offer(element)) {
|
||||
return true;
|
||||
@ -23,7 +24,8 @@ public abstract class AbstractQueue<T> extends AbstractCollection<T> implements
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection <? extends T> collection) {
|
||||
if (collection == null) {
|
||||
throw new NullPointerException();
|
||||
@ -35,26 +37,31 @@ public abstract class AbstractQueue<T> extends AbstractCollection<T> implements
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
while (size() > 0) {
|
||||
poll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T element() {
|
||||
emptyCheck();
|
||||
return peek();
|
||||
}
|
||||
|
||||
public T remove() {
|
||||
emptyCheck();
|
||||
return poll();
|
||||
}
|
||||
|
||||
private void emptyCheck() {
|
||||
if (size() == 0) {
|
||||
T result = peek();
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove() {
|
||||
T result = poll();
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
364
classpath/java/util/ArrayDeque.java
Normal file
364
classpath/java/util/ArrayDeque.java
Normal file
@ -0,0 +1,364 @@
|
||||
/* Copyright (c) 2008-2014, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.util;
|
||||
|
||||
public class ArrayDeque<T> extends AbstractDeque<T>
|
||||
implements Deque<T> {
|
||||
private Object[] dataArray;
|
||||
// both indexes are inclusive, except when size == 0
|
||||
private int startIndex;
|
||||
private int endIndex;
|
||||
private int size;
|
||||
private int modCount;
|
||||
|
||||
public ArrayDeque() {
|
||||
this(16);
|
||||
}
|
||||
|
||||
public ArrayDeque(int intialSize) {
|
||||
dataArray = new Object[intialSize];
|
||||
modCount = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
public ArrayDeque(Collection<? extends T> c) {
|
||||
this(c.size());
|
||||
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
private void copyInto(Object[] array) {
|
||||
if (startIndex <= endIndex) {
|
||||
// only one copy needed
|
||||
System.arraycopy(dataArray, startIndex, array, 0, size);
|
||||
} else {
|
||||
int firstCopyCount = dataArray.length - startIndex;
|
||||
System.arraycopy(dataArray, startIndex, array, 0, firstCopyCount);
|
||||
System.arraycopy(dataArray, 0, array, firstCopyCount, endIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureCapacity(int newSize) {
|
||||
if (dataArray.length < newSize) {
|
||||
Object[] newArray = new Object[dataArray.length * 2];
|
||||
copyInto(newArray);
|
||||
|
||||
dataArray = newArray;
|
||||
startIndex = 0;
|
||||
endIndex = size - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offerFirst(T e) {
|
||||
ensureCapacity(size() + 1);
|
||||
modCount++;
|
||||
|
||||
if (size > 0) {
|
||||
// we don't need to move the head index for the first one
|
||||
startIndex--;
|
||||
if (startIndex < 0) { // wrapping to the end of the array
|
||||
startIndex = dataArray.length - 1;
|
||||
}
|
||||
}
|
||||
size++;
|
||||
dataArray[startIndex] = e;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offerLast(T e) {
|
||||
ensureCapacity(size() + 1);
|
||||
modCount++;
|
||||
|
||||
if (size > 0) {
|
||||
// we don't need to move the tail index for the first one
|
||||
endIndex = (endIndex + 1) % dataArray.length;
|
||||
}
|
||||
size++;
|
||||
dataArray[endIndex] = e;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T pollFirst() {
|
||||
modCount++;
|
||||
|
||||
if (size == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T result = (T)dataArray[startIndex];
|
||||
size--;
|
||||
if (size == 0) {
|
||||
startIndex = endIndex = 0;
|
||||
} else {
|
||||
startIndex = (startIndex + 1) % dataArray.length;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T pollLast() {
|
||||
modCount++;
|
||||
|
||||
if (size == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T result = (T)dataArray[endIndex];
|
||||
size--;
|
||||
if (size == 0) {
|
||||
startIndex = endIndex = 0;
|
||||
} else {
|
||||
endIndex--;
|
||||
if (endIndex < 0) {
|
||||
endIndex = dataArray.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peekFirst() {
|
||||
if (size == 0) {
|
||||
return null;
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
T result = (T)dataArray[startIndex];
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peekLast() {
|
||||
if (size == 0) {
|
||||
return null;
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
T result = (T)dataArray[endIndex];
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
if (c == null || c.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ensureCapacity(size() + c.size());
|
||||
|
||||
Iterator<? extends T> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
add(it.next());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
boolean removed = false;
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
removed = remove(it.next()) || removed;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
private boolean remove(Object o, boolean first) {
|
||||
modCount++;
|
||||
|
||||
Iterator<T> it;
|
||||
if (first) {
|
||||
it = iterator();
|
||||
} else {
|
||||
it = descendingIterator();
|
||||
}
|
||||
while (it.hasNext()) {
|
||||
T next = it.next();
|
||||
if (next == null) {
|
||||
if (o == null) {
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
} else if (next.equals(o)) {
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFirstOccurrence(Object o) {
|
||||
return remove(o, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLastOccurrence(Object o) {
|
||||
return remove(o, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
size = 0;
|
||||
startIndex = endIndex = 0;
|
||||
modCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object element) {
|
||||
Iterator<T> it = iterator();
|
||||
while (it.hasNext()) {
|
||||
T next = it.next();
|
||||
if (next == null) {
|
||||
if (element == null) {
|
||||
return true;
|
||||
}
|
||||
} else if (next.equals(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
if (! contains(it.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
Object[] result = new Object[size];
|
||||
copyInto(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> S[] toArray(S[] array) {
|
||||
return avian.Data.toArray(this, array);
|
||||
}
|
||||
|
||||
public Iterator<T> iterator() {
|
||||
return new GenericIterator() {
|
||||
@Override
|
||||
protected int getArrayIndex() {
|
||||
int result = (currentIndex + startIndex) % dataArray.length;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Iterator<T> descendingIterator() {
|
||||
return new GenericIterator() {
|
||||
@Override
|
||||
protected int getArrayIndex() {
|
||||
int result = (endIndex - currentIndex) % dataArray.length;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private abstract class GenericIterator implements Iterator<T> {
|
||||
protected int expectedModCount = modCount;
|
||||
protected int currentIndex = 0;
|
||||
|
||||
protected abstract int getArrayIndex();
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (modCount != expectedModCount) {
|
||||
throw new ConcurrentModificationException();
|
||||
} else if (currentIndex == size) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T result = (T)dataArray[getArrayIndex()];
|
||||
currentIndex++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentIndex < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
currentIndex--;
|
||||
|
||||
int removalIndex = getArrayIndex();
|
||||
if (removalIndex == startIndex) {
|
||||
// avoid array copy
|
||||
pollFirst();
|
||||
expectedModCount = modCount;
|
||||
} else if (removalIndex == endIndex) {
|
||||
// avoid array copy
|
||||
pollLast();
|
||||
expectedModCount = modCount;
|
||||
} else { // array must be copied
|
||||
Object[] newArray = new Object[dataArray.length];
|
||||
if (startIndex <= endIndex) {
|
||||
int firstCopyCount = removalIndex - startIndex;
|
||||
System.arraycopy(dataArray, startIndex,
|
||||
newArray, 0, firstCopyCount);
|
||||
System.arraycopy(dataArray, removalIndex + 1,
|
||||
newArray, firstCopyCount, size - firstCopyCount);
|
||||
} else if (removalIndex > startIndex) {
|
||||
int firstCopyCount = removalIndex - startIndex;
|
||||
System.arraycopy(dataArray, startIndex,
|
||||
newArray, 0, firstCopyCount);
|
||||
System.arraycopy(dataArray, startIndex + firstCopyCount + 1,
|
||||
newArray, firstCopyCount, dataArray.length - removalIndex - 1);
|
||||
System.arraycopy(dataArray, 0, newArray, size - removalIndex, endIndex + 1);
|
||||
} else {
|
||||
int firstCopyCount = dataArray.length - startIndex;
|
||||
System.arraycopy(dataArray, startIndex,
|
||||
newArray, 0, firstCopyCount);
|
||||
System.arraycopy(dataArray, 0,
|
||||
newArray, firstCopyCount, removalIndex);
|
||||
System.arraycopy(dataArray, removalIndex + 1,
|
||||
newArray, firstCopyCount + removalIndex, endIndex - removalIndex);
|
||||
}
|
||||
|
||||
dataArray = newArray;
|
||||
startIndex = 0;
|
||||
endIndex = --size - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.util.AbstractQueue;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Queue;
|
||||
|
||||
import avian.Atomic;
|
||||
|
||||
public class ConcurrentLinkedQueue<T> implements Queue<T> {
|
||||
public class ConcurrentLinkedQueue<T> extends AbstractQueue<T> {
|
||||
private static final long QueueHead;
|
||||
private static final long QueueTail;
|
||||
private static final long NodeNext;
|
||||
@ -67,31 +66,11 @@ public class ConcurrentLinkedQueue<T> implements Queue<T> {
|
||||
return poll(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T element() {
|
||||
T result = peek();
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T poll() {
|
||||
return poll(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove() {
|
||||
T result = poll();
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private T poll(boolean remove) {
|
||||
while (true) {
|
||||
Node<T> h = head;
|
||||
@ -150,12 +129,6 @@ public class ConcurrentLinkedQueue<T> implements Queue<T> {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> collection) {
|
||||
// TODO - implement
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object element) {
|
||||
// TODO - implement
|
||||
|
@ -1,11 +1,22 @@
|
||||
/* Copyright (c) 2008-2014, Avian Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software
|
||||
for any purpose with or without fee is hereby granted, provided
|
||||
that the above copyright notice and this permission notice appear
|
||||
in all copies.
|
||||
|
||||
There is NO WARRANTY for this software. See license.txt for
|
||||
details. */
|
||||
|
||||
package java.util.concurrent;
|
||||
|
||||
import java.util.AbstractQueue;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class LinkedBlockingQueue<T> implements BlockingQueue<T> {
|
||||
public class LinkedBlockingQueue<T> extends AbstractQueue<T>
|
||||
implements BlockingQueue<T> {
|
||||
private final Object collectionLock;
|
||||
private final LinkedList<T> storage;
|
||||
private final int capacity;
|
||||
@ -84,15 +95,6 @@ public class LinkedBlockingQueue<T> implements BlockingQueue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
if (! offer(element)) {
|
||||
throw new IllegalStateException("At capacity");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(T element) {
|
||||
synchronized (collectionLock) {
|
||||
@ -158,17 +160,6 @@ public class LinkedBlockingQueue<T> implements BlockingQueue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T element() {
|
||||
T result = peek();
|
||||
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// should be synchronized on collectionLock before calling
|
||||
private T removeFirst() {
|
||||
T result = storage.removeFirst();
|
||||
@ -209,17 +200,6 @@ public class LinkedBlockingQueue<T> implements BlockingQueue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove() {
|
||||
T result = poll();
|
||||
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drainTo(Collection<? super T> c) {
|
||||
return drainTo(c, Integer.MAX_VALUE);
|
||||
@ -256,11 +236,6 @@ public class LinkedBlockingQueue<T> implements BlockingQueue<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object element) {
|
||||
synchronized (collectionLock) {
|
||||
|
Reference in New Issue
Block a user