Adds Vector and Hashtable

This commit is contained in:
konsoletyper 2014-05-06 15:33:56 +04:00
parent 9b18d51760
commit e9af85534f
10 changed files with 3615 additions and 6 deletions

View File

@ -42,15 +42,23 @@ public abstract class TAbstractList<E> extends TAbstractCollection<E> implements
private int index;
private int modCount = TAbstractList.this.modCount;
private int size = size();
private int removeIndex = -1;
@Override public boolean hasNext() {
return index < size;
}
@Override public E next() {
checkConcurrentModification();
removeIndex = index;
return get(index++);
}
@Override public void remove() {
if (removeIndex < 0) {
throw new TIllegalStateException();
}
TAbstractList.this.remove(index - 1);
modCount = TAbstractList.this.modCount;
--index;
removeIndex = -1;
}
private void checkConcurrentModification() {
if (modCount < TAbstractList.this.modCount) {

View File

@ -0,0 +1,55 @@
/*
* 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.TObject;
public abstract class TDictionary<K, V> extends TObject {
public TDictionary() {
super();
}
public abstract TEnumeration<V> elements();
public abstract V get(Object key);
public abstract boolean isEmpty();
public abstract TEnumeration<K> keys();
public abstract V put(K key, V value);
public abstract V remove(Object key);
public abstract int size();
}

View File

@ -0,0 +1,773 @@
/*
* 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.TCloneNotSupportedException;
import org.teavm.classlib.java.lang.TCloneable;
import org.teavm.classlib.java.lang.TNullPointerException;
import org.teavm.classlib.java.lang.TUnsupportedOperationException;
public class THashtable<K, V> extends TDictionary<K, V> implements TMap<K, V>,
TCloneable, TSerializable {
transient int elementCount;
transient Entry<K, V>[] elementData;
private float loadFactor;
private int threshold;
transient int firstSlot;
transient int lastSlot = -1;
transient int modCount;
private static final TEnumeration<?> EMPTY_ENUMERATION = new TEnumeration<Object>() {
@Override
public boolean hasMoreElements() {
return false;
}
@Override
public Object nextElement() {
throw new TNoSuchElementException();
}
};
private static final TIterator<?> EMPTY_ITERATOR = new TIterator<Object>() {
@Override
public boolean hasNext() {
return false;
}
@Override
public Object next() {
throw new TNoSuchElementException();
}
@Override
public void remove() {
throw new IllegalStateException();
}
};
private static <K, V> Entry<K, V> newEntry(K key, V value, @SuppressWarnings("unused") int hash) {
return new Entry<>(key, value);
}
private static class Entry<K, V> extends TMapEntry<K, V> {
Entry<K, V> next;
final int hashcode;
Entry(K theKey, V theValue) {
super(theKey, theValue);
hashcode = theKey.hashCode();
}
@Override
@SuppressWarnings("unchecked")
public Object clone() {
Entry<K, V> entry = (Entry<K, V>) super.clone();
if (next != null) {
entry.next = (Entry<K, V>) next.clone();
}
return entry;
}
@Override
public V setValue(V object) {
if (object == null) {
throw new NullPointerException();
}
V result = value;
value = object;
return result;
}
public int getKeyHash() {
return key.hashCode();
}
public boolean equalsKey(Object aKey, @SuppressWarnings("unused") int hash) {
return hashcode == aKey.hashCode() && key.equals(aKey);
}
@Override
public String toString() {
return key + "=" + value;
}
}
private class HashIterator<E> implements TIterator<E> {
int position, expectedModCount;
final TMapEntry.Type<E, K, V> type;
Entry<K, V> lastEntry;
int lastPosition;
boolean canRemove = false;
HashIterator(TMapEntry.Type<E, K, V> value) {
type = value;
position = lastSlot;
expectedModCount = modCount;
}
@Override
public boolean hasNext() {
if (lastEntry != null && lastEntry.next != null) {
return true;
}
while (position >= firstSlot) {
if (elementData[position] == null) {
position--;
} else {
return true;
}
}
return false;
}
@Override
public E next() {
if (expectedModCount == modCount) {
if (lastEntry != null) {
lastEntry = lastEntry.next;
}
if (lastEntry == null) {
while (position >= firstSlot
&& (lastEntry = elementData[position]) == null) {
position--;
}
if (lastEntry != null) {
lastPosition = position;
// decrement the position so we don't find the same slot
// next time
position--;
}
}
if (lastEntry != null) {
canRemove = true;
return type.get(lastEntry);
}
throw new TNoSuchElementException();
}
throw new TConcurrentModificationException();
}
@Override
public void remove() {
if (expectedModCount == modCount) {
if (canRemove) {
canRemove = false;
synchronized (THashtable.this) {
boolean removed = false;
Entry<K, V> entry = elementData[lastPosition];
if (entry == lastEntry) {
elementData[lastPosition] = entry.next;
removed = true;
} else {
while (entry != null && entry.next != lastEntry) {
entry = entry.next;
}
if (entry != null) {
entry.next = lastEntry.next;
removed = true;
}
}
if (removed) {
modCount++;
elementCount--;
expectedModCount++;
return;
}
// the entry must have been (re)moved outside of the
// iterator
// but this condition wasn't caught by the modCount
// check
// throw ConcurrentModificationException() outside of
// synchronized block
}
} else {
throw new IllegalStateException();
}
}
throw new TConcurrentModificationException();
}
}
public THashtable() {
this(11);
}
public THashtable(int capacity) {
if (capacity >= 0) {
elementCount = 0;
elementData = newElementArray(capacity == 0 ? 1 : capacity);
firstSlot = elementData.length;
loadFactor = 0.75f;
computeMaxSize();
} else {
throw new IllegalArgumentException();
}
}
public THashtable(int capacity, float loadFactor) {
if (capacity >= 0 && loadFactor > 0) {
elementCount = 0;
firstSlot = capacity;
elementData = newElementArray(capacity == 0 ? 1 : capacity);
this.loadFactor = loadFactor;
computeMaxSize();
} else {
throw new IllegalArgumentException();
}
}
public THashtable(TMap<? extends K, ? extends V> map) {
this(map.size() < 6 ? 11 : (map.size() * 4 / 3) + 11);
putAll(map);
}
@SuppressWarnings("unchecked")
private Entry<K, V>[] newElementArray(int size) {
return new Entry[size];
}
@Override
public synchronized void clear() {
elementCount = 0;
Arrays.fill(elementData, null);
modCount++;
}
@Override
@SuppressWarnings("unchecked")
public synchronized Object clone() {
try {
THashtable<K, V> hashtable = (THashtable<K, V>) super.clone();
hashtable.elementData = new Entry[elementData.length];
Entry<K, V> entry;
for (int i = elementData.length; --i >= 0;) {
if ((entry = elementData[i]) != null) {
hashtable.elementData[i] = (Entry<K, V>) entry.clone();
}
}
return hashtable;
} catch (TCloneNotSupportedException e) {
return null;
}
}
private void computeMaxSize() {
threshold = (int) (elementData.length * loadFactor);
}
public synchronized boolean contains(Object value) {
if (value == null) {
throw new TNullPointerException();
}
for (int i = elementData.length; --i >= 0;) {
Entry<K, V> entry = elementData[i];
while (entry != null) {
if (entry.value.equals(value)) {
return true;
}
entry = entry.next;
}
}
return false;
}
@Override
public synchronized boolean containsKey(Object key) {
return getEntry(key) != null;
}
@Override
public boolean containsValue(Object value) {
return contains(value);
}
@Override
@SuppressWarnings("unchecked")
public synchronized TEnumeration<V> elements() {
if (elementCount == 0) {
return (TEnumeration<V>) EMPTY_ENUMERATION;
}
return new HashEnumIterator<>(new TMapEntry.Type<V, K, V>() {
@Override
public V get(TMapEntry<K, V> entry) {
return entry.value;
}
}, true);
}
@Override
public TSet<TMap.Entry<K, V>> entrySet() {
return new TAbstractSet<TMap.Entry<K, V>>() {
@Override
public int size() {
return elementCount;
}
@Override
public void clear() {
THashtable.this.clear();
}
@Override
@SuppressWarnings("unchecked")
public boolean remove(Object object) {
if (contains(object)) {
THashtable.this.remove(((TMap.Entry<K, V>) object)
.getKey());
return true;
}
return false;
}
@Override
@SuppressWarnings("unchecked")
public boolean contains(Object object) {
Entry<K, V> entry = getEntry(((TMap.Entry<K, V>) object)
.getKey());
return object.equals(entry);
}
@Override
public TIterator<TMap.Entry<K, V>> iterator() {
return new HashIterator<>(
new TMapEntry.Type<TMap.Entry<K, V>, K, V>() {
@Override
public TMap.Entry<K, V> get(
TMapEntry<K, V> entry) {
return entry;
}
});
}
};
}
@Override
public synchronized boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof TMap) {
TMap<?, ?> map = (TMap<?, ?>) object;
if (size() != map.size()) {
return false;
}
TSet<TMap.Entry<K, V>> entries = entrySet();
for (TIterator<? extends TMap.Entry<?, ?>> iter = map.entrySet().iterator(); iter.hasNext();) {
TMap.Entry<?, ?> e = iter.next();
if (!entries.contains(e)) {
return false;
}
}
return true;
}
return false;
}
@Override
public synchronized V get(Object key) {
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % elementData.length;
Entry<K, V> entry = elementData[index];
while (entry != null) {
if (entry.equalsKey(key, hash)) {
return entry.value;
}
entry = entry.next;
}
return null;
}
Entry<K, V> getEntry(Object key) {
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % elementData.length;
Entry<K, V> entry = elementData[index];
while (entry != null) {
if (entry.equalsKey(key, hash)) {
return entry;
}
entry = entry.next;
}
return null;
}
@Override
public synchronized int hashCode() {
int result = 0;
TIterator<TMap.Entry<K, V>> it = entrySet().iterator();
while (it.hasNext()) {
TMap.Entry<K, V> entry = it.next();
Object key = entry.getKey();
if (key == this) {
continue;
}
Object value = entry.getValue();
if (value == this) {
continue;
}
int hash = (key != null ? key.hashCode() : 0)
^ (value != null ? value.hashCode() : 0);
result += hash;
}
return result;
}
@Override
public synchronized boolean isEmpty() {
return elementCount == 0;
}
@Override
@SuppressWarnings("unchecked")
public synchronized TEnumeration<K> keys() {
if (elementCount == 0) {
return (TEnumeration<K>) EMPTY_ENUMERATION;
}
return new HashEnumIterator<>(new TMapEntry.Type<K, K, V>() {
@Override
public K get(TMapEntry<K, V> entry) {
return entry.key;
}
}, true);
}
@Override
public TSet<K> keySet() {
return new TAbstractSet<K>() {
@Override
public boolean contains(Object object) {
return containsKey(object);
}
@Override
public int size() {
return elementCount;
}
@Override
public void clear() {
THashtable.this.clear();
}
@Override
public boolean remove(Object key) {
if (containsKey(key)) {
THashtable.this.remove(key);
return true;
}
return false;
}
@SuppressWarnings("unchecked")
@Override
public TIterator<K> iterator() {
if (this.size() == 0) {
return (TIterator<K>) EMPTY_ITERATOR;
}
return new HashEnumIterator<>(new TMapEntry.Type<K, K, V>() {
@Override
public K get(TMapEntry<K, V> entry) {
return entry.key;
}
});
}
};
}
class HashEnumIterator<E> extends HashIterator<E> implements TEnumeration<E> {
private boolean isEnumeration = false;
int start;
Entry<K, V> entry;
HashEnumIterator(TMapEntry.Type<E, K, V> value) {
super(value);
}
HashEnumIterator(TMapEntry.Type<E, K, V> value, boolean isEnumeration) {
super(value);
this.isEnumeration = isEnumeration;
start = lastSlot + 1;
}
@Override
public boolean hasMoreElements() {
if (isEnumeration) {
if (entry != null) {
return true;
}
while (start > firstSlot) {
if (elementData[--start] != null) {
entry = elementData[start];
return true;
}
}
return false;
}
// iterator
return super.hasNext();
}
@Override
public boolean hasNext() {
if (isEnumeration) {
return hasMoreElements();
}
// iterator
return super.hasNext();
}
@Override
public E next() {
if (isEnumeration) {
if (expectedModCount == modCount) {
return nextElement();
} else {
throw new TConcurrentModificationException();
}
}
// iterator
return super.next();
}
@Override
@SuppressWarnings("unchecked")
public E nextElement() {
if (isEnumeration) {
if (hasMoreElements()) {
Object result = type.get(entry);
entry = entry.next;
return (E) result;
}
throw new TNoSuchElementException();
}
// iterator
return super.next();
}
@Override
public void remove() {
if (isEnumeration) {
throw new TUnsupportedOperationException();
} else {
super.remove();
}
}
}
@Override
public synchronized V put(K key, V value) {
if (key != null && value != null) {
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % elementData.length;
Entry<K, V> entry = elementData[index];
while (entry != null && !entry.equalsKey(key, hash)) {
entry = entry.next;
}
if (entry == null) {
modCount++;
if (++elementCount > threshold) {
rehash();
index = (hash & 0x7FFFFFFF) % elementData.length;
}
if (index < firstSlot) {
firstSlot = index;
}
if (index > lastSlot) {
lastSlot = index;
}
entry = newEntry(key, value, hash);
entry.next = elementData[index];
elementData[index] = entry;
return null;
}
V result = entry.value;
entry.value = value;
return result;
}
throw new NullPointerException();
}
@Override
public synchronized void putAll(TMap<? extends K, ? extends V> map) {
for (TIterator<? extends TMap.Entry<? extends K, ? extends V>> iter = map.entrySet().iterator();
iter.hasNext();) {
TMap.Entry<? extends K, ? extends V> entry = iter.next();
put(entry.getKey(), entry.getValue());
}
}
protected void rehash() {
int length = (elementData.length << 1) + 1;
if (length == 0) {
length = 1;
}
int newFirst = length;
int newLast = -1;
Entry<K, V>[] newData = newElementArray(length);
for (int i = lastSlot + 1; --i >= firstSlot;) {
Entry<K, V> entry = elementData[i];
while (entry != null) {
int index = (entry.getKeyHash() & 0x7FFFFFFF) % length;
if (index < newFirst) {
newFirst = index;
}
if (index > newLast) {
newLast = index;
}
Entry<K, V> next = entry.next;
entry.next = newData[index];
newData[index] = entry;
entry = next;
}
}
firstSlot = newFirst;
lastSlot = newLast;
elementData = newData;
computeMaxSize();
}
@Override
public synchronized V remove(Object key) {
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % elementData.length;
Entry<K, V> last = null;
Entry<K, V> entry = elementData[index];
while (entry != null && !entry.equalsKey(key, hash)) {
last = entry;
entry = entry.next;
}
if (entry != null) {
modCount++;
if (last == null) {
elementData[index] = entry.next;
} else {
last.next = entry.next;
}
elementCount--;
V result = entry.value;
entry.value = null;
return result;
}
return null;
}
@Override
public synchronized int size() {
return elementCount;
}
@Override
public synchronized String toString() {
if (isEmpty()) {
return "{}";
}
StringBuilder buffer = new StringBuilder(size() * 28);
buffer.append('{');
for (int i = lastSlot; i >= firstSlot; i--) {
Entry<K, V> entry = elementData[i];
while (entry != null) {
if (entry.key != this) {
buffer.append(entry.key);
} else {
buffer.append("(this Map)");
}
buffer.append('=');
if (entry.value != this) {
buffer.append(entry.value);
} else {
buffer.append("(this Map)");
}
buffer.append(", "); //$NON-NLS-1$
entry = entry.next;
}
}
// Remove the last ", "
if (elementCount > 0) {
buffer.setLength(buffer.length() - 2);
}
buffer.append('}');
return buffer.toString();
}
@Override
public TCollection<V> values() {
return new TAbstractCollection<V>() {
@Override
public boolean contains(Object object) {
return THashtable.this.contains(object);
}
@Override
public int size() {
return elementCount;
}
@Override
public void clear() {
THashtable.this.clear();
}
@Override
public TIterator<V> iterator() {
return new HashIterator<>(
new TMapEntry.Type<V, K, V>() {
@Override
public V get(TMapEntry<K, V> entry) {
return entry.value;
}
});
}
};
}
}

View File

@ -0,0 +1,552 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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;
import java.util.Arrays;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TCloneNotSupportedException;
import org.teavm.classlib.java.lang.TCloneable;
public class TVector<E> extends TAbstractList<E> implements TList<E>, TRandomAccess, TCloneable, TSerializable {
protected int elementCount;
protected Object[] elementData;
protected int capacityIncrement;
private static final int DEFAULT_SIZE = 10;
public TVector() {
this(DEFAULT_SIZE, 0);
}
public TVector(int capacity) {
this(capacity, 0);
}
public TVector(int capacity, int capacityIncrement) {
if (capacity < 0) {
throw new IllegalArgumentException();
}
elementData = newElementArray(capacity);
elementCount = 0;
this.capacityIncrement = capacityIncrement;
}
public TVector(TCollection<? extends E> collection) {
this(collection.size(), 0);
TIterator<? extends E> it = collection.iterator();
while (it.hasNext()) {
elementData[elementCount++] = it.next();
}
}
@SuppressWarnings("unchecked")
private E[] newElementArray(int size) {
return (E[]) new Object[size];
}
@Override
public void add(int location, E object) {
insertElementAt(object, location);
}
@Override
public synchronized boolean add(E object) {
if (elementCount == elementData.length) {
growByOne();
}
elementData[elementCount++] = object;
modCount++;
return true;
}
@Override
public synchronized boolean addAll(int location, TCollection<? extends E> collection) {
if (0 <= location && location <= elementCount) {
int size = collection.size();
if (size == 0) {
return false;
}
int required = size - (elementData.length - elementCount);
if (required > 0) {
growBy(required);
}
int count = elementCount - location;
if (count > 0) {
System.arraycopy(elementData, location, elementData, location + size, count);
}
TIterator<? extends E> it = collection.iterator();
while (it.hasNext()) {
elementData[location++] = it.next();
}
elementCount += size;
modCount++;
return true;
}
throw new ArrayIndexOutOfBoundsException(location);
}
@Override
public synchronized boolean addAll(TCollection<? extends E> collection) {
return addAll(elementCount, collection);
}
public synchronized void addElement(E object) {
if (elementCount == elementData.length) {
growByOne();
}
elementData[elementCount++] = object;
modCount++;
}
public synchronized int capacity() {
return elementData.length;
}
@Override
public void clear() {
removeAllElements();
}
@Override
@SuppressWarnings("unchecked")
public synchronized Object clone() {
try {
TVector<E> vector = (TVector<E>) super.clone();
vector.elementData = elementData.clone();
return vector;
} catch (TCloneNotSupportedException e) {
return null;
}
}
@Override
public boolean contains(Object object) {
return indexOf(object, 0) != -1;
}
@Override
public synchronized boolean containsAll(TCollection<?> collection) {
return super.containsAll(collection);
}
public synchronized void copyInto(Object[] elements) {
System.arraycopy(elementData, 0, elements, 0, elementCount);
}
@SuppressWarnings("unchecked")
public synchronized E elementAt(int location) {
if (location < elementCount) {
return (E) elementData[location];
}
throw new ArrayIndexOutOfBoundsException(location);
}
public TEnumeration<E> elements() {
return new TEnumeration<E>() {
int pos = 0;
@Override
public boolean hasMoreElements() {
return pos < elementCount;
}
@Override
@SuppressWarnings("unchecked")
public E nextElement() {
synchronized (TVector.this) {
if (pos < elementCount) {
return (E) elementData[pos++];
}
}
throw new TNoSuchElementException();
}
};
}
public synchronized void ensureCapacity(int minimumCapacity) {
if (elementData.length < minimumCapacity) {
int next = (capacityIncrement <= 0 ? elementData.length : capacityIncrement) + elementData.length;
grow(minimumCapacity > next ? minimumCapacity : next);
}
}
@Override
public synchronized boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof TList) {
TList<?> list = (TList<?>) object;
if (list.size() != elementCount) {
return false;
}
int index = 0;
TIterator<?> it = list.iterator();
while (it.hasNext()) {
Object e1 = elementData[index++], e2 = it.next();
if (!(e1 == null ? e2 == null : e1.equals(e2))) {
return false;
}
}
return true;
}
return false;
}
@SuppressWarnings("unchecked")
public synchronized E firstElement() {
if (elementCount > 0) {
return (E) elementData[0];
}
throw new TNoSuchElementException();
}
@Override
public E get(int location) {
return elementAt(location);
}
private void grow(int newCapacity) {
E[] newData = newElementArray(newCapacity);
// Assumes elementCount is <= newCapacity
assert elementCount <= newCapacity;
System.arraycopy(elementData, 0, newData, 0, elementCount);
elementData = newData;
}
/**
* JIT optimization
*/
private void growByOne() {
int adding = 0;
if (capacityIncrement <= 0) {
if ((adding = elementData.length) == 0) {
adding = 1;
}
} else {
adding = capacityIncrement;
}
E[] newData = newElementArray(elementData.length + adding);
System.arraycopy(elementData, 0, newData, 0, elementCount);
elementData = newData;
}
private void growBy(int required) {
int adding = 0;
if (capacityIncrement <= 0) {
if ((adding = elementData.length) == 0) {
adding = required;
}
while (adding < required) {
adding += adding;
}
} else {
adding = (required / capacityIncrement) * capacityIncrement;
if (adding < required) {
adding += capacityIncrement;
}
}
E[] newData = newElementArray(elementData.length + adding);
System.arraycopy(elementData, 0, newData, 0, elementCount);
elementData = newData;
}
@Override
public synchronized int hashCode() {
int result = 1;
for (int i = 0; i < elementCount; i++) {
result = (31 * result) + (elementData[i] == null ? 0 : elementData[i].hashCode());
}
return result;
}
@Override
public int indexOf(Object object) {
return indexOf(object, 0);
}
public synchronized int indexOf(Object object, int location) {
if (location < 0) {
throw new ArrayIndexOutOfBoundsException();
}
if (object != null) {
for (int i = location; i < elementCount; i++) {
if (object.equals(elementData[i])) {
return i;
}
}
} else {
for (int i = location; i < elementCount; i++) {
if (elementData[i] == null) {
return i;
}
}
}
return -1;
}
public synchronized void insertElementAt(E object, int location) {
if (0 <= location && location <= elementCount) {
if (elementCount == elementData.length) {
growByOne();
}
int count = elementCount - location;
if (count > 0) {
System.arraycopy(elementData, location, elementData, location + 1, count);
}
elementData[location] = object;
elementCount++;
modCount++;
} else {
throw new ArrayIndexOutOfBoundsException(location);
}
}
@Override
public synchronized boolean isEmpty() {
return elementCount == 0;
}
@SuppressWarnings("unchecked")
public synchronized E lastElement() {
if (isEmpty()) {
throw new TNoSuchElementException();
}
return (E) elementData[elementCount - 1];
}
@Override
public synchronized int lastIndexOf(Object object) {
return lastIndexOf(object, elementCount - 1);
}
public synchronized int lastIndexOf(Object object, int location) {
if (location < 0) {
return -1;
} else if (location < elementCount) {
if (object != null) {
for (int i = location; i >= 0; i--) {
if (object.equals(elementData[i])) {
return i;
}
}
} else {
for (int i = location; i >= 0; i--) {
if (elementData[i] == null) {
return i;
}
}
}
return -1;
}
throw new ArrayIndexOutOfBoundsException(location);
}
@SuppressWarnings("unchecked")
@Override
public synchronized E remove(int location) {
if (location < elementCount && location >= 0) {
E result = (E) elementData[location];
elementCount--;
int size = elementCount - location;
if (size > 0) {
System.arraycopy(elementData, location + 1, elementData, location, size);
}
elementData[elementCount] = null;
modCount++;
return result;
}
throw new ArrayIndexOutOfBoundsException(location);
}
@Override
public boolean remove(Object object) {
return removeElement(object);
}
@Override
public synchronized boolean removeAll(TCollection<?> collection) {
return super.removeAll(collection);
}
public synchronized void removeAllElements() {
for (int i = 0; i < elementCount; i++) {
elementData[i] = null;
}
modCount++;
elementCount = 0;
}
public synchronized boolean removeElement(Object object) {
int index;
if ((index = indexOf(object, 0)) == -1) {
return false;
}
removeElementAt(index);
return true;
}
public synchronized void removeElementAt(int location) {
if (0 <= location && location < elementCount) {
elementCount--;
int size = elementCount - location;
if (size > 0) {
System.arraycopy(elementData, location + 1, elementData, location, size);
}
elementData[elementCount] = null;
modCount++;
} else {
throw new ArrayIndexOutOfBoundsException(location);
}
}
@Override
protected void removeRange(int start, int end) {
if (start >= 0 && start <= end && end <= elementCount) {
if (start == end) {
return;
}
if (end != elementCount) {
System.arraycopy(elementData, end, elementData, start, elementCount - end);
int newCount = elementCount - (end - start);
Arrays.fill(elementData, newCount, elementCount, null);
elementCount = newCount;
} else {
Arrays.fill(elementData, start, elementCount, null);
elementCount = start;
}
modCount++;
} else {
throw new IndexOutOfBoundsException();
}
}
@Override
public synchronized boolean retainAll(TCollection<?> collection) {
return super.retainAll(collection);
}
@SuppressWarnings("unchecked")
@Override
public synchronized E set(int location, E object) {
if (location >= 0 && location < elementCount) {
E result = (E) elementData[location];
elementData[location] = object;
return result;
}
throw new ArrayIndexOutOfBoundsException(location);
}
public synchronized void setElementAt(E object, int location) {
if (location < elementCount && location >= 0) {
elementData[location] = object;
} else {
throw new ArrayIndexOutOfBoundsException(location);
}
}
public synchronized void setSize(int length) {
if (length < 0) {
throw new ArrayIndexOutOfBoundsException();
}
if (length == elementCount) {
return;
}
ensureCapacity(length);
if (elementCount > length) {
Arrays.fill(elementData, length, elementCount, null);
}
elementCount = length;
modCount++;
}
@Override
public synchronized int size() {
return elementCount;
}
@Override
public synchronized Object[] toArray() {
Object[] result = new Object[elementCount];
System.arraycopy(elementData, 0, result, 0, elementCount);
return result;
}
@Override
@SuppressWarnings("unchecked")
public synchronized <T> T[] toArray(T[] contents) {
if (elementCount > contents.length) {
Class<?> ct = contents.getClass().getComponentType();
contents = (T[]) Array.newInstance(ct, elementCount);
}
System.arraycopy(elementData, 0, contents, 0, elementCount);
if (elementCount < contents.length) {
contents[elementCount] = null;
}
return contents;
}
@Override
public synchronized String toString() {
if (elementCount == 0) {
return "[]"; //$NON-NLS-1$
}
int length = elementCount - 1;
StringBuilder buffer = new StringBuilder(elementCount * 16);
buffer.append('[');
for (int i = 0; i < length; i++) {
if (elementData[i] == this) {
buffer.append("(this Collection)");
} else {
buffer.append(elementData[i]);
}
buffer.append(", ");
}
if (elementData[length] == this) {
buffer.append("(this Collection)");
} else {
buffer.append(elementData[length]);
}
buffer.append(']');
return buffer.toString();
}
public synchronized void trimToSize() {
if (elementData.length != elementCount) {
grow(elementCount);
}
}
}

View File

@ -0,0 +1,719 @@
/*
* 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeMap;
import java.util.Vector;
import org.junit.Test;
import org.teavm.classlib.support.Support_MapTest2;
import org.teavm.classlib.support.Support_UnmodifiableCollectionTest;
public class HashtableTest {
private Hashtable<String, String> ht10;
private Hashtable<String, Integer> ht100;
private Hashtable<String, String> htfull;
private Vector<String> keyVector;
private Vector<String> elmVector;
public HashtableTest() {
ht10 = new Hashtable<>(10);
ht100 = new Hashtable<>(100);
htfull = new Hashtable<>(10);
keyVector = new Vector<>(10);
elmVector = new Vector<>(10);
for (int i = 0; i < 10; i++) {
ht10.put("Key " + i, "Val " + i);
keyVector.addElement("Key " + i);
elmVector.addElement("Val " + i);
}
for (int i = 0; i < 7; i++)
htfull.put("FKey " + i, "FVal " + i);
}
@Test
public void test_Constructor() {
// Test for method java.util.Hashtable()
new Support_MapTest2(new Hashtable<String, String>()).runTest();
Hashtable<String, String> h = new Hashtable<>();
assertEquals("Created incorrect hashtable", 0, h.size());
}
@Test
public void test_ConstructorI() {
// Test for method java.util.Hashtable(int)
Hashtable<String, String> h = new Hashtable<>(9);
assertEquals("Created incorrect hashtable", 0, h.size());
Hashtable<String, String> empty = new Hashtable<>(0);
assertNull("Empty hashtable access", empty.get("nothing"));
empty.put("something", "here");
assertEquals("cannot get element", "here", empty.get("something"));
}
@Test
public void test_ConstructorIF() {
// Test for method java.util.Hashtable(int, float)
Hashtable<String, String> h = new Hashtable<>(10, 0.5f);
assertEquals("Created incorrect hashtable", 0, h.size());
Hashtable<String, String> empty = new Hashtable<>(0, 0.75f);
assertNull("Empty hashtable access", empty.get("nothing"));
empty.put("something", "here");
assertEquals("cannot get element", "here", empty.get("something"));
}
@Test
public void test_ConstructorLjava_util_Map() {
// Test for method java.util.Hashtable(java.util.Map)
Map<String, Object> map = new TreeMap<>();
Object firstVal = "Gabba";
Object secondVal = new Integer(5);
map.put("Gah", firstVal);
map.put("Ooga", secondVal);
Hashtable<String, Object> ht = new Hashtable<>(map);
assertSame("a) Incorrect Hashtable constructed", firstVal, ht.get("Gah"));
assertSame("b) Incorrect Hashtable constructed", secondVal, ht.get("Ooga"));
}
public void test_HashTable_Constructor() {
Hashtable<Hashtable<?, ?>, Set<Hashtable<?, ?>>> hashTable = new Hashtable<>();
hashTable.put(hashTable, hashTable.keySet());
new Hashtable<>(hashTable);
}
@Test
public void test_clear() {
// Test for method void java.util.Hashtable.clear()
Hashtable<String, String> h = hashtableClone(htfull);
h.clear();
assertEquals("Hashtable was not cleared", 0, h.size());
Enumeration<String> el = h.elements();
Enumeration<String> keys = h.keys();
assertTrue("Hashtable improperly cleared", !el.hasMoreElements() && !(keys.hasMoreElements()));
}
@Test
public void test_clone() {
// Test for method java.lang.Object java.util.Hashtable.clone()
@SuppressWarnings("unchecked")
Hashtable<String, String> h = (Hashtable<String, String>) htfull.clone();
assertTrue("Clone different size than original", h.size() == htfull.size());
Enumeration<String> org = htfull.keys();
Enumeration<String> cpy = h.keys();
String okey, ckey;
while (org.hasMoreElements()) {
assertTrue("Key comparison failed", (okey = org.nextElement()).equals(ckey = cpy.nextElement()));
assertTrue("Value comparison failed", (htfull.get(okey)).equals(h.get(ckey)));
}
assertTrue("Copy has more keys than original", !cpy.hasMoreElements());
}
@Test
public void test_containsLjava_lang_Object() {
// Test for method boolean
// java.util.Hashtable.contains(java.lang.Object)
assertTrue("Element not found", ht10.contains("Val 7"));
assertTrue("Invalid element found", !ht10.contains("ZZZZZZZZZZZZZZZZ"));
}
@Test
public void test_containsKeyLjava_lang_Object() {
// Test for method boolean
// java.util.Hashtable.containsKey(java.lang.Object)
assertTrue("Failed to find key", htfull.containsKey("FKey 4"));
assertTrue("Failed to find key", !htfull.containsKey("FKey 99"));
}
@Test
public void test_containsValueLjava_lang_Object() {
// Test for method boolean
// java.util.Hashtable.containsValue(java.lang.Object)
Enumeration<String> e = elmVector.elements();
while (e.hasMoreElements())
assertTrue("Returned false for valid value", ht10.containsValue(e.nextElement()));
assertTrue("Returned true for invalid value", !ht10.containsValue(new Object()));
}
@Test
public void test_elements() {
// Test for method java.util.Enumeration java.util.Hashtable.elements()
Enumeration<String> elms = ht10.elements();
while (elms.hasMoreElements()) {
String s = elms.nextElement();
assertTrue("Missing key from enumeration", elmVector.contains(s));
}
assertEquals("All keys not retrieved", 10, ht10.size());
// cast Enumeration to Iterator
@SuppressWarnings("unchecked")
Iterator<String> iterator = (Iterator<String>) elms;
assertFalse(iterator.hasNext());
try {
iterator.next();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
}
@Test
public void test_elements_subtest0() {
// this is the reference implementation behavior
final Hashtable<String, String> ht = new Hashtable<>(7);
ht.put("1", "a");
// these three elements hash to the same bucket in a 7 element Hashtable
ht.put("2", "b");
ht.put("9", "c");
ht.put("12", "d");
// Hashtable looks like:
// 0: "1"
// 1: "12" -> "9" -> "2"
Enumeration<String> en = ht.elements();
// cache the first entry
en.hasMoreElements();
ht.remove("12");
ht.remove("9");
}
@Test
public void test_entrySet() {
// Test for method java.util.Set java.util.Hashtable.entrySet()
Set<Map.Entry<String, String>> s = ht10.entrySet();
Set<String> s2 = new HashSet<>();
for (Map.Entry<String, String> entry : s) {
s2.add(entry.getValue());
}
Enumeration<String> e = elmVector.elements();
while (e.hasMoreElements())
assertTrue("Returned incorrect entry set", s2.contains(e.nextElement()));
boolean exception = false;
try {
(ht10.entrySet().iterator().next()).setValue(null);
} catch (NullPointerException e1) {
exception = true;
}
assertTrue("Should not be able to assign null to a Hashtable entrySet() Map.Entry", exception);
}
@Test
public void test_equalsLjava_lang_Object() {
// Test for method boolean java.util.Hashtable.equals(java.lang.Object)
Hashtable<String, String> h = hashtableClone(ht10);
assertTrue("Returned false for equal tables", ht10.equals(h));
assertTrue("Returned true for unequal tables", !ht10.equals(htfull));
}
@Test
public void test_getLjava_lang_Object() {
// Test for method java.lang.Object
// java.util.Hashtable.get(java.lang.Object)
Hashtable<String, String> h = hashtableClone(htfull);
assertEquals("Could not retrieve element", "FVal 2", h.get("FKey 2"));
// Regression for HARMONY-262
ReusableKey k = new ReusableKey();
Hashtable<ReusableKey, String> h2 = new Hashtable<>();
k.setKey(1);
h2.put(k, "value1");
k.setKey(13);
assertNull(h2.get(k));
k.setKey(12);
assertNull(h2.get(k));
}
@Test
public void test_hashCode() {
// Test for method int java.util.Hashtable.hashCode()
Set<Map.Entry<String, String>> entrySet = ht10.entrySet();
Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
int expectedHash;
for (expectedHash = 0; iterator.hasNext(); expectedHash += iterator.next().hashCode()) {
// do nothing
}
assertTrue("Incorrect hashCode returned. Wanted: " + expectedHash + " got: " + ht10.hashCode(),
expectedHash == ht10.hashCode());
}
@Test
public void test_isEmpty() {
// Test for method boolean java.util.Hashtable.isEmpty()
assertTrue("isEmpty returned incorrect value", !ht10.isEmpty());
assertTrue("isEmpty returned incorrect value", new Hashtable<String, String>().isEmpty());
}
@Test
public void test_keys() {
// Test for method java.util.Enumeration java.util.Hashtable.keys()
Enumeration<String> keys = ht10.keys();
while (keys.hasMoreElements()) {
String s = keys.nextElement();
assertTrue("Missing key from enumeration", keyVector.contains(s));
}
assertEquals("All keys not retrieved", 10, ht10.size());
// cast Enumeration to Iterator
@SuppressWarnings("unchecked")
Iterator<String> iterator = (Iterator<String>) keys;
assertFalse(iterator.hasNext());
try {
iterator.next();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
}
@Test
public void test_keys_subtest0() {
// this is the reference implementation behavior
final Hashtable<String, String> ht = new Hashtable<>(3);
ht.put("initial", "");
Enumeration<String> en = ht.keys();
en.hasMoreElements();
ht.remove("initial");
boolean exception = false;
try {
Object result = en.nextElement();
assertTrue("unexpected: " + result, "initial".equals(result));
} catch (NoSuchElementException e) {
exception = true;
}
assertTrue("unexpected NoSuchElementException", !exception);
}
@Test
public void test_keySet() {
// Test for method java.util.Set java.util.Hashtable.keySet()
Set<String> s = ht10.keySet();
Enumeration<String> e = keyVector.elements();
while (e.hasMoreElements())
assertTrue("Returned incorrect key set", s.contains(e.nextElement()));
Map<Integer, String> map = new Hashtable<>(101);
map.put(new Integer(1), "1");
map.put(new Integer(102), "102");
map.put(new Integer(203), "203");
Iterator<Integer> it = map.keySet().iterator();
Integer remove1 = it.next();
it.remove();
Integer remove2 = it.next();
it.remove();
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(new Integer[] { 1, 102, 203 }));
list.remove(remove1);
list.remove(remove2);
assertTrue("Wrong result", it.next().equals(list.get(0)));
assertEquals("Wrong size", 1, map.size());
assertTrue("Wrong contents", map.keySet().iterator().next().equals(list.get(0)));
Map<Integer, String> map2 = new Hashtable<>(101);
map2.put(new Integer(1), "1");
map2.put(new Integer(4), "4");
Iterator<Integer> it2 = map2.keySet().iterator();
Integer remove3 = it2.next();
Integer next;
if (remove3.intValue() == 1)
next = new Integer(4);
else
next = new Integer(1);
it2.hasNext();
it2.remove();
assertTrue("Wrong result 2", it2.next().equals(next));
assertEquals("Wrong size 2", 1, map2.size());
assertTrue("Wrong contents 2", map2.keySet().iterator().next().equals(next));
// cast Iterator to Enumeration
@SuppressWarnings("unchecked")
Enumeration<String> enumeration = (Enumeration<String>) s.iterator();
assertTrue(enumeration.hasMoreElements());
}
@Test
public void test_keySet_subtest0() {
Set<String> s1 = ht10.keySet();
assertTrue("should contain key", s1.remove("Key 0"));
assertTrue("should not contain key", !s1.remove("Key 0"));
}
@Test
public void test_keySet_subtest1() {
// this is the reference implementation behavior
final Hashtable<String, String> ht = new Hashtable<>(7);
ht.put("1", "a");
// these three elements hash to the same bucket in a 7 element Hashtable
ht.put("2", "b");
ht.put("9", "c");
ht.put("12", "d");
// Hashtable looks like:
// 0: "1"
// 1: "12" -> "9" -> "2"
Enumeration<String> en = ht.elements();
// cache the first entry
en.hasMoreElements();
Iterator<String> it = ht.keySet().iterator();
// this is mostly a copy of the test in test_elements_subtest0()
// test removing with the iterator does not null the values
while (it.hasNext()) {
String key = it.next();
if ("1".equals(key)) {
it.remove();
}
}
boolean exception = false;
try {
// cached "12"
Set<String> iteratorElements = new HashSet<>();
iteratorElements.add(en.nextElement());
iteratorElements.add(en.nextElement());
iteratorElements.add(en.nextElement());
assertTrue(iteratorElements.contains("b"));
assertTrue(iteratorElements.contains("c"));
assertTrue(iteratorElements.contains("d"));
} catch (NoSuchElementException e) {
exception = true;
}
assertTrue("unexpected NoSuchElementException", !exception);
}
@Test
public void test_putLjava_lang_ObjectLjava_lang_Object() {
// Test for method java.lang.Object
// java.util.Hashtable.put(java.lang.Object, java.lang.Object)
Hashtable<String, Integer> h = hashtableClone(ht100);
Integer key = new Integer(100);
h.put("Value 100", key);
assertTrue("Key/Value not inserted", h.size() == 1 && (h.contains(key)));
}
@Test
public void test_putAllLjava_util_Map() {
// Test for method void java.util.Hashtable.putAll(java.util.Map)
Hashtable<String, String> h = new Hashtable<>();
h.putAll(ht10);
Enumeration<String> e = keyVector.elements();
while (e.hasMoreElements()) {
Object x = e.nextElement();
assertTrue("Failed to put all elements", h.get(x).equals(ht10.get(x)));
}
}
@Test
public void test_removeLjava_lang_Object() {
// Test for method java.lang.Object
// java.util.Hashtable.remove(java.lang.Object)
Hashtable<String, String> h = hashtableClone(htfull);
Object k = h.remove("FKey 0");
assertTrue("Remove failed", !h.containsKey("FKey 0") || k == null);
}
@Test
public void test_HashTable_remove_scenario1() {
Hashtable<Hashtable<?, ?>, Set<Hashtable<?, ?>>> hashTable = new Hashtable<>();
Set<Hashtable<?, ?>> keySet = hashTable.keySet();
hashTable.put(hashTable, keySet);
hashTable.remove(hashTable);
}
@Test
public void test_HashTable_remove_scenario2() {
Hashtable<Hashtable<?, ?>, Hashtable<?, ?>> hashTable = new Hashtable<>();
hashTable.keySet();
hashTable.put(hashTable, hashTable);
hashTable.remove(hashTable);
}
@Test
public void test_HashTable_remove_scenario3() {
Hashtable<Hashtable<Hashtable<?, ?>, Hashtable<?, ?>>, Hashtable<?, ?>> hashTable = new Hashtable<>();
Hashtable<Hashtable<?, ?>, Hashtable<?, ?>> keyHashTable = new Hashtable<>();
keyHashTable.put(hashTable, keyHashTable);
hashTable.put(keyHashTable, hashTable);
hashTable.remove(keyHashTable);
}
@Test
public void test_size() {
// Test for method int java.util.Hashtable.size()
assertTrue("Returned invalid size", ht10.size() == 10 && (ht100.size() == 0));
}
@Test
public void test_toString() {
// Test for method java.lang.String java.util.Hashtable.toString()
Hashtable<Serializable, Serializable> h = new Hashtable<>();
assertEquals("Incorrect toString for Empty table", "{}", h.toString());
h.put("one", "1");
h.put("two", h);
h.put(h, "3");
h.put(h, h);
String result = h.toString();
assertTrue("should contain self ref", result.indexOf("(this") > -1);
}
@Test
public void test_values() {
// Test for method java.util.Collection java.util.Hashtable.values()
Collection<String> c = ht10.values();
Enumeration<String> e = elmVector.elements();
while (e.hasMoreElements())
assertTrue("Returned incorrect values", c.contains(e.nextElement()));
Hashtable<Integer, Integer> myHashtable = new Hashtable<>();
for (int i = 0; i < 100; i++)
myHashtable.put(new Integer(i), new Integer(i));
Collection<Integer> values = myHashtable.values();
new Support_UnmodifiableCollectionTest(values).runTest();
values.remove(new Integer(0));
assertTrue("Removing from the values collection should remove from the original map",
!myHashtable.containsValue(new Integer(0)));
}
@Test
public void test_entrySet_remove() {
Hashtable<String, String> hashtable = new Hashtable<>();
hashtable.put("my.nonexistent.prop", "AAA");
hashtable.put("parse.error", "BBB");
Iterator<Map.Entry<String, String>> iterator = hashtable.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
final Object value = entry.getValue();
if (value.equals("AAA")) {
iterator.remove();
}
}
assertFalse(hashtable.containsKey("my.nonexistent.prop"));
}
@Test
@SuppressWarnings("unchecked")
public void test_keys_elements_keySet_Exceptions() {
Hashtable<String, String> hashTable = new Hashtable<>();
String key = "key";
String value = "value";
hashTable.put(key, value);
Iterator<String> iterator = (Iterator<String>) hashTable.keys();
assertTrue(iterator.hasNext());
try {
iterator.remove();
fail("should throw UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// Expected
}
iterator.next();
try {
iterator.remove();
fail("should throw UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// Expected
}
assertFalse(iterator.hasNext());
iterator = (Iterator<String>) hashTable.elements();
assertTrue(iterator.hasNext());
try {
iterator.remove();
fail("should throw UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// Expected
}
iterator.next();
try {
iterator.remove();
fail("should throw UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// Expected
}
assertFalse(iterator.hasNext());
iterator = hashTable.keySet().iterator();
assertTrue(iterator.hasNext());
try {
iterator.remove();
fail("should throw IllegalStateException");
} catch (IllegalStateException e) {
// Expected
}
iterator.next();
iterator.remove();
assertFalse(iterator.hasNext());
hashTable.clear();
for (int i = 0; i < 10; i++) {
hashTable.put(key + i, value + i);
}
// cast Enumeration to Iterator
Enumeration<String> enumeration = hashTable.keys();
iterator = (Iterator<String>) enumeration;
assertTrue(enumeration.hasMoreElements());
assertTrue(iterator.hasNext());
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
enumeration.nextElement();
} else {
iterator.next();
}
}
assertFalse(enumeration.hasMoreElements());
assertFalse(iterator.hasNext());
try {
enumeration.nextElement();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
try {
iterator.next();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
// cast Enumeration to Iterator
enumeration = hashTable.elements();
iterator = (Iterator<String>) enumeration;
assertTrue(enumeration.hasMoreElements());
assertTrue(iterator.hasNext());
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
enumeration.nextElement();
} else {
iterator.next();
}
}
assertFalse(enumeration.hasMoreElements());
assertFalse(iterator.hasNext());
try {
enumeration.nextElement();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
try {
iterator.next();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
// cast Iterator to Enumeration
enumeration = (Enumeration<String>) hashTable.keySet().iterator();
iterator = (Iterator<String>) enumeration;
assertTrue(enumeration.hasMoreElements());
assertTrue(iterator.hasNext());
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
enumeration.nextElement();
} else {
iterator.next();
}
}
assertFalse(enumeration.hasMoreElements());
assertFalse(iterator.hasNext());
try {
enumeration.nextElement();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
try {
iterator.next();
fail("should throw NoSuchElementException");
} catch (NoSuchElementException e) {
// Expected
}
}
@SuppressWarnings("unchecked")
protected <K, V> Hashtable<K, V> hashtableClone(Hashtable<K, V> s) {
return (Hashtable<K, V>) s.clone();
}
static class ReusableKey {
private int key = 0;
public void setKey(int key) {
this.key = key;
}
@Override
public int hashCode() {
return key;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof ReusableKey)) {
return false;
}
return key == ((ReusableKey) o).key;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,100 @@
/*
* 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.support;
import static org.junit.Assert.*;
import java.util.Collection;
import java.util.TreeSet;
/**
* @tests java.util.Collection
*/
public class Support_CollectionTest {
Collection<Integer> col; // must contain the Integers 0 to 99
public Support_CollectionTest() {
}
public Support_CollectionTest(Collection<Integer> c) {
col = c;
}
public void runTest() {
new Support_UnmodifiableCollectionTest(col).runTest();
// setup
Collection<Integer> myCollection = new TreeSet<>();
myCollection.add(new Integer(101));
myCollection.add(new Integer(102));
myCollection.add(new Integer(103));
// add
assertTrue("CollectionTest - a) add did not work", col.add(new Integer(101)));
assertTrue("CollectionTest - b) add did not work", col.contains(new Integer(101)));
// remove
assertTrue("CollectionTest - a) remove did not work", col.remove(new Integer(101)));
assertTrue("CollectionTest - b) remove did not work", !col.contains(new Integer(101)));
// addAll
assertTrue("CollectionTest - a) addAll failed", col.addAll(myCollection));
assertTrue("CollectionTest - b) addAll failed", col.containsAll(myCollection));
// containsAll
assertTrue("CollectionTest - a) containsAll failed", col.containsAll(myCollection));
col.remove(new Integer(101));
assertTrue("CollectionTest - b) containsAll failed", !col.containsAll(myCollection));
// removeAll
assertTrue("CollectionTest - a) removeAll failed", col.removeAll(myCollection));
assertTrue("CollectionTest - b) removeAll failed", !col.removeAll(myCollection));
assertTrue("CollectionTest - c) removeAll failed", !col.contains(new Integer(102)));
assertTrue("CollectionTest - d) removeAll failed", !col.contains(new Integer(103)));
// retianAll
col.addAll(myCollection);
assertTrue("CollectionTest - a) retainAll failed", col.retainAll(myCollection));
assertTrue("CollectionTest - b) retainAll failed", !col.retainAll(myCollection));
assertTrue("CollectionTest - c) retainAll failed", col.containsAll(myCollection));
assertTrue("CollectionTest - d) retainAll failed", !col.contains(new Integer(0)));
assertTrue("CollectionTest - e) retainAll failed", !col.contains(new Integer(50)));
// clear
col.clear();
assertTrue("CollectionTest - a) clear failed", col.isEmpty());
assertTrue("CollectionTest - b) clear failed", !col.contains(new Integer(101)));
}
}

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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.support;
import static org.junit.Assert.*;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
public class Support_ListTest {
List<Integer> list; // must contain the Integers 0 to 99 in order
public Support_ListTest() {
}
public Support_ListTest(List<Integer> l) {
list = l;
}
public void runTest() {
int hashCode = 1;
for (int counter = 0; counter < 100; counter++) {
Object elem;
elem = list.get(counter);
hashCode = 31 * hashCode + elem.hashCode();
assertTrue("ListTest - get failed", elem.equals(new Integer(counter)));
}
assertTrue("ListTest - hashCode failed", hashCode == list.hashCode());
list.add(50, new Integer(1000));
assertTrue("ListTest - a) add with index failed--did not insert", list.get(50).equals(new Integer(1000)));
assertTrue("ListTest - b) add with index failed--did not move following elements",
list.get(51).equals(new Integer(50)));
assertTrue("ListTest - c) add with index failed--affected previous elements",
list.get(49).equals(new Integer(49)));
list.set(50, new Integer(2000));
assertTrue("ListTest - a) set failed--did not set", list.get(50).equals(new Integer(2000)));
assertTrue("ListTest - b) set failed--affected following elements", list.get(51).equals(new Integer(50)));
assertTrue("ListTest - c) set failed--affected previous elements", list.get(49).equals(new Integer(49)));
list.remove(50);
assertTrue("ListTest - a) remove with index failed--did not remove", list.get(50).equals(new Integer(50)));
assertTrue("ListTest - b) remove with index failed--did not move following elements",
list.get(51).equals(new Integer(51)));
assertTrue("ListTest - c) remove with index failed--affected previous elements",
list.get(49).equals(new Integer(49)));
List<Integer> myList = new LinkedList<>();
myList.add(new Integer(500));
myList.add(new Integer(501));
myList.add(new Integer(502));
list.addAll(50, myList);
assertTrue("ListTest - a) addAll with index failed--did not insert", list.get(50).equals(new Integer(500)));
assertTrue("ListTest - b) addAll with index failed--did not insert", list.get(51).equals(new Integer(501)));
assertTrue("ListTest - c) addAll with index failed--did not insert", list.get(52).equals(new Integer(502)));
assertTrue("ListTest - d) addAll with index failed--did not move following elements",
list.get(53).equals(new Integer(50)));
assertTrue("ListTest - e) addAll with index failed--affected previous elements",
list.get(49).equals(new Integer(49)));
List<Integer> mySubList = list.subList(50, 53);
assertEquals(3, mySubList.size());
assertTrue("ListTest - a) sublist Failed--does not contain correct elements",
mySubList.get(0).equals(new Integer(500)));
assertTrue("ListTest - b) sublist Failed--does not contain correct elements",
mySubList.get(1).equals(new Integer(501)));
assertTrue("ListTest - c) sublist Failed--does not contain correct elements",
mySubList.get(2).equals(new Integer(502)));
t_listIterator(mySubList);
mySubList.clear();
assertEquals("ListTest - Clearing the sublist did not remove the appropriate elements from the original list",
100, list.size());
t_listIterator(list);
ListIterator<Integer> li = list.listIterator();
for (int counter = 0; li.hasNext(); counter++) {
Object elem;
elem = li.next();
assertTrue("ListTest - listIterator failed", elem.equals(new Integer(counter)));
}
new Support_CollectionTest(list).runTest();
}
public void t_listIterator(List<Integer> list) {
ListIterator<Integer> li = list.listIterator(1);
assertTrue("listIterator(1)", li.next() == list.get(1));
int orgSize = list.size();
li = list.listIterator();
for (int i = 0; i <= orgSize; i++) {
if (i == 0) {
assertTrue("list iterator hasPrevious(): " + i, !li.hasPrevious());
} else {
assertTrue("list iterator hasPrevious(): " + i, li.hasPrevious());
}
if (i == list.size()) {
assertTrue("list iterator hasNext(): " + i, !li.hasNext());
} else {
assertTrue("list iterator hasNext(): " + i, li.hasNext());
}
assertTrue("list iterator nextIndex(): " + i, li.nextIndex() == i);
assertTrue("list iterator previousIndex(): " + i, li.previousIndex() == i - 1);
boolean exception = false;
try {
assertTrue("list iterator next(): " + i, li.next() == list.get(i));
} catch (NoSuchElementException e) {
exception = true;
}
if (i == list.size()) {
assertTrue("list iterator next() exception: " + i, exception);
} else {
assertTrue("list iterator next() exception: " + i, !exception);
}
}
for (int i = orgSize - 1; i >= 0; i--) {
assertTrue("list iterator previous(): " + i, li.previous() == list.get(i));
assertTrue("list iterator nextIndex()2: " + i, li.nextIndex() == i);
assertTrue("list iterator previousIndex()2: " + i, li.previousIndex() == i - 1);
if (i == 0) {
assertTrue("list iterator hasPrevious()2: " + i, !li.hasPrevious());
} else {
assertTrue("list iterator hasPrevious()2: " + i, li.hasPrevious());
}
assertTrue("list iterator hasNext()2: " + i, li.hasNext());
}
boolean exception = false;
try {
li.previous();
} catch (NoSuchElementException e) {
exception = true;
}
assertTrue("list iterator previous() exception", exception);
Integer add1 = new Integer(600);
Integer add2 = new Integer(601);
li.add(add1);
assertTrue("list iterator add(), size()", list.size() == (orgSize + 1));
assertEquals("list iterator add(), nextIndex()", 1, li.nextIndex());
assertEquals("list iterator add(), previousIndex()", 0, li.previousIndex());
Object next = li.next();
assertTrue("list iterator add(), next(): " + next, next == list.get(1));
li.add(add2);
Object previous = li.previous();
assertTrue("list iterator add(), previous(): " + previous, previous == add2);
assertEquals("list iterator add(), nextIndex()2", 2, li.nextIndex());
assertEquals("list iterator add(), previousIndex()2", 1, li.previousIndex());
li.remove();
assertTrue("list iterator remove(), size()", list.size() == (orgSize + 1));
assertEquals("list iterator remove(), nextIndex()", 2, li.nextIndex());
assertEquals("list iterator remove(), previousIndex()", 1, li.previousIndex());
assertTrue("list iterator previous()2", li.previous() == list.get(1));
assertTrue("list iterator previous()3", li.previous() == list.get(0));
assertTrue("list iterator next()2", li.next() == list.get(0));
li.remove();
assertTrue("list iterator hasPrevious()3", !li.hasPrevious());
assertTrue("list iterator hasNext()3", li.hasNext());
assertTrue("list iterator size()", list.size() == orgSize);
assertEquals("list iterator nextIndex()3", 0, li.nextIndex());
assertEquals("list iterator previousIndex()3", -1, li.previousIndex());
}
}

View File

@ -1,3 +1,18 @@
/*
* 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@ -14,6 +29,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.support;
import static org.junit.Assert.*;
@ -37,9 +53,12 @@ public class Support_MapTest2 {
assertEquals("size should be one", 1, map.size());
map.clear();
assertEquals("size should be zero", 0, map.size());
assertTrue("Should not have entries", !map.entrySet().iterator().hasNext());
assertTrue("Should not have keys", !map.keySet().iterator().hasNext());
assertTrue("Should not have values", !map.values().iterator().hasNext());
assertTrue("Should not have entries", !map.entrySet().iterator()
.hasNext());
assertTrue("Should not have keys", !map.keySet().iterator()
.hasNext());
assertTrue("Should not have values", !map.values().iterator()
.hasNext());
} catch (UnsupportedOperationException e) {
}
@ -48,9 +67,12 @@ public class Support_MapTest2 {
assertEquals("size should be one", 1, map.size());
map.remove("one");
assertEquals("size should be zero", 0, map.size());
assertTrue("Should not have entries", !map.entrySet().iterator().hasNext());
assertTrue("Should not have keys", !map.keySet().iterator().hasNext());
assertTrue("Should not have values", !map.values().iterator().hasNext());
assertTrue("Should not have entries", !map.entrySet().iterator()
.hasNext());
assertTrue("Should not have keys", !map.keySet().iterator()
.hasNext());
assertTrue("Should not have values", !map.values().iterator()
.hasNext());
} catch (UnsupportedOperationException e) {
}
}

View File

@ -0,0 +1,121 @@
/*
* 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.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.support;
import static org.junit.Assert.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
public class Support_UnmodifiableCollectionTest {
Collection<Integer> col;
public Support_UnmodifiableCollectionTest() {
}
public Support_UnmodifiableCollectionTest(Collection<Integer> c) {
col = c;
}
public void runTest() {
// contains
assertTrue("UnmodifiableCollectionTest - should contain 0", col
.contains(new Integer(0)));
assertTrue("UnmodifiableCollectionTest - should contain 50", col
.contains(new Integer(50)));
assertTrue("UnmodifiableCollectionTest - should not contain 100", !col
.contains(new Integer(100)));
// containsAll
HashSet<Integer> hs = new HashSet<>();
hs.add(new Integer(0));
hs.add(new Integer(25));
hs.add(new Integer(99));
assertTrue(
"UnmodifiableCollectionTest - should contain set of 0, 25, and 99",
col.containsAll(hs));
hs.add(new Integer(100));
assertTrue(
"UnmodifiableCollectionTest - should not contain set of 0, 25, 99 and 100",
!col.containsAll(hs));
// isEmpty
assertTrue("UnmodifiableCollectionTest - should not be empty", !col
.isEmpty());
// iterator
Iterator<Integer> it = col.iterator();
SortedSet<Integer> ss = new TreeSet<>();
while (it.hasNext()) {
ss.add(it.next());
}
it = ss.iterator();
for (int counter = 0; it.hasNext(); counter++) {
int nextValue = it.next().intValue();
assertTrue(
"UnmodifiableCollectionTest - Iterator returned wrong value. Wanted: "
+ counter + " got: " + nextValue,
nextValue == counter);
}
// size
assertTrue(
"UnmodifiableCollectionTest - returned wrong size. Wanted 100, got: "
+ col.size(), col.size() == 100);
// toArray
Object[] objArray;
objArray = col.toArray();
for (int counter = 0; it.hasNext(); counter++) {
assertTrue(
"UnmodifiableCollectionTest - toArray returned incorrect array",
objArray[counter] == it.next());
}
// toArray (Object[])
objArray = new Object[100];
col.toArray(objArray);
for (int counter = 0; it.hasNext(); counter++) {
assertTrue(
"UnmodifiableCollectionTest - toArray(Object) filled array incorrectly",
objArray[counter] == it.next());
}
}
}