classlib: inheritDeque from SequencedCollection, fix ArrayDeque (#765)

Second part of JEP-431
This commit is contained in:
Ivan Hetman 2023-09-28 15:35:41 +03:00 committed by GitHub
parent ada85b4c07
commit 0ef08a01e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 480 additions and 106 deletions

View File

@ -16,9 +16,10 @@
package org.teavm.classlib.java.util; package org.teavm.classlib.java.util;
import java.util.Arrays; import java.util.Arrays;
import org.teavm.classlib.java.lang.*; import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TCloneable;
public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E> { public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>, TCloneable, TSerializable {
private int version; private int version;
private Object[] array; private Object[] array;
private int head; private int head;
@ -38,8 +39,8 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
} else { } else {
array = new Object[c.size() + 1]; array = new Object[c.size() + 1];
int index = 0; int index = 0;
for (TIterator<? extends E> iter = c.iterator(); iter.hasNext();) { for (var it = c.iterator(); it.hasNext();) {
array[index++] = iter.next(); array[index++] = it.next();
} }
tail = array.length - 1; tail = array.length - 1;
} }
@ -47,28 +48,19 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
@Override @Override
public void addFirst(E e) { public void addFirst(E e) {
if (e == null) { TObjects.requireNonNull(e);
throw new TNullPointerException();
}
ensureCapacity(size() + 1); ensureCapacity(size() + 1);
--head; head = modDec(head, array.length);
if (head < 0) {
head += array.length;
}
array[head] = e; array[head] = e;
++version; ++version;
} }
@Override @Override
public void addLast(E e) { public void addLast(E e) {
if (e == null) { TObjects.requireNonNull(e);
throw new TNullPointerException();
}
ensureCapacity(size() + 1); ensureCapacity(size() + 1);
array[tail++] = e; array[tail] = e;
if (tail >= array.length) { tail = modInc(tail, array.length);
tail = 0;
}
++version; ++version;
} }
@ -110,10 +102,7 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
E result = (E) array[head]; E result = (E) array[head];
array[head] = null; array[head] = null;
head++; head = modInc(head, array.length);
if (head >= array.length) {
head = 0;
}
++version; ++version;
return result; return result;
} }
@ -123,10 +112,7 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
if (head == tail) { if (head == tail) {
return null; return null;
} }
--tail; tail = modDec(tail, array.length);
if (tail < 0) {
tail = array.length - 1;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
E result = (E) array[tail]; E result = (E) array[tail];
array[tail] = null; array[tail] = null;
@ -161,7 +147,7 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public E peekLast() { public E peekLast() {
return !isEmpty() ? (E) array[tail > 0 ? tail - 1 : array.length - 1] : null; return !isEmpty() ? (E) array[modDec(tail, array.length)] : null;
} }
@Override @Override
@ -169,9 +155,9 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
if (o == null) { if (o == null) {
return false; return false;
} }
for (TIterator<E> iter = iterator(); iter.hasNext();) { for (var it = iterator(); it.hasNext();) {
if (iter.next().equals(o)) { if (it.next().equals(o)) {
iter.remove(); it.remove();
return true; return true;
} }
} }
@ -183,9 +169,9 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
if (o == null) { if (o == null) {
return false; return false;
} }
for (TIterator<E> iter = descendingIterator(); iter.hasNext();) { for (var it = descendingIterator(); it.hasNext();) {
if (iter.next().equals(o)) { if (it.next().equals(o)) {
iter.remove(); it.remove();
return true; return true;
} }
} }
@ -243,68 +229,85 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
return head == tail; return head == tail;
} }
private void removeAt(int index) { private boolean removeAt(int index) {
if (head < tail) { if (head < tail) {
if (tail - index < index - head) { if (tail - index < index - head) {
for (int i = index + 1; i < tail; ++i) { for (int i = index + 1; i < tail; ++i) {
array[i - 1] = array[i]; array[i - 1] = array[i];
} }
array[--tail] = null; array[--tail] = null;
return true;
} else { } else {
for (int i = index - 1; i >= head; --i) { for (int i = index - 1; i >= head; --i) {
array[i + 1] = array[i]; array[i + 1] = array[i];
} }
array[head++] = null; array[head++] = null;
return false;
} }
} else { } else {
if (index >= head) { if (index >= head) {
for (int i = index - 1; i >= head; --i) { for (int i = index - 1; i >= head; --i) {
array[i + 1] = array[i]; array[i + 1] = array[i];
} }
array[head++] = null; array[head] = null;
if (head >= array.length) { head = modInc(head, array.length);
head = 0; return false;
}
} else { } else {
for (int i = index + 1; i < tail; ++i) { for (int i = index + 1; i < tail; ++i) {
array[i - 1] = array[i]; array[i - 1] = array[i];
} }
if (--tail < 0) { tail = modDec(tail, array.length);
tail += array.length;
}
array[tail] = null; array[tail] = null;
return true;
} }
} }
} }
private static int modInc(int i, int mod) {
return ++i == mod ? 0 : i;
}
private static int modDec(int i, int mod) {
return --i == -1 ? mod - 1 : i;
}
@Override @Override
public TIterator<E> iterator() { public TIterator<E> iterator() {
return new TIterator<E>() { return new TIterator<>() {
private int refVersion = version; private int refVersion = version;
private int index = head; private int index = head;
private int lastIndex = -1; private int lastIndex = -1;
private boolean wrapped = head <= tail; private int left = size();
@Override public boolean hasNext() {
return !wrapped || index < tail; @Override
public boolean hasNext() {
return left > 0;
} }
@Override public E next() {
@Override
public E next() {
if (--left < 0) {
throw new TNoSuchElementException();
}
if (version > refVersion) { if (version > refVersion) {
throw new TConcurrentModificationException(); throw new TConcurrentModificationException();
} }
lastIndex = index; lastIndex = index;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
E result = (E) array[index++]; E result = (E) array[index];
if (index >= array.length) { index = modInc(index, array.length);
index = 0;
wrapped = true;
}
return result; return result;
} }
@Override public void remove() {
@Override
public void remove() {
if (lastIndex < 0) { if (lastIndex < 0) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
removeAt(lastIndex); boolean toLeft = removeAt(lastIndex);
if (toLeft) {
index = modInc(index, array.length);
}
lastIndex = -1; lastIndex = -1;
} }
}; };
@ -312,30 +315,41 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
@Override @Override
public TIterator<E> descendingIterator() { public TIterator<E> descendingIterator() {
return new TIterator<E>() { return new TIterator<>() {
private int refVersion = version; private int refVersion = version;
private int index = tail; private int index = tail;
private int lastIndex = -1; private int lastIndex = -1;
private boolean wrapped = head <= tail; private int left = size();
@Override public boolean hasNext() {
return !wrapped || index > head; @Override
public boolean hasNext() {
return left > 0;
} }
@Override public E next() {
@Override
public E next() {
if (--left < 0) {
throw new TNoSuchElementException();
}
if (version > refVersion) { if (version > refVersion) {
throw new TConcurrentModificationException(); throw new TConcurrentModificationException();
} }
--index; index = modDec(index, array.length);
if (index < 0) {
index = array.length - 1;
wrapped = true;
}
lastIndex = index; lastIndex = index;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
E result = (E) array[index]; E result = (E) array[index];
return result; return result;
} }
@Override public void remove() {
removeAt(lastIndex); @Override
public void remove() {
if (lastIndex < 0) {
throw new IllegalStateException();
}
boolean toLeft = removeAt(lastIndex);
if (!toLeft) {
index = modInc(index, array.length);
}
lastIndex = -1; lastIndex = -1;
} }
}; };
@ -345,9 +359,9 @@ public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E>
if (capacity < array.length) { if (capacity < array.length) {
return; return;
} }
int newArraySize = TMath.max(array.length * 2, capacity * 3 / 2 + 1); int newArraySize = Math.max(array.length * 2, capacity * 3 / 2 + 1);
if (newArraySize < 1) { if (newArraySize < 1) {
newArraySize = TInteger.MAX_VALUE; newArraySize = Integer.MAX_VALUE;
} }
Object[] newArray = new Object[newArraySize]; Object[] newArray = new Object[newArraySize];
int j = 0; int j = 0;

View File

@ -16,31 +16,18 @@
package org.teavm.classlib.java.util; package org.teavm.classlib.java.util;
/** /**
*
* @author Alexey Andreev
* @param <E> * @param <E>
* @author Alexey Andreev
*/ */
public interface TDeque<E> extends TQueue<E> { public interface TDeque<E> extends TQueue<E>, TSequencedCollection<E> {
void addFirst(E e);
void addLast(E e);
boolean offerFirst(E e); boolean offerFirst(E e);
boolean offerLast(E e); boolean offerLast(E e);
E removeFirst();
E removeLast();
E pollFirst(); E pollFirst();
E pollLast(); E pollLast();
E getFirst();
E getLast();
E peekFirst(); E peekFirst();
E peekLast(); E peekLast();
@ -54,4 +41,9 @@ public interface TDeque<E> extends TQueue<E> {
E pop(); E pop();
TIterator<E> descendingIterator(); TIterator<E> descendingIterator();
@Override
default TDeque<E> reversed() {
return new TReversedDeque<>(this);
}
} }

View File

@ -0,0 +1,253 @@
/*
* Copyright 2023 ihromant.
*
* 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.lang.reflect.Array;
class TReversedDeque<E> implements TDeque<E> {
private final TDeque<E> base;
TReversedDeque(TDeque<E> base) {
this.base = base;
}
@Override
public TDeque<E> reversed() {
return base;
}
@Override
public TIterator<E> iterator() {
return base.descendingIterator();
}
@Override
public int size() {
return base.size();
}
@Override
public boolean isEmpty() {
return base.isEmpty();
}
@Override
public boolean contains(Object o) {
return base.contains(o);
}
@Override
public Object[] toArray() {
Object[] arr = new Object[size()];
int i = 0;
for (var it = base.descendingIterator(); it.hasNext();) {
arr[i++] = it.next();
}
return arr;
}
@SuppressWarnings("unchecked")
@Override
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size) {
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
} else {
for (int i = size; i < a.length; ++i) {
a[i] = null;
}
}
int i = 0;
for (var it = base.descendingIterator(); it.hasNext();) {
a[i++] = (T) it.next();
}
return a;
}
@Override
public boolean add(E e) {
base.addFirst(e);
return true;
}
@Override
public void addFirst(E e) {
base.addLast(e);
}
@Override
public void addLast(E e) {
base.addFirst(e);
}
@Override
public boolean remove(Object o) {
for (var it = base.descendingIterator(); it.hasNext();) {
E e = it.next();
if (TObjects.equals(e, o)) {
it.remove();
return true;
}
}
return false;
}
@Override
public boolean containsAll(TCollection<?> c) {
return base.contains(c);
}
@Override
public boolean addAll(TCollection<? extends E> c) {
boolean changed = false;
for (var it = c.iterator(); it.hasNext();) {
addFirst(it.next());
changed = true;
}
return changed;
}
@Override
public boolean removeAll(TCollection<?> c) {
boolean changed = false;
for (var it = base.descendingIterator(); it.hasNext();) {
E e = it.next();
if (c.contains(e)) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
public boolean retainAll(TCollection<?> c) {
boolean changed = false;
for (var it = base.descendingIterator(); it.hasNext();) {
E e = it.next();
if (!c.contains(e)) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
public void clear() {
base.clear();
}
@Override
public boolean offerFirst(E e) {
return base.offerLast(e);
}
@Override
public boolean offerLast(E e) {
return base.offerFirst(e);
}
@Override
public E pollFirst() {
return base.pollLast();
}
@Override
public E pollLast() {
return base.pollFirst();
}
@Override
public E peekFirst() {
return base.peekLast();
}
@Override
public E peekLast() {
return base.peekFirst();
}
@Override
public boolean removeFirstOccurrence(Object o) {
return base.removeLastOccurrence(o);
}
@Override
public boolean removeLastOccurrence(Object o) {
return base.removeFirstOccurrence(o);
}
@Override
public void push(E e) {
base.addLast(e);
}
@Override
public E pop() {
return base.removeLast();
}
@Override
public TIterator<E> descendingIterator() {
return base.iterator();
}
@Override
public boolean offer(E e) {
return base.offerFirst(e);
}
@Override
public E remove() {
return base.removeLast();
}
@Override
public E removeFirst() {
return base.removeLast();
}
@Override
public E removeLast() {
return base.removeFirst();
}
@Override
public E poll() {
return base.pollLast();
}
@Override
public E element() {
return base.getLast();
}
@Override
public E getFirst() {
return base.getLast();
}
@Override
public E getLast() {
return base.getFirst();
}
@Override
public E peek() {
return base.peekLast();
}
}

View File

@ -15,12 +15,16 @@
*/ */
package org.teavm.classlib.java.util; package org.teavm.classlib.java.util;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
import java.util.Iterator; import java.util.Iterator;
import org.junit.Assert; import java.util.List;
import java.util.NoSuchElementException;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.teavm.junit.TeaVMTestRunner; import org.teavm.junit.TeaVMTestRunner;
@ -137,19 +141,19 @@ public class ArrayDequeTest {
Object object2 = new Object(); Object object2 = new Object();
Object object3 = new Object(); Object object3 = new Object();
arrayDeque.add(object1); arrayDeque.add(object1);
Assert.assertTrue(arrayDeque.size() == 1); assertEquals(1, arrayDeque.size());
arrayDeque.remove(object1); arrayDeque.remove(object1);
Assert.assertTrue(arrayDeque.size() == 0); assertEquals(0, arrayDeque.size());
arrayDeque.add(object1); arrayDeque.add(object1);
arrayDeque.add(object2); arrayDeque.add(object2);
arrayDeque.add(object3); arrayDeque.add(object3);
Assert.assertTrue(arrayDeque.size() == 3); assertEquals(3, arrayDeque.size());
arrayDeque.remove(object1); arrayDeque.remove(object1);
arrayDeque.remove(object2); arrayDeque.remove(object2);
arrayDeque.remove(object3); arrayDeque.remove(object3);
Assert.assertTrue(arrayDeque.size() == 0); assertEquals(0, arrayDeque.size());
arrayDeque.remove(object1); arrayDeque.remove(object1);
Assert.assertTrue(arrayDeque.size() == 0); assertEquals(0, arrayDeque.size());
} }
@Test @Test
@ -162,9 +166,9 @@ public class ArrayDequeTest {
arrayDeque1.add(object2); arrayDeque1.add(object2);
arrayDeque1.add(object3); arrayDeque1.add(object3);
arrayDeque1.removeFirst(); arrayDeque1.removeFirst();
Assert.assertTrue(arrayDeque1.size() == 2); assertEquals(2, arrayDeque1.size());
Assert.assertTrue(arrayDeque1.contains(object2)); assertTrue(arrayDeque1.contains(object2));
Assert.assertTrue(arrayDeque1.contains(object3)); assertTrue(arrayDeque1.contains(object3));
ArrayDeque<Object> arrayDeque2 = new ArrayDeque<>(); ArrayDeque<Object> arrayDeque2 = new ArrayDeque<>();
arrayDeque2.add(object1); arrayDeque2.add(object1);
@ -172,8 +176,8 @@ public class ArrayDequeTest {
arrayDeque2.add(object3); arrayDeque2.add(object3);
arrayDeque2.remove(object1); arrayDeque2.remove(object1);
arrayDeque2.removeFirst(); arrayDeque2.removeFirst();
Assert.assertTrue(arrayDeque2.size() == 1); assertEquals(1, arrayDeque2.size());
Assert.assertTrue(arrayDeque2.contains(object3)); assertTrue(arrayDeque2.contains(object3));
ArrayDeque<Object> arrayDeque3 = new ArrayDeque<>(); ArrayDeque<Object> arrayDeque3 = new ArrayDeque<>();
arrayDeque3.add(object1); arrayDeque3.add(object1);
@ -181,8 +185,8 @@ public class ArrayDequeTest {
arrayDeque3.add(object3); arrayDeque3.add(object3);
arrayDeque3.remove(object2); arrayDeque3.remove(object2);
arrayDeque3.removeFirst(); arrayDeque3.removeFirst();
Assert.assertTrue(arrayDeque3.size() == 1); assertEquals(1, arrayDeque3.size());
Assert.assertTrue(arrayDeque3.contains(object3)); assertTrue(arrayDeque3.contains(object3));
ArrayDeque<Object> arrayDeque4 = new ArrayDeque<>(); ArrayDeque<Object> arrayDeque4 = new ArrayDeque<>();
arrayDeque4.add(object1); arrayDeque4.add(object1);
@ -190,8 +194,8 @@ public class ArrayDequeTest {
arrayDeque4.add(object3); arrayDeque4.add(object3);
arrayDeque4.remove(object3); arrayDeque4.remove(object3);
arrayDeque4.removeFirst(); arrayDeque4.removeFirst();
Assert.assertTrue(arrayDeque4.size() == 1); assertEquals(1, arrayDeque4.size());
Assert.assertTrue(arrayDeque4.contains(object2)); assertTrue(arrayDeque4.contains(object2));
} }
@Test @Test
@ -204,9 +208,9 @@ public class ArrayDequeTest {
arrayDeque1.add(object2); arrayDeque1.add(object2);
arrayDeque1.add(object3); arrayDeque1.add(object3);
arrayDeque1.removeLast(); arrayDeque1.removeLast();
Assert.assertTrue(arrayDeque1.size() == 2); assertEquals(2, arrayDeque1.size());
Assert.assertTrue(arrayDeque1.contains(object1)); assertTrue(arrayDeque1.contains(object1));
Assert.assertTrue(arrayDeque1.contains(object2)); assertTrue(arrayDeque1.contains(object2));
ArrayDeque<Object> arrayDeque2 = new ArrayDeque<>(); ArrayDeque<Object> arrayDeque2 = new ArrayDeque<>();
arrayDeque2.add(object1); arrayDeque2.add(object1);
@ -214,8 +218,8 @@ public class ArrayDequeTest {
arrayDeque2.add(object3); arrayDeque2.add(object3);
arrayDeque2.remove(object3); arrayDeque2.remove(object3);
arrayDeque2.removeLast(); arrayDeque2.removeLast();
Assert.assertTrue(arrayDeque2.size() == 1); assertEquals(1, arrayDeque2.size());
Assert.assertTrue(arrayDeque2.contains(object1)); assertTrue(arrayDeque2.contains(object1));
ArrayDeque<Object> arrayDeque3 = new ArrayDeque<>(); ArrayDeque<Object> arrayDeque3 = new ArrayDeque<>();
arrayDeque3.add(object1); arrayDeque3.add(object1);
@ -223,8 +227,8 @@ public class ArrayDequeTest {
arrayDeque3.add(object3); arrayDeque3.add(object3);
arrayDeque3.remove(object2); arrayDeque3.remove(object2);
arrayDeque3.removeLast(); arrayDeque3.removeLast();
Assert.assertTrue(arrayDeque3.size() == 1); assertEquals(1, arrayDeque3.size());
Assert.assertTrue(arrayDeque3.contains(object1)); assertTrue(arrayDeque3.contains(object1));
ArrayDeque<Object> arrayDeque4 = new ArrayDeque<>(); ArrayDeque<Object> arrayDeque4 = new ArrayDeque<>();
arrayDeque4.add(object1); arrayDeque4.add(object1);
@ -232,8 +236,8 @@ public class ArrayDequeTest {
arrayDeque4.add(object3); arrayDeque4.add(object3);
arrayDeque4.remove(object3); arrayDeque4.remove(object3);
arrayDeque4.removeLast(); arrayDeque4.removeLast();
Assert.assertTrue(arrayDeque4.size() == 1); assertEquals(1, arrayDeque4.size());
Assert.assertTrue(arrayDeque4.contains(object1)); assertTrue(arrayDeque4.contains(object1));
} }
@Test @Test
@ -254,4 +258,115 @@ public class ArrayDequeTest {
arrayDeque.removeLast(); arrayDeque.removeLast();
} }
} }
@Test
public void testSequencedCollectionReadOnly() {
Deque<String> deque = new ArrayDeque<>(List.of("0", "1", "2", "3", "4", "5", "6"));
Deque<String> reversed = deque.reversed();
Iterator<String> it = reversed.iterator();
assertEquals("6", it.next());
assertEquals("5", it.next());
assertEquals("6", reversed.getFirst());
assertEquals("0", reversed.getLast());
assertEquals("6", reversed.peek());
assertEquals("6", reversed.peekFirst());
assertEquals("0", reversed.peekLast());
}
@Test
public void testSequencedCollectionMutations() {
Deque<String> deque = new ArrayDeque<>(List.of("a", "b", "c", "d"));
assertEquals("a", deque.removeFirst());
assertEquals("d", deque.removeLast());
deque.addFirst("u");
deque.addLast("e");
assertArrayEquals(new String[] { "u", "b", "c", "e" }, deque.toArray());
deque = new ArrayDeque<>(List.of("a", "b", "c", "d")).reversed();
assertEquals("d", deque.removeFirst());
assertEquals("a", deque.removeLast());
deque.addFirst("u");
deque.addLast("e");
assertEquals("u", deque.remove());
deque.add("f");
assertArrayEquals(new String[] { "c", "b", "e", "f" }, deque.toArray());
}
@Test
public void testSequencedCollectionIterator() {
Deque<String> deque = new ArrayDeque<>(List.of("a", "b", "c", "d"));
deque.addLast("e");
deque.addLast("f");
Iterator<String> it = deque.iterator();
assertEquals("a", it.next());
it.remove();
assertEquals("b", it.next());
it.remove();
assertEquals("c", it.next());
it.remove();
assertEquals("d", it.next());
it.remove();
assertEquals("e", it.next());
it.remove();
assertEquals("f", it.next());
it.remove();
assertTrue(deque.isEmpty());
try {
it.next();
fail();
} catch (NoSuchElementException e) {
// ok
}
deque = new ArrayDeque<>(List.of("a", "b", "c", "d")).reversed();
it = deque.iterator();
assertEquals("d", it.next());
assertEquals("c", it.next());
it.remove();
assertArrayEquals(new String[] { "d", "b", "a" }, deque.toArray());
deque = new ArrayDeque<>(List.of("a", "b", "c", "d")).reversed();
it = deque.iterator();
assertEquals("d", it.next());
assertEquals("c", it.next());
it.remove();
assertEquals("b", it.next());
it.remove();
assertEquals("a", it.next());
try {
it.next();
fail();
} catch (NoSuchElementException e) {
// ok
}
assertArrayEquals(new String[] { "d", "a" }, deque.toArray());
}
@Test
public void sequenceCollectionMethodsOnEmpty() {
var empty = new ArrayDeque<>();
try {
empty.getFirst();
fail();
} catch (NoSuchElementException e) {
// ok
}
try {
empty.getLast();
fail();
} catch (NoSuchElementException e) {
// ok
}
try {
empty.removeFirst();
fail();
} catch (NoSuchElementException e) {
// ok
}
try {
empty.removeLast();
fail();
} catch (NoSuchElementException e) {
// ok
}
}
} }