Adds incomplete implementation of LinkedList

This commit is contained in:
konsoletyper 2014-05-06 17:00:33 +04:00
parent e9af85534f
commit 1bd0a42103
3 changed files with 419 additions and 0 deletions

View File

@ -0,0 +1,87 @@
/*
* 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.TIndexOutOfBoundsException;
/**
*
* @author Alexey Andreev
*/
public abstract class TAbstractSequentialList<E> extends TAbstractList<E> {
@Override
public E get(int index) {
if (index < 0) {
throw new TIndexOutOfBoundsException();
}
TIterator<E> iter = listIterator(index);
return iter.next();
}
@Override
public E set(int index, E element) {
if (index < 0) {
throw new TIndexOutOfBoundsException();
}
TListIterator<E> iter = listIterator(index);
E old = iter.next();
iter.set(element);
return old;
}
@Override
public void add(int index, E element) {
if (index < 0) {
throw new TIndexOutOfBoundsException();
}
TListIterator<E> iter = listIterator(index);
iter.add(element);
}
@Override
public E remove(int index) {
if (index < 0) {
throw new TIndexOutOfBoundsException();
}
TListIterator<E> iter = listIterator(index);
E elem = iter.next();
iter.remove();
return elem;
}
@Override
public boolean addAll(int index, TCollection<? extends E> c) {
if (index < 0) {
throw new TIndexOutOfBoundsException();
}
TListIterator<E> iter = listIterator(index);
boolean added = false;
for (TIterator<? extends E> srcIter = c.iterator(); srcIter.hasNext();) {
iter.add(srcIter.next());
iter.next();
added = true;
}
return added;
}
@Override
public TIterator<E> iterator() {
return listIterator();
}
@Override
public abstract TListIterator<E> listIterator(int index);
}

View File

@ -0,0 +1,200 @@
/*
* 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.ConcurrentModificationException;
import java.util.NoSuchElementException;
/**
*
* @author Alexey Andreev
*/
public class TLinkedList<E> extends TAbstractSequentialList<E> {
static class Entry<E> {
E item;
Entry<E> next;
Entry<E> previous;
}
private Entry<E> firstEntry;
private Entry<E> lastEntry;
private int size;
@Override
public int size() {
return size;
}
@Override
public void clear() {
firstEntry = null;
lastEntry = null;
size = 0;
modCount++;
}
@Override
public TListIterator<E> listIterator() {
return new SequentialListIterator(firstEntry, null);
}
@Override
public TListIterator<E> listIterator(int index) {
if (index <= size / 2) {
TListIterator<E> iter = listIterator();
while (index-- > 0) {
if (!iter.hasNext()) {
throw new IndexOutOfBoundsException();
}
iter.next();
}
return iter;
} else {
TListIterator<E> iter = new SequentialListIterator(null, lastEntry);
while (index++ < size) {
if (!iter.hasPrevious()) {
throw new IndexOutOfBoundsException();
}
iter.previous();
}
return iter;
}
}
private class SequentialListIterator implements TListIterator<E> {
private Entry<E> nextEntry = firstEntry;
private Entry<E> prevEntry = null;
private Entry<E> currentEntry;
private int index;
private int version = modCount;
public SequentialListIterator(Entry<E> nextEntry, Entry<E> prevEntry) {
this.nextEntry = nextEntry;
this.prevEntry = prevEntry;
}
@Override
public boolean hasNext() {
return nextEntry != null;
}
@Override
public E next() {
checkConcurrentModification();
if (nextEntry == null) {
throw new NoSuchElementException();
}
E result = nextEntry.item;
currentEntry = nextEntry;
prevEntry = nextEntry;
nextEntry = nextEntry.next;
++index;
return result;
}
@Override
public void remove() {
if (currentEntry == null) {
throw new IllegalStateException();
}
currentEntry.next.previous = currentEntry.next;
currentEntry.previous.next = currentEntry.next;
if (currentEntry == firstEntry) {
firstEntry = firstEntry.next;
} else if (currentEntry == lastEntry) {
lastEntry = lastEntry.previous;
}
if (currentEntry == prevEntry) {
prevEntry = nextEntry.previous;
} else if (currentEntry == nextEntry) {
nextEntry = prevEntry.next;
}
--index;
--size;
++modCount;
version = modCount;
currentEntry = null;
}
@Override
public boolean hasPrevious() {
return prevEntry != null;
}
@Override
public E previous() {
checkConcurrentModification();
if (prevEntry == null) {
throw new NoSuchElementException();
}
currentEntry = prevEntry;
E result = prevEntry.item;
nextEntry = prevEntry;
prevEntry = prevEntry.previous;
--index;
return result;
}
@Override
public int nextIndex() {
return index;
}
@Override
public int previousIndex() {
return index - 1;
}
@Override
public void set(E e) {
if (currentEntry == null) {
throw new IllegalStateException();
}
checkConcurrentModification();
currentEntry.item = e;
currentEntry = null;
}
@Override
public void add(E e) {
checkConcurrentModification();
Entry<E> newEntry = new Entry<>();
newEntry.item = e;
newEntry.previous = prevEntry;
newEntry.next = nextEntry;
if (prevEntry != null) {
prevEntry.next = newEntry;
} else {
firstEntry = newEntry;
}
if (nextEntry != null) {
nextEntry.previous = newEntry;
} else {
lastEntry = newEntry;
}
prevEntry = newEntry;
++size;
++modCount;
version = modCount;
currentEntry = null;
}
private void checkConcurrentModification() {
if (version < modCount) {
throw new ConcurrentModificationException();
}
}
}
}

