mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds ArrayDeque
This commit is contained in:
parent
2968ef9e83
commit
5fd2b18eba
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import org.teavm.classlib.java.lang.TIllegalStateException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public abstract class TAbstractQueue<E> extends TAbstractCollection<E> implements TQueue<E> {
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
if (offer(e)) {
|
||||
return true;
|
||||
}
|
||||
throw new TIllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove() {
|
||||
if (isEmpty()) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
return poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E element() {
|
||||
if (isEmpty()) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
return peek();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
while (!isEmpty()) {
|
||||
poll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(TCollection<? extends E> c) {
|
||||
boolean oneAdded = false;
|
||||
for (TIterator<? extends E> iter = c.iterator(); iter.hasNext();) {
|
||||
oneAdded |= add(iter.next());
|
||||
}
|
||||
return oneAdded;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.teavm.classlib.java.lang.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E> {
|
||||
private int version;
|
||||
private Object[] array;
|
||||
private int head;
|
||||
private int tail;
|
||||
|
||||
public TArrayDeque() {
|
||||
this(8);
|
||||
}
|
||||
|
||||
public TArrayDeque(int numElements) {
|
||||
array = new Object[numElements + 1];
|
||||
}
|
||||
|
||||
public TArrayDeque(TCollection<? extends E> c) {
|
||||
if (c.isEmpty()) {
|
||||
array = new Object[8];
|
||||
} else {
|
||||
array = new Object[c.size() + 1];
|
||||
int index = 0;
|
||||
for (TIterator<? extends E> iter = c.iterator(); iter.hasNext();) {
|
||||
array[index++] = iter.next();
|
||||
}
|
||||
tail = array.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFirst(E e) {
|
||||
if (e == null) {
|
||||
throw new TNullPointerException();
|
||||
}
|
||||
ensureCapacity(size() + 1);
|
||||
--head;
|
||||
if (head < 0) {
|
||||
head += array.length;
|
||||
}
|
||||
array[head] = e;
|
||||
++version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLast(E e) {
|
||||
if (e == null) {
|
||||
throw new TNullPointerException();
|
||||
}
|
||||
ensureCapacity(size() + 1);
|
||||
array[tail++] = e;
|
||||
if (tail >= array.length) {
|
||||
tail = 0;
|
||||
}
|
||||
++version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offerFirst(E e) {
|
||||
addFirst(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offerLast(E e) {
|
||||
addLast(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeFirst() {
|
||||
E value = pollFirst();
|
||||
if (value == null) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeLast() {
|
||||
E value = pollLast();
|
||||
if (value == null) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pollFirst() {
|
||||
if (head == tail) {
|
||||
return null;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
E result = (E)array[head];
|
||||
array[head] = null;
|
||||
head++;
|
||||
if (head >= array.length) {
|
||||
head = 0;
|
||||
}
|
||||
++version;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pollLast() {
|
||||
if (head == tail) {
|
||||
return null;
|
||||
}
|
||||
--tail;
|
||||
if (tail < 0) {
|
||||
tail = array.length - 1;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
E result = (E)array[tail];
|
||||
array[tail] = null;
|
||||
++version;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFirst() {
|
||||
E result = peekFirst();
|
||||
if (result == null) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getLast() {
|
||||
E result = peekLast();
|
||||
if (result == null) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public E peekFirst() {
|
||||
return !isEmpty() ? (E)array[head] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public E peekLast() {
|
||||
return !isEmpty() ? (E)array[tail > 0 ? tail - 1 : array.length - 1] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFirstOccurrence(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
for (TIterator<E> iter = iterator(); iter.hasNext();) {
|
||||
if (iter.next().equals(o)) {
|
||||
iter.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeLastOccurrence(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
for (TIterator<E> iter = descendingIterator(); iter.hasNext();) {
|
||||
if (iter.next().equals(o)) {
|
||||
iter.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
addLast(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e) {
|
||||
return offerLast(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove() {
|
||||
return removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll() {
|
||||
return pollFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E element() {
|
||||
return getFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peek() {
|
||||
return peekFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(E e) {
|
||||
addFirst(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E pop() {
|
||||
return removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return tail >= head ? tail - head : array.length - head + tail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return head == tail;
|
||||
}
|
||||
|
||||
private void removeAt(int index) {
|
||||
if (head < tail) {
|
||||
if (tail - index < index - head) {
|
||||
for (int i = index + 1; i < tail; ++i) {
|
||||
array[i - 1] = array[i];
|
||||
}
|
||||
array[tail - 1] = null;
|
||||
} else {
|
||||
for (int i = index - 1; i >= head; --i) {
|
||||
array[i + 1] = array[i];
|
||||
}
|
||||
array[head] = null;
|
||||
}
|
||||
} else {
|
||||
if (index >= head) {
|
||||
for (int i = index - 1; i >= head; --i) {
|
||||
array[i + 1] = array[i];
|
||||
}
|
||||
array[head] = null;
|
||||
} else {
|
||||
for (int i = index + 1; i < tail; ++i) {
|
||||
array[i - 1] = array[i];
|
||||
}
|
||||
array[tail - 1] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIterator<E> iterator() {
|
||||
return new TIterator<E>() {
|
||||
private int refVersion = version;
|
||||
private int index = head;
|
||||
private int lastIndex = -1;
|
||||
private boolean wrapped = head <= tail;
|
||||
@Override public boolean hasNext() {
|
||||
return !wrapped || index < tail;
|
||||
}
|
||||
@Override public E next() {
|
||||
if (version > refVersion) {
|
||||
throw new TConcurrentModificationException();
|
||||
}
|
||||
lastIndex = index;
|
||||
@SuppressWarnings("unchecked")
|
||||
E result = (E)array[index++];
|
||||
if (index >= array.length) {
|
||||
index = 0;
|
||||
wrapped = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@Override public void remove() {
|
||||
removeAt(lastIndex);
|
||||
lastIndex = -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIterator<E> descendingIterator() {
|
||||
return new TIterator<E>() {
|
||||
private int refVersion = version;
|
||||
private int index = tail;
|
||||
private int lastIndex = -1;
|
||||
private boolean wrapped = head <= tail;
|
||||
@Override public boolean hasNext() {
|
||||
return !wrapped || index > head;
|
||||
}
|
||||
@Override public E next() {
|
||||
if (version > refVersion) {
|
||||
throw new TConcurrentModificationException();
|
||||
}
|
||||
--index;
|
||||
if (index < 0) {
|
||||
index = array.length - 1;
|
||||
wrapped = true;
|
||||
}
|
||||
lastIndex = index;
|
||||
@SuppressWarnings("unchecked")
|
||||
E result = (E)array[index];
|
||||
return result;
|
||||
}
|
||||
@Override public void remove() {
|
||||
removeAt(lastIndex);
|
||||
lastIndex = -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void ensureCapacity(int capacity) {
|
||||
if (capacity < array.length) {
|
||||
return;
|
||||
}
|
||||
int newArraySize = TMath.max(array.length * 2, capacity * 3 / 2 + 1);
|
||||
if (newArraySize < 1) {
|
||||
newArraySize = TInteger.MAX_VALUE;
|
||||
}
|
||||
Object[] newArray = new Object[newArraySize];
|
||||
int j = 0;
|
||||
if (head <= tail) {
|
||||
for (int i = head; i < tail; ++i) {
|
||||
newArray[j++] = array[i];
|
||||
}
|
||||
} else {
|
||||
for (int i = head; i < array.length; ++i) {
|
||||
newArray[j++] = array[i];
|
||||
}
|
||||
for (int i = 0; i < tail; ++i) {
|
||||
newArray[j++] = array[i];
|
||||
}
|
||||
}
|
||||
head = 0;
|
||||
tail = j;
|
||||
array = newArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(array, null);
|
||||
head = tail;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TArrayDeque<E> clone() {
|
||||
return new TArrayDeque<>(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class ArrayDequeTest {
|
||||
@Test
|
||||
public void addsToFront() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
deque.addFirst(1);
|
||||
deque.addFirst(2);
|
||||
Iterator<Integer> iter = deque.iterator();
|
||||
assertEquals(2, deque.size());
|
||||
assertEquals((Integer)2, iter.next());
|
||||
assertEquals((Integer)1, iter.next());
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addsToBack() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
deque.addLast(1);
|
||||
deque.addLast(2);
|
||||
Iterator<Integer> iter = deque.iterator();
|
||||
assertEquals(2, deque.size());
|
||||
assertEquals((Integer)1, iter.next());
|
||||
assertEquals((Integer)2, iter.next());
|
||||
assertFalse(iter.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addsManyToFront() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
deque.addFirst(i);
|
||||
}
|
||||
assertEquals(1000, deque.size());
|
||||
Iterator<Integer> iter = deque.iterator();
|
||||
assertEquals((Integer)999, iter.next());
|
||||
for (int i = 2; i < 500; ++i) {
|
||||
iter.next();
|
||||
}
|
||||
assertEquals((Integer)500, iter.next());
|
||||
for (int i = 1; i < 500; ++i) {
|
||||
iter.next();
|
||||
}
|
||||
assertEquals((Integer)0, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addsManyToBack() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
deque.addLast(i);
|
||||
}
|
||||
assertEquals(1000, deque.size());
|
||||
Iterator<Integer> iter = deque.iterator();
|
||||
assertEquals((Integer)0, iter.next());
|
||||
for (int i = 1; i < 500; ++i) {
|
||||
iter.next();
|
||||
}
|
||||
assertEquals((Integer)500, iter.next());
|
||||
for (int i = 2; i < 500; ++i) {
|
||||
iter.next();
|
||||
}
|
||||
assertEquals((Integer)999, iter.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removesFromFront() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
deque.addFirst(1);
|
||||
deque.addFirst(2);
|
||||
assertEquals((Integer)2, deque.removeFirst());
|
||||
assertEquals((Integer)1, deque.removeFirst());
|
||||
assertEquals(0, deque.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removesFromBack() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
deque.addFirst(1);
|
||||
deque.addFirst(2);
|
||||
assertEquals((Integer)1, deque.removeLast());
|
||||
assertEquals((Integer)2, deque.removeLast());
|
||||
assertEquals(0, deque.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAndRemoves() {
|
||||
Deque<Integer> deque = new ArrayDeque<>();
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
deque.addLast(i);
|
||||
}
|
||||
assertEquals((Integer)0, deque.removeFirst());
|
||||
for (int i = 1; i < 20; ++i) {
|
||||
deque.removeFirst();
|
||||
}
|
||||
assertEquals((Integer)20, deque.removeFirst());
|
||||
for (int i = 101; i < 111; ++i) {
|
||||
deque.addLast(i);
|
||||
}
|
||||
assertEquals((Integer)110, deque.removeLast());
|
||||
for (int i = 2; i < 40; ++i) {
|
||||
deque.removeLast();
|
||||
}
|
||||
assertEquals((Integer)70, deque.removeLast());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user