mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 16:04:10 -08:00
Adds Vector and Hashtable
This commit is contained in:
parent
9b18d51760
commit
e9af85534f
|
@ -42,15 +42,23 @@ public abstract class TAbstractList<E> extends TAbstractCollection<E> implements
|
||||||
private int index;
|
private int index;
|
||||||
private int modCount = TAbstractList.this.modCount;
|
private int modCount = TAbstractList.this.modCount;
|
||||||
private int size = size();
|
private int size = size();
|
||||||
|
private int removeIndex = -1;
|
||||||
@Override public boolean hasNext() {
|
@Override public boolean hasNext() {
|
||||||
return index < size;
|
return index < size;
|
||||||
}
|
}
|
||||||
@Override public E next() {
|
@Override public E next() {
|
||||||
checkConcurrentModification();
|
checkConcurrentModification();
|
||||||
|
removeIndex = index;
|
||||||
return get(index++);
|
return get(index++);
|
||||||
}
|
}
|
||||||
@Override public void remove() {
|
@Override public void remove() {
|
||||||
|
if (removeIndex < 0) {
|
||||||
|
throw new TIllegalStateException();
|
||||||
|
}
|
||||||
TAbstractList.this.remove(index - 1);
|
TAbstractList.this.remove(index - 1);
|
||||||
|
modCount = TAbstractList.this.modCount;
|
||||||
|
--index;
|
||||||
|
removeIndex = -1;
|
||||||
}
|
}
|
||||||
private void checkConcurrentModification() {
|
private void checkConcurrentModification() {
|
||||||
if (modCount < TAbstractList.this.modCount) {
|
if (modCount < TAbstractList.this.modCount) {
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
@ -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)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
@ -14,6 +29,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.teavm.classlib.support;
|
package org.teavm.classlib.support;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -37,9 +53,12 @@ public class Support_MapTest2 {
|
||||||
assertEquals("size should be one", 1, map.size());
|
assertEquals("size should be one", 1, map.size());
|
||||||
map.clear();
|
map.clear();
|
||||||
assertEquals("size should be zero", 0, map.size());
|
assertEquals("size should be zero", 0, map.size());
|
||||||
assertTrue("Should not have entries", !map.entrySet().iterator().hasNext());
|
assertTrue("Should not have entries", !map.entrySet().iterator()
|
||||||
assertTrue("Should not have keys", !map.keySet().iterator().hasNext());
|
.hasNext());
|
||||||
assertTrue("Should not have values", !map.values().iterator().hasNext());
|
assertTrue("Should not have keys", !map.keySet().iterator()
|
||||||
|
.hasNext());
|
||||||
|
assertTrue("Should not have values", !map.values().iterator()
|
||||||
|
.hasNext());
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,9 +67,12 @@ public class Support_MapTest2 {
|
||||||
assertEquals("size should be one", 1, map.size());
|
assertEquals("size should be one", 1, map.size());
|
||||||
map.remove("one");
|
map.remove("one");
|
||||||
assertEquals("size should be zero", 0, map.size());
|
assertEquals("size should be zero", 0, map.size());
|
||||||
assertTrue("Should not have entries", !map.entrySet().iterator().hasNext());
|
assertTrue("Should not have entries", !map.entrySet().iterator()
|
||||||
assertTrue("Should not have keys", !map.keySet().iterator().hasNext());
|
.hasNext());
|
||||||
assertTrue("Should not have values", !map.values().iterator().hasNext());
|
assertTrue("Should not have keys", !map.keySet().iterator()
|
||||||
|
.hasNext());
|
||||||
|
assertTrue("Should not have values", !map.values().iterator()
|
||||||
|
.hasNext());
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user