View File

@ -0,0 +1,132 @@
/*
* 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.*;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
public class LinkedListTest {
@Test
public void emptyListCreated() {
LinkedList<String> list = new LinkedList<>();
assertTrue(list.isEmpty());
assertEquals(0, list.size());
assertFalse(list.iterator().hasNext());
}
@Test
public void elementAdded() {
LinkedList<String> list = new LinkedList<>();
list.add("foo");
Iterator<String> iter = list.iterator();
assertEquals("foo", iter.next());
assertEquals(1, list.size());
assertFalse(iter.hasNext());
}
@Test
public void elementRetrievedByIndex() {
LinkedList<String> list = new LinkedList<>();
list.add("foo");
list.add("bar");
list.add("baz");
assertEquals("foo", list.get(0));
assertEquals("bar", list.get(1));
assertEquals("baz", list.get(2));
}
@Test
public void listIteratorPositioned() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(1);
assertEquals(1, iter.nextIndex());
assertEquals(0, iter.previousIndex());
assertTrue(iter.hasNext());
assertTrue(iter.hasPrevious());
assertEquals("2", iter.next());
}
@Test
public void listIteratorMoved() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(1);
assertEquals("2", iter.next());
assertEquals("3", iter.next());
assertEquals("a", iter.next());
assertEquals("a", iter.previous());
assertEquals("3", iter.previous());
assertEquals(2, iter.nextIndex());
assertEquals(1, iter.previousIndex());
}
@Test(expected = NoSuchElementException.class)
public void listInteratorCantMoveBeyondLowerBound() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(1);
assertEquals("1", iter.previous());
iter.previous();
}
@Test(expected = NoSuchElementException.class)
public void listInteratorCantMoveBeyondUpperBound() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(4);
assertEquals("b", iter.next());
iter.next();
}
@Test
public void listIteratorRemovesItem() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(2);
assertEquals("3", iter.next());
iter.remove();
assertEquals(2, iter.nextIndex());
assertEquals("a", iter.next());
assertArrayEquals(new String[] { "1", "2", "a", "b" }, list.toArray(new String[0]));
}
@Test
public void listIteratorAddsItem() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(2);
iter.add("*");
assertEquals("3", iter.next());
assertArrayEquals(new String[] { "1", "2", "*", "3", "a", "b" }, list.toArray(new String[0]));
}
@Test
public void listIteratorReplacesItem() {
LinkedList<String> list = new LinkedList<>();
list.addAll(Arrays.asList("1", "2", "3", "a", "b"));
ListIterator<String> iter = list.listIterator(2);
iter.next();
iter.set("*");
assertEquals("a", iter.next());
assertArrayEquals(new String[] { "1", "2", "*", "a", "b" }, list.toArray(new String[0]));
}
}