diff --git a/classpath/java/util/AbstractList.java b/classpath/java/util/AbstractList.java new file mode 100644 index 0000000000..fa1abbd65a --- /dev/null +++ b/classpath/java/util/AbstractList.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2009, 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 AbstractList extends AbstractCollection + implements List +{ } diff --git a/classpath/java/util/AbstractSequentialList.java b/classpath/java/util/AbstractSequentialList.java new file mode 100644 index 0000000000..8af8938ba0 --- /dev/null +++ b/classpath/java/util/AbstractSequentialList.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2009, 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 AbstractSequentialList extends AbstractList + implements List +{ } diff --git a/classpath/java/util/ArrayList.java b/classpath/java/util/ArrayList.java index e130c55c67..22726cb4fa 100644 --- a/classpath/java/util/ArrayList.java +++ b/classpath/java/util/ArrayList.java @@ -10,7 +10,7 @@ package java.util; -public class ArrayList implements List { +public class ArrayList extends AbstractList { private static final int MinimumCapacity = 16; private Object[] array; @@ -169,7 +169,7 @@ public class ArrayList implements List { } public Iterator iterator() { - return new Collections.ArrayListIterator(this); + return listIterator(); } public ListIterator listIterator(int index) { diff --git a/classpath/java/util/Arrays.java b/classpath/java/util/Arrays.java index db41e6bddc..219612f040 100644 --- a/classpath/java/util/Arrays.java +++ b/classpath/java/util/Arrays.java @@ -102,7 +102,15 @@ public class Arrays { } public Iterator iterator() { - return new Collections.ArrayListIterator(this); + return listIterator(); + } + + public ListIterator listIterator(int index) { + return new Collections.ArrayListIterator(this, index); + } + + public ListIterator listIterator() { + return listIterator(0); } }; } diff --git a/classpath/java/util/Collections.java b/classpath/java/util/Collections.java index 3b6ab87d87..70b6e03a48 100644 --- a/classpath/java/util/Collections.java +++ b/classpath/java/util/Collections.java @@ -198,7 +198,6 @@ public class Collections { return new SynchronizedMap (map); } - static class SynchronizedSet extends SynchronizedCollection implements Set @@ -232,7 +231,7 @@ public class Collections { static class ArrayListIterator implements ListIterator { private final List list; - private boolean canRemove = false; + private int toRemove = -1; private int index; public ArrayListIterator(List list) { @@ -250,7 +249,7 @@ public class Collections { public T previous() { if (hasPrevious()) { - canRemove = true; + toRemove = index; return list.get(index--); } else { throw new NoSuchElementException(); @@ -259,8 +258,8 @@ public class Collections { public T next() { if (hasNext()) { - canRemove = true; - return list.get(++index); + toRemove = ++index; + return list.get(index); } else { throw new NoSuchElementException(); } @@ -271,9 +270,10 @@ public class Collections { } public void remove() { - if (canRemove) { - canRemove = false; - list.remove(index--); + if (toRemove != -1) { + list.remove(toRemove); + index = toRemove - 1; + toRemove = -1; } else { throw new IllegalStateException(); } diff --git a/classpath/java/util/LinkedList.java b/classpath/java/util/LinkedList.java index 0fab004117..49164d87fe 100644 --- a/classpath/java/util/LinkedList.java +++ b/classpath/java/util/LinkedList.java @@ -10,7 +10,7 @@ package java.util; -public class LinkedList implements List { +public class LinkedList extends AbstractSequentialList { private Cell front; private Cell rear; private int size; @@ -198,7 +198,19 @@ public class LinkedList implements List { } public Iterator iterator() { - return new MyIterator(front); + return listIterator(); + } + + public ListIterator listIterator(int index) { + MyIterator it = new MyIterator(); + for (int i = 0; i < index; ++i) { + it.next(); + } + return it; + } + + public ListIterator listIterator() { + return listIterator(0); } public String toString() { @@ -217,18 +229,29 @@ public class LinkedList implements List { } } - private class MyIterator implements Iterator { + private class MyIterator implements ListIterator { + private Cell toRemove; private Cell current; - private Cell next; - public MyIterator(Cell start) { - next = start; + public T previous() { + if (hasPrevious()) { + T v = current.value; + toRemove = current; + current = current.prev; + return v; + } else { + throw new NoSuchElementException(); + } } public T next() { if (hasNext()) { - current = next; - next = next.next; + if (current == null) { + current = front; + } else { + current = current.next; + } + toRemove = current; return current.value; } else { throw new NoSuchElementException(); @@ -236,13 +259,22 @@ public class LinkedList implements List { } public boolean hasNext() { - return next != null; + if (current == null) { + return front != null; + } else { + return current.next != null; + } + } + + public boolean hasPrevious() { + return current != null; } public void remove() { - if (current != null) { - LinkedList.this.remove(current); - current = null; + if (toRemove != null) { + current = toRemove.prev; + LinkedList.this.remove(toRemove); + toRemove = null; } else { throw new IllegalStateException(); } diff --git a/classpath/java/util/List.java b/classpath/java/util/List.java index 0577e4b3e7..b9e5735edb 100644 --- a/classpath/java/util/List.java +++ b/classpath/java/util/List.java @@ -22,4 +22,8 @@ public interface List extends Collection { public void add(int index, T element); public boolean isEmpty(); + + public ListIterator listIterator(int index); + + public ListIterator listIterator(); } diff --git a/classpath/java/util/Vector.java b/classpath/java/util/Vector.java index f06f58ecbc..99b3dd7138 100644 --- a/classpath/java/util/Vector.java +++ b/classpath/java/util/Vector.java @@ -10,7 +10,7 @@ package java.util; -public class Vector implements List { +public class Vector extends AbstractList { private final ArrayList list; public Vector(int capacity) { @@ -112,7 +112,15 @@ public class Vector implements List { } public Iterator iterator() { - return new Collections.ArrayListIterator(this); + return listIterator(); + } + + public ListIterator listIterator(int index) { + return new Collections.ArrayListIterator(this, index); + } + + public ListIterator listIterator() { + return listIterator(0); } public Enumeration elements() { diff --git a/test/List.java b/test/List.java index ee3ffc0204..797aefbb7f 100644 --- a/test/List.java +++ b/test/List.java @@ -1,4 +1,6 @@ import java.util.ArrayList; +import java.util.LinkedList; +import java.util.ListIterator; public class List { private static void expect(boolean v) { @@ -21,6 +23,114 @@ public class List { expect(s1.equals(s2)); } + private static void testIterators(java.util.List l) { + l.add(1); + l.add(2); + l.add(3); + + ListIterator it = l.listIterator(); + expect(it.next().equals(Integer.valueOf(1))); + expect(it.next().equals(Integer.valueOf(2))); + expect(it.next().equals(Integer.valueOf(3))); + expect(! it.hasNext()); + + it = l.listIterator(1); + expect(it.next().equals(Integer.valueOf(2))); + expect(it.next().equals(Integer.valueOf(3))); + expect(! it.hasNext()); + + it = l.listIterator(2); + expect(it.next().equals(Integer.valueOf(3))); + expect(! it.hasNext()); + + it = l.listIterator(3); + expect(it.previous().equals(Integer.valueOf(3))); + expect(it.previous().equals(Integer.valueOf(2))); + expect(it.previous().equals(Integer.valueOf(1))); + expect(! it.hasPrevious()); + + it = l.listIterator(2); + expect(it.previous().equals(Integer.valueOf(2))); + expect(it.previous().equals(Integer.valueOf(1))); + expect(! it.hasPrevious()); + + it = l.listIterator(1); + expect(it.previous().equals(Integer.valueOf(1))); + expect(! it.hasPrevious()); + } + + private static void testIterators2(java.util.List l) { + l.add(1); + l.add(2); + l.add(3); + + ListIterator it = l.listIterator(); + expect(it.next().equals(Integer.valueOf(1))); + it.remove(); + expect(it.next().equals(Integer.valueOf(2))); + it.remove(); + expect(it.next().equals(Integer.valueOf(3))); + it.remove(); + expect(! it.hasNext()); + expect(l.isEmpty()); + + l.add(1); + l.add(2); + l.add(3); + + it = l.listIterator(1); + expect(it.next().equals(Integer.valueOf(2))); + it.remove(); + expect(it.next().equals(Integer.valueOf(3))); + it.remove(); + expect(! it.hasNext()); + expect(l.size() == 1); + + l.add(2); + l.add(3); + + it = l.listIterator(2); + expect(it.next().equals(Integer.valueOf(3))); + it.remove(); + expect(! it.hasNext()); + expect(l.size() == 2); + + l.add(3); + + it = l.listIterator(3); + expect(it.previous().equals(Integer.valueOf(3))); + it.remove(); + expect(it.previous().equals(Integer.valueOf(2))); + it.remove(); + expect(it.previous().equals(Integer.valueOf(1))); + it.remove(); + expect(! it.hasPrevious()); + expect(l.isEmpty()); + + l.add(1); + l.add(2); + l.add(3); + + it = l.listIterator(2); + expect(it.previous().equals(Integer.valueOf(2))); + it.remove(); + expect(it.previous().equals(Integer.valueOf(1))); + it.remove(); + expect(! it.hasPrevious()); + expect(l.size() == 1); + + l.clear(); + l.add(1); + l.add(2); + l.add(3); + + it = l.listIterator(1); + expect(it.previous().equals(Integer.valueOf(1))); + it.remove(); + expect(! it.hasPrevious()); + expect(l.size() == 2); + } + public static void main(String args[]) { ArrayList l = new ArrayList(); l.add(1); l.add(2); l.add(3); l.add(4); l.add(5); @@ -39,5 +149,11 @@ public class List { for (int i=0; i < z.length; i++) { System.out.println(z[i]); } + + testIterators(new ArrayList()); + testIterators(new LinkedList()); + + testIterators2(new ArrayList()); + testIterators2(new LinkedList()); } }