Implements ArrayList and AbstractList

This commit is contained in:
konsoletyper 2014-02-21 00:29:57 +04:00
parent dfafbceede
commit 18f6791b8e
7 changed files with 670 additions and 13 deletions

View File

@ -15,6 +15,7 @@
*/
package org.teavm.classlib.java.util;
import java.lang.reflect.Array;
import org.teavm.classlib.java.lang.TObject;
import org.teavm.classlib.java.lang.TUnsupportedOperationException;
@ -53,8 +54,21 @@ public abstract class TAbstractCollection<E> extends TObject implements TCollect
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
return null;
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 (TIterator<E> iter = iterator(); iter.hasNext();) {
a[i++] = (T)iter.next();
}
return a;
}
@Override

View File

@ -15,10 +15,427 @@
*/
package org.teavm.classlib.java.util;
import org.teavm.classlib.java.lang.TIllegalArgumentException;
import org.teavm.classlib.java.lang.TIllegalStateException;
import org.teavm.classlib.java.lang.TIndexOutOfBoundsException;
import org.teavm.classlib.java.lang.TUnsupportedOperationException;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TAbstractList {
public abstract class TAbstractList<E> extends TAbstractCollection<E> implements TList<E> {
protected transient int modCount;
protected TAbstractList() {
}
@Override
public boolean add(E e) {
add(size(), e);
return true;
}
@Override
public TIterator<E> iterator() {
return new TIterator<E>() {
private int index;
private int modCount = TAbstractList.this.modCount;
private int size = size();
@Override public boolean hasNext() {
return index < size;
}
@Override public E next() {
checkConcurrentModification();
return get(index++);
}
@Override public void remove() {
TAbstractList.this.remove(index - 1);
}
private void checkConcurrentModification() {
if (modCount < TAbstractList.this.modCount) {
throw new TConcurrentModificationException();
}
}
};
}
@Override
public boolean addAll(int index, TCollection<? extends E> c) {
if (index < 0 || index > size()) {
throw new TIllegalArgumentException();
}
if (c.isEmpty()) {
return false;
}
for (TIterator<? extends E> iter = c.iterator(); iter.hasNext();) {
add(index++, iter.next());
}
return true;
}
@Override
public E set(int index, E element) {
throw new TUnsupportedOperationException();
}
@Override
public void add(int index, E element) {
throw new TUnsupportedOperationException();
}
@Override
public E remove(int index) {
throw new TUnsupportedOperationException();
}
@Override
public int indexOf(Object o) {
int sz = size();
for (int i = 0; i < sz; ++i) {
Object e = get(i);
if (o == null ? e == null : o.equals(e)) {
return i;
}
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
int sz = size();
for (int i = sz - 1; i >= 0; --i) {
Object e = get(i);
if (o == null ? e == null : o.equals(e)) {
return i;
}
}
return -1;
}
@Override
public void clear() {
removeRange(0, size());
}
@Override
public TListIterator<E> listIterator() {
return listIterator(0);
}
@Override
public TListIterator<E> listIterator(int index) {
return new TListIteratorImpl(index, modCount, size());
}
@Override
public TList<E> subList(int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new TIllegalArgumentException();
}
if (fromIndex < 0 || toIndex >= size()) {
throw new TIndexOutOfBoundsException();
}
if (this instanceof TRandomAccess) {
return new SubAbstractListRandomAccess<>(this, fromIndex, toIndex);
}
return new SubAbstractList<>(this, fromIndex, toIndex);
}
protected void removeRange(int start, int end) {
for (int i = start; i < end; i++) {
remove(i);
}
}
private class TListIteratorImpl implements TListIterator<E> {
private int i;
private int j;
private int lastModCount;
private int sz;
public TListIteratorImpl(int i, int lastModCount, int sz) {
this.i = i;
this.j = i;
this.lastModCount = lastModCount;
this.sz = sz;
}
@Override public boolean hasNext() {
return i < sz;
}
@Override public E next() {
checkConcurrentModification();
if (i == sz) {
throw new TNoSuchElementException();
}
j = i;
return get(i++);
}
@Override public void remove() {
if (j == -1) {
throw new TIllegalStateException();
}
checkConcurrentModification();
TAbstractList.this.remove(j);
--sz;
lastModCount = modCount;
}
@Override public boolean hasPrevious() {
return i > 0;
}
@Override public E previous() {
checkConcurrentModification();
j = i - 1;
if (j < 0) {
throw new TNoSuchElementException();
}
return get((i--) - 1);
}
@Override public int nextIndex() {
return i;
}
@Override public int previousIndex() {
return i - 1;
}
@Override public void set(E e) {
if (j == -1) {
throw new TIllegalStateException();
}
checkConcurrentModification();
TAbstractList.this.set(j, e);
}
@Override public void add(E e) {
if (j == -1) {
throw new TIllegalStateException();
}
TAbstractList.this.add(i++, e);
lastModCount = modCount;
j = -1;
}
private void checkConcurrentModification() {
if (lastModCount < modCount) {
throw new TConcurrentModificationException();
}
}
}
private static final class SubAbstractListRandomAccess<E> extends SubAbstractList<E> implements TRandomAccess {
SubAbstractListRandomAccess(TAbstractList<E> list, int start, int end) {
super(list, start, end);
}
}
private static class SubAbstractList<E> extends TAbstractList<E> {
private final TAbstractList<E> fullList;
private int offset;
private int size;
private static final class SubAbstractListIterator<E> implements TListIterator<E> {
private final SubAbstractList<E> subList;
private final TListIterator<E> iterator;
private int start;
private int end;
SubAbstractListIterator(TListIterator<E> it, SubAbstractList<E> list, int offset, int length) {
super();
iterator = it;
subList = list;
start = offset;
end = start + length;
}
@Override
public void add(E object) {
iterator.add(object);
subList.sizeChanged(true);
end++;
}
@Override
public boolean hasNext() {
return iterator.nextIndex() < end;
}
@Override
public boolean hasPrevious() {
return iterator.previousIndex() >= start;
}
@Override
public E next() {
if (iterator.nextIndex() < end) {
return iterator.next();
}
throw new TNoSuchElementException();
}
@Override
public int nextIndex() {
return iterator.nextIndex() - start;
}
@Override
public E previous() {
if (iterator.previousIndex() >= start) {
return iterator.previous();
}
throw new TNoSuchElementException();
}
@Override
public int previousIndex() {
int previous = iterator.previousIndex();
if (previous >= start) {
return previous - start;
}
return -1;
}
@Override
public void remove() {
iterator.remove();
subList.sizeChanged(false);
end--;
}
@Override
public void set(E object) {
iterator.set(object);
}
}
SubAbstractList(TAbstractList<E> list, int start, int end) {
super();
fullList = list;
modCount = fullList.modCount;
offset = start;
size = end - start;
}
@Override
public void add(int location, E object) {
if (modCount == fullList.modCount) {
if (0 <= location && location <= size) {
fullList.add(location + offset, object);
size++;
modCount = fullList.modCount;
} else {
throw new TIndexOutOfBoundsException();
}
} else {
throw new TConcurrentModificationException();
}
}
@Override
public boolean addAll(int location, TCollection<? extends E> collection) {
if (modCount == fullList.modCount) {
if (0 <= location && location <= size) {
boolean result = fullList.addAll(location + offset, collection);
if (result) {
size += collection.size();
modCount = fullList.modCount;
}
return result;
}
throw new TIndexOutOfBoundsException();
}
throw new TConcurrentModificationException();
}
@Override
public boolean addAll(TCollection<? extends E> collection) {
if (modCount == fullList.modCount) {
boolean result = fullList.addAll(offset + size, collection);
if (result) {
size += collection.size();
modCount = fullList.modCount;
}
return result;
}
throw new TConcurrentModificationException();
}
@Override
public E get(int location) {
if (modCount == fullList.modCount) {
if (0 <= location && location < size) {
return fullList.get(location + offset);
}
throw new IndexOutOfBoundsException();
}
throw new TConcurrentModificationException();
}
@Override
public TIterator<E> iterator() {
return listIterator(0);
}
@Override
public TListIterator<E> listIterator(int location) {
if (modCount == fullList.modCount) {
if (0 <= location && location <= size) {
return new SubAbstractListIterator<>(fullList.listIterator(location + offset), this, offset, size);
}
throw new TIndexOutOfBoundsException();
}
throw new TConcurrentModificationException();
}
@Override
public E remove(int location) {
if (modCount == fullList.modCount) {
if (0 <= location && location < size) {
E result = fullList.remove(location + offset);
size--;
modCount = fullList.modCount;
return result;
}
throw new IndexOutOfBoundsException();
}
throw new TConcurrentModificationException();
}
@Override
protected void removeRange(int start, int end) {
if (start != end) {
if (modCount == fullList.modCount) {
fullList.removeRange(start + offset, end + offset);
size -= end - start;
modCount = fullList.modCount;
} else {
throw new TConcurrentModificationException();
}
}
}
@Override
public E set(int location, E object) {
if (modCount == fullList.modCount) {
if (0 <= location && location < size) {
return fullList.set(location + offset, object);
}
throw new TIndexOutOfBoundsException();
}
throw new TConcurrentModificationException();
}
@Override
public int size() {
if (modCount == fullList.modCount) {
return size;
}
throw new TConcurrentModificationException();
}
void sizeChanged(boolean increment) {
if (increment) {
size++;
} else {
size--;
}
modCount = fullList.modCount;
}
}
}

View File

@ -0,0 +1,172 @@
/*
* 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.io.TSerializable;
import org.teavm.classlib.java.lang.*;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TArrayList<E> extends TAbstractList<E> implements TCloneable, TSerializable {
private E[] array;
private int size;
public TArrayList() {
this(10);
}
@SuppressWarnings("unchecked")
public TArrayList(int initialCapacity) {
array = (E[])new Object[initialCapacity];
}
public TArrayList(TCollection<? extends E> c) {
this(c.size());
TIterator<? extends E> iter = c.iterator();
for (int i = 0; i < array.length; ++i) {
array[i] = iter.next();
}
}
public void trimToSize() {
array = Arrays.copyOf(array, size);
}
public void ensureCapacity(int minCapacity) {
if (array.length < minCapacity) {
array = TArrays.copyOf(array, array.length + TMath.min(5, array.length / 2));
}
}
@Override
public E get(int index) {
checkIndex(index);
return array[index];
}
@Override
public int size() {
return size;
}
@Override
public TObject clone() {
return new TArrayList<>(this);
}
@Override
public E set(int index, E element) {
checkIndex(index);
E old = array[index];
array[index] = element;
return old;
}
@Override
public void add(int index, E element) {
checkIndexForAdd(index);
ensureCapacity(size + 1);
for (int i = size; i > index; --i) {
array[i] = array[i - 1];
}
array[index] = element;
++modCount;
}
@Override
public E remove(int index) {
checkIndex(index);
E old = array[index];
--size;
for (int i = index; i < size; ++i) {
array[i] = array[i + 1];
}
array[size] = null;
++modCount;
return old;
}
@Override
public boolean remove(Object o) {
int index = indexOf(o);
if (index >= 0) {
remove(index);
return true;
} else {
return false;
}
}
@Override
public void clear() {
Arrays.fill(array, 0, size, null);
size = 0;
}
@Override
public boolean addAll(int index, TCollection<? extends E> c) {
checkIndexForAdd(index);
if (c.isEmpty()) {
return false;
}
ensureCapacity(size + c.size());
int gap = c.size();
size += gap;
for (int i = gap - 1; i > index; --i) {
array[i] = array[i - gap];
}
TIterator<? extends E> iter = c.iterator();
for (int i = 0; i < gap; ++i) {
array[index++] = iter.next();
}
++modCount;
return true;
}
@Override
protected void removeRange(int start, int end) {
if (start > end) {
throw new TIllegalArgumentException();
}
if (start < 0 || end > size) {
throw new TIndexOutOfBoundsException();
}
if (start == end) {
return;
}
for (int i = end; i < size; ++i) {
array[start++] = array[end++];
}
Arrays.fill(array, start, end, null);
size -= end - start;
++modCount;
}
private void checkIndex(int index) {
if (index < 0 || index >= size) {
throw new TIndexOutOfBoundsException();
}
}
private void checkIndexForAdd(int index) {
if (index < 0 || index > size) {
throw new TIndexOutOfBoundsException();
}
}
}

View File

@ -15,10 +15,7 @@
*/
package org.teavm.classlib.java.util;
import org.teavm.classlib.java.lang.TMath;
import org.teavm.classlib.java.lang.TObject;
import org.teavm.classlib.java.lang.TString;
import org.teavm.classlib.java.lang.TStringBuilder;
import org.teavm.classlib.java.lang.*;
/**
*
@ -43,6 +40,16 @@ public class TArrays extends TObject {
return result;
}
public static <T> T[] copyOf(T[] original, int newLength) {
@SuppressWarnings("unchecked")
T[] result = (T[])new Object[newLength];
int sz = TMath.min(newLength, original.length);
for (int i = 0; i < sz; ++i) {
result[i] = original[i];
}
return result;
}
public static TString toString(TObject[] a) {
TStringBuilder sb = new TStringBuilder();
sb.append(TString.wrap("["));
@ -159,4 +166,20 @@ public class TArrays extends TObject {
sb.append(TString.wrap("]"));
return TString.wrap(sb.toString());
}
public static void fill(TObject[] a, int fromIndex, int toIndex, TObject val) {
if (fromIndex > toIndex) {
throw new TIllegalArgumentException();
}
if (fromIndex < 0 || toIndex > a.length) {
throw new TIndexOutOfBoundsException();
}
while (fromIndex < toIndex) {
a[fromIndex++] = val;
}
}
public static void fill(TObject[] a, TObject val) {
fill(a, 0, a.length, val);
}
}

View File

@ -15,13 +15,11 @@
*/
package org.teavm.classlib.java.util;
import org.teavm.classlib.java.lang.TObject;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface TList<E extends TObject> extends TCollection<E> {
public interface TList<E> extends TCollection<E> {
boolean addAll(int index, TCollection<? extends E> c);
E get(int index);

View File

@ -15,13 +15,11 @@
*/
package org.teavm.classlib.java.util;
import org.teavm.classlib.java.lang.TObject;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public interface TListIterator<E extends TObject> extends TIterator<E> {
public interface TListIterator<E> extends TIterator<E> {
boolean hasPrevious();
E previous();

View File

@ -0,0 +1,35 @@
/*
* 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.TRuntimeException;
import org.teavm.classlib.java.lang.TString;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TNoSuchElementException extends TRuntimeException {
private static final long serialVersionUID = -4890604137042866919L;
public TNoSuchElementException() {
super();
}
public TNoSuchElementException(TString message) {
super(message);
}
}