mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Proper implementation for List.of, Set.of, Map.of/ofEntries
This commit is contained in:
parent
74cc1d8d7d
commit
55ba9be16a
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 Alexey Andreev.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.teavm.classlib.java.util;
|
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
|
||||||
import java.util.RandomAccess;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory-methods for List/Set/Map.of(...).
|
|
||||||
*/
|
|
||||||
class CollectionsFactory {
|
|
||||||
|
|
||||||
private CollectionsFactory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
static <E> TList<E> createList(E... elements) {
|
|
||||||
if (elements.length == 0) {
|
|
||||||
return TCollections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't permit null elements
|
|
||||||
for (E element : elements) {
|
|
||||||
requireNonNull(element, "element");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ImmutableArrayList<>(elements);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
static <E> TSet<E> createSet(E... elements) {
|
|
||||||
if (elements.length == 0) {
|
|
||||||
return TCollections.emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't permit null or duplicate elements
|
|
||||||
final TSet<E> set = new THashSet<>();
|
|
||||||
for (E element : elements) {
|
|
||||||
if (!set.add(requireNonNull(element, "element"))) {
|
|
||||||
throw new IllegalArgumentException("duplicate element: " + element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TCollections.unmodifiableSet(set);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
static <K, V> TMap<K, V> createMap(TMap.Entry<K, V>... entries) {
|
|
||||||
if (entries.length == 0) {
|
|
||||||
return TCollections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't permit null or duplicate keys and don't permit null values
|
|
||||||
final TMap<K, V> map = new THashMap<>();
|
|
||||||
for (TMap.Entry<K, V> entry : entries) {
|
|
||||||
if (map.put(requireNonNull(entry.getKey(), "key"), requireNonNull(entry.getValue(), "value")) != null) {
|
|
||||||
throw new IllegalArgumentException("duplicate key: " + entry.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TCollections.unmodifiableMap(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ImmutableArrayList<T> extends TAbstractList<T> implements RandomAccess {
|
|
||||||
private final T[] list;
|
|
||||||
|
|
||||||
public ImmutableArrayList(T[] list) {
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T get(int index) {
|
|
||||||
return list[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return list.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -76,7 +76,7 @@ public abstract class TAbstractMap<K, V> extends TObject implements TMap<K, V> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.valueOf(getKey()) + "=" + String.valueOf(getValue());
|
return getKey() + "=" + getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ public abstract class TAbstractMap<K, V> extends TObject implements TMap<K, V> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.valueOf(getKey()) + "=" + String.valueOf(getValue());
|
return getKey() + "=" + getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import org.teavm.classlib.java.util.TMap.Entry;
|
||||||
|
|
||||||
public class TCollections extends TObject {
|
public class TCollections extends TObject {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public static final TSet EMPTY_SET = new TAbstractSet<Object>() {
|
public static final TSet EMPTY_SET = new TTemplateCollections.AbstractImmutableSet<Object>() {
|
||||||
@Override public int size() {
|
@Override public int size() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public class TCollections extends TObject {
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public static final TMap EMPTY_MAP = new TAbstractMap<Object, Object>() {
|
public static final TMap EMPTY_MAP = new TTemplateCollections.AbstractImmutableMap<Object, Object>() {
|
||||||
@Override public TSet<Entry<Object, Object>> entrySet() {
|
@Override public TSet<Entry<Object, Object>> entrySet() {
|
||||||
return emptySet();
|
return emptySet();
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ public class TCollections extends TObject {
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public static final TList EMPTY_LIST = new TAbstractList<Object>() {
|
public static final TList EMPTY_LIST = new TTemplateCollections.AbstractImmutableList<Object>() {
|
||||||
@Override public Object get(int index) {
|
@Override public Object get(int index) {
|
||||||
throw new TIndexOutOfBoundsException();
|
throw new TIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
|
@ -164,47 +164,12 @@ public class TCollections extends TObject {
|
||||||
return (TMap<K, V>) EMPTY_MAP;
|
return (TMap<K, V>) EMPTY_MAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> TList<T> singletonList(final T o) {
|
public static <T> TList<T> singletonList(T o) {
|
||||||
return new TAbstractList<T>() {
|
return new TTemplateCollections.SingleElementList<>(o);
|
||||||
@Override public T get(int index) {
|
|
||||||
if (index != 0) {
|
|
||||||
throw new TIndexOutOfBoundsException();
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
@Override public int size() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> TSet<T> singleton(final T o) {
|
public static <T> TSet<T> singleton(T o) {
|
||||||
return new TAbstractSet<T>() {
|
return new TTemplateCollections.SingleElementSet<>(o);
|
||||||
@Override public int size() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@Override public TIterator<T> iterator() {
|
|
||||||
return new TIterator<T>() {
|
|
||||||
private boolean read;
|
|
||||||
@Override public boolean hasNext() {
|
|
||||||
return !read;
|
|
||||||
}
|
|
||||||
@Override public T next() {
|
|
||||||
if (read) {
|
|
||||||
throw new TNoSuchElementException();
|
|
||||||
}
|
|
||||||
read = true;
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
@Override public void remove() {
|
|
||||||
throw new TUnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@Override public boolean contains(Object o2) {
|
|
||||||
return TObjects.equals(o, o2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <K, V> TMap<K, V> singletonMap(final K key, final V value) {
|
public static <K, V> TMap<K, V> singletonMap(final K key, final V value) {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.util;
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Objects;
|
||||||
import org.teavm.classlib.java.util.function.TUnaryOperator;
|
import org.teavm.classlib.java.util.function.TUnaryOperator;
|
||||||
|
|
||||||
public interface TList<E> extends TCollection<E> {
|
public interface TList<E> extends TCollection<E> {
|
||||||
|
@ -55,49 +55,104 @@ public interface TList<E> extends TCollection<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e) {
|
static <E> TList<E> of(E e) {
|
||||||
return CollectionsFactory.createList(e);
|
return TCollections.singletonList(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2) {
|
static <E> TList<E> of(E e1, E e2) {
|
||||||
return CollectionsFactory.createList(e1, e2);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
return new TTemplateCollections.TwoElementsList<>(e1, e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3) {
|
static <E> TList<E> of(E e1, E e2, E e3) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4, e5);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
Objects.requireNonNull(e5);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4, e5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4, e5, e6);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
Objects.requireNonNull(e5);
|
||||||
|
Objects.requireNonNull(e6);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4, e5, e6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4, e5, e6, e7);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
Objects.requireNonNull(e5);
|
||||||
|
Objects.requireNonNull(e6);
|
||||||
|
Objects.requireNonNull(e7);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4, e5, e6, e7);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4, e5, e6, e7, e8);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
Objects.requireNonNull(e5);
|
||||||
|
Objects.requireNonNull(e6);
|
||||||
|
Objects.requireNonNull(e7);
|
||||||
|
Objects.requireNonNull(e8);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4, e5, e6, e7, e8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4, e5, e6, e7, e8, e9);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
Objects.requireNonNull(e5);
|
||||||
|
Objects.requireNonNull(e6);
|
||||||
|
Objects.requireNonNull(e7);
|
||||||
|
Objects.requireNonNull(e8);
|
||||||
|
Objects.requireNonNull(e9);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4, e5, e6, e7, e8, e9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
static <E> TList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
||||||
return CollectionsFactory.createList(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
Objects.requireNonNull(e3);
|
||||||
|
Objects.requireNonNull(e4);
|
||||||
|
Objects.requireNonNull(e5);
|
||||||
|
Objects.requireNonNull(e6);
|
||||||
|
Objects.requireNonNull(e7);
|
||||||
|
Objects.requireNonNull(e8);
|
||||||
|
Objects.requireNonNull(e9);
|
||||||
|
Objects.requireNonNull(e10);
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
static <E> TList<E> of(E... elements) {
|
static <E> TList<E> of(E... elements) {
|
||||||
// the returned list reuses the given array
|
for (E element : elements) {
|
||||||
// create a copy to prevent modifying the list by modifying the original array
|
Objects.requireNonNull(element);
|
||||||
return CollectionsFactory.createList(Arrays.copyOf(elements, elements.length));
|
}
|
||||||
|
return new TTemplateCollections.ImmutableArrayList<>(elements.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,20 +159,15 @@ public interface TMap<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1) {
|
static <K, V> TMap<K, V> of(K k1, V v1) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.SingleEntryMap<>(k1, v1);
|
||||||
entry(k1, v1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2) {
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.TwoEntriesMap<>(k1, v1, k2, v2);
|
||||||
entry(k1, v1),
|
|
||||||
entry(k2, v2)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3)
|
entry(k3, v3)
|
||||||
|
@ -180,7 +175,7 @@ public interface TMap<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -189,7 +184,7 @@ public interface TMap<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -199,7 +194,7 @@ public interface TMap<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -211,7 +206,7 @@ public interface TMap<K, V> {
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||||
K k6, V v6, K k7, V v7) {
|
K k6, V v6, K k7, V v7) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -224,7 +219,7 @@ public interface TMap<K, V> {
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||||
K k6, V v6, K k7, V v7, K k8, V v8) {
|
K k6, V v6, K k7, V v7, K k8, V v8) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -238,7 +233,7 @@ public interface TMap<K, V> {
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
|
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -253,7 +248,7 @@ public interface TMap<K, V> {
|
||||||
|
|
||||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
|
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
|
||||||
return CollectionsFactory.createMap(
|
return new TTemplateCollections.NEtriesMap<>(
|
||||||
entry(k1, v1),
|
entry(k1, v1),
|
||||||
entry(k2, v2),
|
entry(k2, v2),
|
||||||
entry(k3, v3),
|
entry(k3, v3),
|
||||||
|
@ -269,10 +264,10 @@ public interface TMap<K, V> {
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
static <K, V> TMap<K, V> ofEntries(TMap.Entry<K, V>... entries) {
|
static <K, V> TMap<K, V> ofEntries(TMap.Entry<K, V>... entries) {
|
||||||
return CollectionsFactory.createMap(entries);
|
return new TTemplateCollections.NEtriesMap<>(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <K, V> TMap.Entry<K, V> entry(K k, V v) {
|
static <K, V> TMap.Entry<K, V> entry(K k, V v) {
|
||||||
return new TMapEntry<>(requireNonNull(k), requireNonNull(v));
|
return new TTemplateCollections.ImmutableEntry<>(requireNonNull(k), requireNonNull(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.util;
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
/**
|
import java.util.Objects;
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
* @param <E>
|
|
||||||
*/
|
|
||||||
public interface TSet<E> extends TCollection<E> {
|
public interface TSet<E> extends TCollection<E> {
|
||||||
|
|
||||||
static <E> TSet<E> of() {
|
static <E> TSet<E> of() {
|
||||||
|
@ -27,48 +24,53 @@ public interface TSet<E> extends TCollection<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e) {
|
static <E> TSet<E> of(E e) {
|
||||||
return CollectionsFactory.createSet(e);
|
Objects.requireNonNull(e);
|
||||||
|
return new TTemplateCollections.SingleElementSet<>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2) {
|
static <E> TSet<E> of(E e1, E e2) {
|
||||||
return CollectionsFactory.createSet(e1, e2);
|
Objects.requireNonNull(e1);
|
||||||
|
Objects.requireNonNull(e2);
|
||||||
|
if (e1.equals(e2)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
return new TTemplateCollections.TwoElementsSet<>(e1, e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3) {
|
static <E> TSet<E> of(E e1, E e2, E e3) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4, e5);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4, e5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4, e5, e6);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4, e5, e6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4, e5, e6, e7);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4, e5, e6, e7);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4, e5, e6, e7, e8);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4, e5, e6, e7, e8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4, e5, e6, e7, e8, e9);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4, e5, e6, e7, e8, e9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
static <E> TSet<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
||||||
return CollectionsFactory.createSet(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
|
return new TTemplateCollections.NElementSet<>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
static <E> TSet<E> of(E... elements) {
|
static <E> TSet<E> of(E... elements) {
|
||||||
return CollectionsFactory.createSet(elements);
|
return new TTemplateCollections.NElementSet<>(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,764 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
class TTemplateCollections {
|
||||||
|
|
||||||
|
private TTemplateCollections() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ImmutableArrayList<T> extends AbstractImmutableList<T> implements RandomAccess {
|
||||||
|
private final T[] list;
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
ImmutableArrayList(T... list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int index) {
|
||||||
|
return list[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return list.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SingleElementList<T> extends AbstractImmutableList<T> implements RandomAccess {
|
||||||
|
private T value;
|
||||||
|
|
||||||
|
SingleElementList(T value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int index) {
|
||||||
|
if (index == 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sort(TComparator<? super T> c) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TwoElementsList<T> extends AbstractImmutableList<T> implements RandomAccess {
|
||||||
|
private T first;
|
||||||
|
private T second;
|
||||||
|
|
||||||
|
TwoElementsList(T first, T second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get(int index) {
|
||||||
|
if (index == 0) {
|
||||||
|
return first;
|
||||||
|
} else if (index == 1) {
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SingleElementSet<T> extends AbstractImmutableSet<T> {
|
||||||
|
private T element;
|
||||||
|
|
||||||
|
SingleElementSet(T element) {
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TIterator<T> iterator() {
|
||||||
|
return new TIterator<T>() {
|
||||||
|
private boolean more = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return more;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (!more) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
more = false;
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return Objects.equals(o, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TwoElementsSet<T> extends AbstractImmutableSet<T> {
|
||||||
|
private T first;
|
||||||
|
private T second;
|
||||||
|
|
||||||
|
TwoElementsSet(T first, T second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return Objects.equals(o, first) || Objects.equals(o, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TIterator<T> iterator() {
|
||||||
|
return new TIterator<T>() {
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return index < 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
switch (index++) {
|
||||||
|
case 0:
|
||||||
|
return first;
|
||||||
|
case 1:
|
||||||
|
return second;
|
||||||
|
default:
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NElementSet<T> extends AbstractImmutableSet<T> {
|
||||||
|
private T[] data;
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
NElementSet(T... data) {
|
||||||
|
T[] table = data.clone();
|
||||||
|
Arrays.fill(table, null);
|
||||||
|
|
||||||
|
for (T element : data) {
|
||||||
|
Objects.requireNonNull(element);
|
||||||
|
|
||||||
|
int suggestedIndex = element.hashCode() % data.length;
|
||||||
|
int index = suggestedIndex;
|
||||||
|
boolean found = false;
|
||||||
|
while (index < data.length) {
|
||||||
|
T existingElement = table[index];
|
||||||
|
if (existingElement == null) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
} else if (existingElement.equals(element)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
index = 0;
|
||||||
|
while (index < suggestedIndex) {
|
||||||
|
T existingElement = table[index];
|
||||||
|
if (existingElement == null) {
|
||||||
|
break;
|
||||||
|
} else if (existingElement.equals(element)) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table[index] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TIterator<T> iterator() {
|
||||||
|
return new TIterator<T>() {
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return index < data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (index >= data.length) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
return data[index++];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
if (data.length == 0 || o == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int suggestedIndex = o.hashCode() % data.length;
|
||||||
|
for (int i = suggestedIndex; i < data.length; ++i) {
|
||||||
|
if (data[i].equals(o)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < suggestedIndex; ++i) {
|
||||||
|
if (data[i].equals(o)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SingleEntryMap<K, V> extends AbstractImmutableMap<K, V> {
|
||||||
|
private Entry<K, V> entry;
|
||||||
|
private AbstractImmutableSet<Entry<K, V>> entrySet;
|
||||||
|
private AbstractImmutableSet<K> keySet;
|
||||||
|
private AbstractImmutableList<V> values;
|
||||||
|
|
||||||
|
SingleEntryMap(K key, V value) {
|
||||||
|
this.entry = new ImmutableEntry<>(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TSet<Entry<K, V>> entrySet() {
|
||||||
|
if (entrySet == null) {
|
||||||
|
entrySet = new SingleElementSet<>(entry);
|
||||||
|
}
|
||||||
|
return entrySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object key) {
|
||||||
|
return entry.getKey().equals(key) ? entry.getValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
return entry.getValue().equals(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
return entry.getKey().equals(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TSet<K> keySet() {
|
||||||
|
if (keySet == null) {
|
||||||
|
keySet = new SingleElementSet<>(entry.getKey());
|
||||||
|
}
|
||||||
|
return keySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TCollection<V> values() {
|
||||||
|
if (values == null) {
|
||||||
|
values = new SingleElementList<>(entry.getValue());
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TwoEntriesMap<K, V> extends AbstractImmutableMap<K, V> {
|
||||||
|
private Entry<K, V> first;
|
||||||
|
private Entry<K, V> second;
|
||||||
|
private AbstractImmutableSet<Entry<K, V>> entrySet;
|
||||||
|
private AbstractImmutableSet<K> keySet;
|
||||||
|
private AbstractImmutableList<V> values;
|
||||||
|
|
||||||
|
TwoEntriesMap(K k1, V v1, K k2, V v2) {
|
||||||
|
this.first = new ImmutableEntry<>(k1, v1);
|
||||||
|
this.second = new ImmutableEntry<>(k2, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TSet<Entry<K, V>> entrySet() {
|
||||||
|
if (entrySet == null) {
|
||||||
|
entrySet = new TwoElementsSet<>(first, second);
|
||||||
|
}
|
||||||
|
return entrySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object key) {
|
||||||
|
return first.getKey().equals(key)
|
||||||
|
? first.getValue()
|
||||||
|
: second.getKey().equals(key) ? second.getValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
return first.getValue().equals(value) || second.getValue().equals(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
return first.getKey().equals(key) || second.getKey().equals(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TSet<K> keySet() {
|
||||||
|
if (keySet == null) {
|
||||||
|
keySet = new TwoElementsSet<>(first.getKey(), second.getKey());
|
||||||
|
}
|
||||||
|
return keySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TCollection<V> values() {
|
||||||
|
if (values == null) {
|
||||||
|
values = new TwoElementsList<>(first.getValue(), second.getValue());
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NEtriesMap<K, V> extends AbstractImmutableMap<K, V> {
|
||||||
|
private Entry<K, V>[] data;
|
||||||
|
private AbstractImmutableSet<Entry<K, V>> entrySet;
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
NEtriesMap(Entry<K, V>... data) {
|
||||||
|
Entry<K, V>[] table = data.clone();
|
||||||
|
Arrays.fill(table, null);
|
||||||
|
|
||||||
|
for (Entry<K, V> entry : data) {
|
||||||
|
Objects.requireNonNull(entry.getKey());
|
||||||
|
Objects.requireNonNull(entry.getValue());
|
||||||
|
|
||||||
|
int suggestedIndex = entry == null ? 0 : entry.getKey().hashCode() % data.length;
|
||||||
|
int index = suggestedIndex;
|
||||||
|
boolean found = false;
|
||||||
|
while (index < data.length) {
|
||||||
|
Entry<K, V> existingEntry = table[index];
|
||||||
|
if (existingEntry == null) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
} else if (existingEntry.getKey().equals(entry.getKey())) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
index = 0;
|
||||||
|
while (index < suggestedIndex) {
|
||||||
|
Entry<K, V> existingElement = table[index];
|
||||||
|
if (existingElement == null) {
|
||||||
|
break;
|
||||||
|
} else if (existingElement.getKey().equals(entry.getKey())) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table[index] = new ImmutableEntry<>(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return data.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Entry<K, V> entry : data) {
|
||||||
|
if (entry.getValue().equals(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
if (key == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int suggestedIndex = key.hashCode() % data.length;
|
||||||
|
for (int i = suggestedIndex; i < data.length; ++i) {
|
||||||
|
if (data[i].getKey().equals(key)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < suggestedIndex; ++i) {
|
||||||
|
if (data[i].getKey().equals(key)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object key) {
|
||||||
|
if (key == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int suggestedIndex = key.hashCode() % data.length;
|
||||||
|
for (int i = suggestedIndex; i < data.length; ++i) {
|
||||||
|
Entry<K, V> entry = data[i];
|
||||||
|
if (entry.getKey().equals(key)) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < suggestedIndex; ++i) {
|
||||||
|
Entry<K, V> entry = data[i];
|
||||||
|
if (entry.getKey().equals(key)) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TSet<Entry<K, V>> entrySet() {
|
||||||
|
if (entrySet == null) {
|
||||||
|
entrySet = new AbstractImmutableSet<Entry<K, V>>() {
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TIterator<Entry<K, V>> iterator() {
|
||||||
|
return new TIterator<Entry<K, V>>() {
|
||||||
|
int index;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return index < data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entry<K, V> next() {
|
||||||
|
if (index == data.length) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
return data[index++];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
if (!(o instanceof Entry)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Entry<?, ?> e = (Entry<?, ?>) o;
|
||||||
|
|
||||||
|
Object key = e.getKey();
|
||||||
|
if (key == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int suggestedIndex = key.hashCode() % data.length;
|
||||||
|
for (int i = suggestedIndex; i < data.length; ++i) {
|
||||||
|
Entry<K, V> entry = data[i];
|
||||||
|
if (entry.getKey().equals(key)) {
|
||||||
|
return entry.getValue().equals(e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < suggestedIndex; ++i) {
|
||||||
|
Entry<K, V> entry = data[i];
|
||||||
|
if (entry.getKey().equals(key)) {
|
||||||
|
return entry.getValue().equals(e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return entrySet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class AbstractImmutableList<T> extends TAbstractList<T> implements RandomAccess {
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T remove(int index) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeRange(int start, int end) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(TCollection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeIf(Predicate<? super T> filter) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(TCollection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class AbstractImmutableSet<T> extends TAbstractSet<T> {
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(TCollection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeIf(Predicate<? super T> filter) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(TCollection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class AbstractImmutableMap<K, V> extends TAbstractMap<K, V> {
|
||||||
|
@Override
|
||||||
|
public V put(K key, V value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(TMap<? extends K, ? extends V> m) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V remove(Object key) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object key, Object value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean replace(K key, V value, V newValue) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V replace(K key, V value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V putIfAbsent(K key, V value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ImmutableEntry<K, V> implements TMap.Entry<K, V>, Cloneable {
|
||||||
|
K key;
|
||||||
|
V value;
|
||||||
|
|
||||||
|
ImmutableEntry(K theKey, V theValue) {
|
||||||
|
key = theKey;
|
||||||
|
value = theValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
try {
|
||||||
|
return super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (object instanceof TMap.Entry) {
|
||||||
|
TMap.Entry<?, ?> entry = (TMap.Entry<?, ?>) object;
|
||||||
|
return (key == null ? entry.getKey() == null : key.equals(entry.getKey()))
|
||||||
|
&& (value == null ? entry.getValue() == null : value
|
||||||
|
.equals(entry.getValue()));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public K getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (key == null ? 0 : key.hashCode())
|
||||||
|
^ (value == null ? 0 : value.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V setValue(V object) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return key + "=" + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,134 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 Alexey Andreev.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.teavm.classlib.java.util;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class CollectionsFactoryTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createList() {
|
|
||||||
assertEquals(
|
|
||||||
TArrays.asList(1, 2, 3),
|
|
||||||
CollectionsFactory.createList(1, 2, 3)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createList_zero_elements() {
|
|
||||||
assertSame(CollectionsFactory.createList(), TCollections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createList_null_element() {
|
|
||||||
CollectionsFactory.createList(new Object[] { null });
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createList_null_array() {
|
|
||||||
CollectionsFactory.createList((Object[]) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createSet() {
|
|
||||||
assertEquals(
|
|
||||||
new THashSet<>(TArrays.asList(1, 2, 3)),
|
|
||||||
CollectionsFactory.createSet(1, 2, 3)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void createSet_duplicate_elements() {
|
|
||||||
CollectionsFactory.createSet(1, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createSet_zero_elements() {
|
|
||||||
assertSame(CollectionsFactory.createSet(), TCollections.emptySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createSet_null_element() {
|
|
||||||
CollectionsFactory.createSet(new Object[] { null });
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createSet_null_array() {
|
|
||||||
CollectionsFactory.createSet((Object[]) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createMap() {
|
|
||||||
final THashMap<Integer, String> hashMap = new THashMap<>();
|
|
||||||
hashMap.put(1, "one");
|
|
||||||
hashMap.put(2, "two");
|
|
||||||
hashMap.put(3, "three");
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
hashMap,
|
|
||||||
CollectionsFactory.createMap(
|
|
||||||
TMap.entry(1, "one"),
|
|
||||||
TMap.entry(2, "two"),
|
|
||||||
TMap.entry(3, "three")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createMap_null_key() {
|
|
||||||
CollectionsFactory.createMap(TMap.entry(null, "value"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void createMap_duplicate_key() {
|
|
||||||
CollectionsFactory.createMap(
|
|
||||||
TMap.entry(1, "value"),
|
|
||||||
TMap.entry(1, "another value")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createMap_null_value() {
|
|
||||||
CollectionsFactory.createMap(TMap.entry("key", null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createMap_duplicate_value() {
|
|
||||||
final THashMap<Integer, String> hashMap = new THashMap<>();
|
|
||||||
hashMap.put(1, "value");
|
|
||||||
hashMap.put(2, "value");
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
hashMap,
|
|
||||||
CollectionsFactory.createMap(
|
|
||||||
TMap.entry(1, "value"),
|
|
||||||
TMap.entry(2, "value")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createMap_zero_elements() {
|
|
||||||
assertSame(CollectionsFactory.createMap(), TCollections.emptyMap());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
|
||||||
public void createMap_null_array() {
|
|
||||||
CollectionsFactory.createMap((TMap.Entry<Object, Object>[]) null);
|
|
||||||
}
|
|
||||||
}
|
|
114
tests/src/test/java/org/teavm/classlib/java/util/ListTest.java
Normal file
114
tests/src/test/java/org/teavm/classlib/java/util/ListTest.java
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 konsoletyper.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
import org.teavm.junit.WholeClassCompilation;
|
||||||
|
|
||||||
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@WholeClassCompilation
|
||||||
|
public class ListTest {
|
||||||
|
@Test
|
||||||
|
public void of() {
|
||||||
|
testOf(new String[0], List.of());
|
||||||
|
testOf(new String[] { "q" }, List.of("q"));
|
||||||
|
testOf(new String[] { "q", "w" }, List.of("q", "w"));
|
||||||
|
testOf(new String[] { "q", "w", "e" }, List.of("q", "w", "e"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r" }, List.of("q", "w", "e", "r"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t" }, List.of("q", "w", "e", "r", "t"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y" }, List.of("q", "w", "e", "r", "t", "y"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u" }, List.of("q", "w", "e", "r", "t", "y", "u"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i" },
|
||||||
|
List.of("q", "w", "e", "r", "t", "y", "u", "i"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o" },
|
||||||
|
List.of("q", "w", "e", "r", "t", "y", "u", "i", "o"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p" },
|
||||||
|
List.of("q", "w", "e", "r", "t", "y", "u", "i", "o", "p"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a" },
|
||||||
|
List.of("q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testOf(String[] expected, List<String> actual) {
|
||||||
|
if (actual.size() != expected.length) {
|
||||||
|
fail("Expected size is " + expected.length + ", actual size is " + actual.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < expected.length; ++i) {
|
||||||
|
assertEquals("Element #" + i, expected[i], actual.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.get(-1);
|
||||||
|
fail("get out of bounds does not throw exception");
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.get(expected.length);
|
||||||
|
fail("get out of bounds does not throw exception");
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.set(0, "1");
|
||||||
|
fail("set should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.remove(0);
|
||||||
|
fail("remove should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.add("2");
|
||||||
|
fail("add should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.clear();
|
||||||
|
fail("clear should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < expected.length; ++i) {
|
||||||
|
assertEquals("indexOf of element #" + i + " is correct", i, actual.indexOf(expected[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String value : expected) {
|
||||||
|
assertTrue("contains returns true for existing elements", actual.contains(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse("contains return false for non-existing element", actual.contains("*"));
|
||||||
|
|
||||||
|
assertEquals("isEmpty works properly", expected.length == 0, actual.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
125
tests/src/test/java/org/teavm/classlib/java/util/MapTest.java
Normal file
125
tests/src/test/java/org/teavm/classlib/java/util/MapTest.java
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 konsoletyper.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
import org.teavm.junit.WholeClassCompilation;
|
||||||
|
|
||||||
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@WholeClassCompilation
|
||||||
|
public class MapTest {
|
||||||
|
@Test
|
||||||
|
public void of() {
|
||||||
|
testOf(new String[0], Map.of());
|
||||||
|
testOf(new String[] { "q" }, Map.of("q", 0));
|
||||||
|
testOf(new String[] { "q", "w" }, Map.of("q", 0, "w", 1));
|
||||||
|
testOf(new String[] { "q", "w", "e" }, Map.of("q", 0, "w", 1, "e", 2));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r" }, Map.of("q", 0, "w", 1, "e", 2, "r", 3));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t" }, Map.of("q", 0, "w", 1, "e", 2, "r", 3, "t", 4));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y" }, Map.of("q", 0, "w", 1, "e", 2, "r", 3, "t", 4, "y", 5));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u" },
|
||||||
|
Map.of("q", 0, "w", 1, "e", 2, "r", 3, "t", 4, "y", 5, "u", 6));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i" },
|
||||||
|
Map.of("q", 0, "w", 1, "e", 2, "r", 3, "t", 4, "y", 5, "u", 6, "i", 7));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o" },
|
||||||
|
Map.of("q", 0, "w", 1, "e", 2, "r", 3, "t", 4, "y", 5, "u", 6, "i", 7, "o", 8));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p" },
|
||||||
|
Map.of("q", 0, "w", 1, "e", 2, "r", 3, "t", 4, "y", 5, "u", 6, "i", 7, "o", 8, "p", 9));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a" },
|
||||||
|
Map.ofEntries(Map.entry("q", 0), Map.entry("w", 1), Map.entry("e", 2), Map.entry("r", 3),
|
||||||
|
Map.entry("t", 4), Map.entry("y", 5), Map.entry("u", 6), Map.entry("i", 7), Map.entry("o", 8),
|
||||||
|
Map.entry("p", 9), Map.entry("a", 10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testOf(String[] expected, Map<String, Integer> actual) {
|
||||||
|
if (actual.size() != expected.length) {
|
||||||
|
fail("Expected size is " + expected.length + ", actual size is " + actual.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.remove("*");
|
||||||
|
fail("remove should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.put("*", -1);
|
||||||
|
fail("add should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.clear();
|
||||||
|
fail("clear should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < expected.length; i++) {
|
||||||
|
String key = expected[i];
|
||||||
|
assertTrue("containsKey returns true for existing elements", actual.containsKey(key));
|
||||||
|
assertTrue("containsValue returns true for existing elements", actual.containsValue(i));
|
||||||
|
assertTrue("contains returns true for existing elements", actual.entrySet().contains(Map.entry(key, i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse("containsKey return false for non-existing element", actual.containsKey("*"));
|
||||||
|
assertFalse("containsValue return false for non-existing element", actual.containsValue(-1));
|
||||||
|
for (String key : expected) {
|
||||||
|
assertFalse("contains return false for non-existing element",
|
||||||
|
actual.entrySet().contains(Map.entry(key, -1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("isEmpty works properly", expected.length == 0, actual.isEmpty());
|
||||||
|
|
||||||
|
String[] expectedCopy = expected.clone();
|
||||||
|
for (Map.Entry<String, Integer> entry : actual.entrySet()) {
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < expectedCopy.length; ++i) {
|
||||||
|
if (entry.getKey().equals(expectedCopy[i])) {
|
||||||
|
assertEquals("Strange value of entry.getValue()", (Object) i, entry.getValue());
|
||||||
|
expectedCopy[i] = null;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue("iterator returned strange value", found);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, Integer> entry : actual.entrySet()) {
|
||||||
|
try {
|
||||||
|
entry.setValue(-1);
|
||||||
|
fail("Entries should be immutable");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String e : expectedCopy) {
|
||||||
|
assertNull("Iterator did not return all of expected elements", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
124
tests/src/test/java/org/teavm/classlib/java/util/SetTest.java
Normal file
124
tests/src/test/java/org/teavm/classlib/java/util/SetTest.java
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 konsoletyper.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
import org.teavm.junit.WholeClassCompilation;
|
||||||
|
|
||||||
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@WholeClassCompilation
|
||||||
|
public class SetTest {
|
||||||
|
@Test
|
||||||
|
public void of() {
|
||||||
|
testOf(new String[0], Set.of());
|
||||||
|
testOf(new String[] { "q" }, Set.of("q"));
|
||||||
|
testOf(new String[] { "q", "w" }, Set.of("q", "w"));
|
||||||
|
testOf(new String[] { "q", "w", "e" }, Set.of("q", "w", "e"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r" }, Set.of("q", "w", "e", "r"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t" }, Set.of("q", "w", "e", "r", "t"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y" }, Set.of("q", "w", "e", "r", "t", "y"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u" }, Set.of("q", "w", "e", "r", "t", "y", "u"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i" },
|
||||||
|
Set.of("q", "w", "e", "r", "t", "y", "u", "i"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o" },
|
||||||
|
Set.of("q", "w", "e", "r", "t", "y", "u", "i", "o"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p" },
|
||||||
|
Set.of("q", "w", "e", "r", "t", "y", "u", "i", "o", "p"));
|
||||||
|
testOf(new String[] { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a" },
|
||||||
|
Set.of("q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a"));
|
||||||
|
|
||||||
|
expectIAE(() -> Set.of("q", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "t", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "t", "y", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "t", "y", "u", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "t", "y", "u", "i", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "t", "y", "u", "i", "o", "q"));
|
||||||
|
expectIAE(() -> Set.of("q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "q"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectIAE(Runnable r) {
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
fail("Expected IllegalArgumentException");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testOf(String[] expected, Set<String> actual) {
|
||||||
|
if (actual.size() != expected.length) {
|
||||||
|
fail("Expected size is " + expected.length + ", actual size is " + actual.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.remove("*");
|
||||||
|
fail("remove should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.add("2");
|
||||||
|
fail("add should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
actual.clear();
|
||||||
|
fail("clear should not work");
|
||||||
|
} catch (UnsupportedOperationException e) {
|
||||||
|
// ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String value : expected) {
|
||||||
|
assertTrue("contains returns true for existing elements", actual.contains(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse("contains return false for non-existing element", actual.contains("*"));
|
||||||
|
|
||||||
|
assertEquals("isEmpty works properly", expected.length == 0, actual.isEmpty());
|
||||||
|
|
||||||
|
String[] expectedCopy = expected.clone();
|
||||||
|
for (String elem : actual) {
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < expectedCopy.length; ++i) {
|
||||||
|
if (elem.equals(expectedCopy[i])) {
|
||||||
|
expectedCopy[i] = null;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue("iterator returned strange value", found);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String e : expectedCopy) {
|
||||||
|
assertNull("Iterator did not return all of expected elements", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user