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
|
||||
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
|
||||
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 {
|
||||
@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() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class TCollections extends TObject {
|
|||
};
|
||||
|
||||
@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() {
|
||||
return emptySet();
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class TCollections extends TObject {
|
|||
};
|
||||
|
||||
@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) {
|
||||
throw new TIndexOutOfBoundsException();
|
||||
}
|
||||
|
@ -164,47 +164,12 @@ public class TCollections extends TObject {
|
|||
return (TMap<K, V>) EMPTY_MAP;
|
||||
}
|
||||
|
||||
public static <T> TList<T> singletonList(final T o) {
|
||||
return new TAbstractList<T>() {
|
||||
@Override public T get(int index) {
|
||||
if (index != 0) {
|
||||
throw new TIndexOutOfBoundsException();
|
||||
}
|
||||
return o;
|
||||
}
|
||||
@Override public int size() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
public static <T> TList<T> singletonList(T o) {
|
||||
return new TTemplateCollections.SingleElementList<>(o);
|
||||
}
|
||||
|
||||
public static <T> TSet<T> singleton(final T o) {
|
||||
return new TAbstractSet<T>() {
|
||||
@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 <T> TSet<T> singleton(T o) {
|
||||
return new TTemplateCollections.SingleElementSet<>(o);
|
||||
}
|
||||
|
||||
public static <K, V> TMap<K, V> singletonMap(final K key, final V value) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import org.teavm.classlib.java.util.function.TUnaryOperator;
|
||||
|
||||
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) {
|
||||
return CollectionsFactory.createList(e);
|
||||
return TCollections.singletonList(e);
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
static <E> TList<E> of(E... elements) {
|
||||
// the returned list reuses the given array
|
||||
// create a copy to prevent modifying the list by modifying the original array
|
||||
return CollectionsFactory.createList(Arrays.copyOf(elements, elements.length));
|
||||
for (E element : elements) {
|
||||
Objects.requireNonNull(element);
|
||||
}
|
||||
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) {
|
||||
return CollectionsFactory.createMap(
|
||||
entry(k1, v1)
|
||||
);
|
||||
return new TTemplateCollections.SingleEntryMap<>(k1, v1);
|
||||
}
|
||||
|
||||
static <K, V> TMap<K, V> of(K k1, V v1, K k2, V v2) {
|
||||
return CollectionsFactory.createMap(
|
||||
entry(k1, v1),
|
||||
entry(k2, v2)
|
||||
);
|
||||
return new TTemplateCollections.TwoEntriesMap<>(k1, v1, k2, v2);
|
||||
}
|
||||
|
||||
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(k2, v2),
|
||||
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) {
|
||||
return CollectionsFactory.createMap(
|
||||
return new TTemplateCollections.NEtriesMap<>(
|
||||
entry(k1, v1),
|
||||
entry(k2, v2),
|
||||
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) {
|
||||
return CollectionsFactory.createMap(
|
||||
return new TTemplateCollections.NEtriesMap<>(
|
||||
entry(k1, v1),
|
||||
entry(k2, v2),
|
||||
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) {
|
||||
return CollectionsFactory.createMap(
|
||||
return new TTemplateCollections.NEtriesMap<>(
|
||||
entry(k1, v1),
|
||||
entry(k2, v2),
|
||||
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,
|
||||
K k6, V v6, K k7, V v7) {
|
||||
return CollectionsFactory.createMap(
|
||||
return new TTemplateCollections.NEtriesMap<>(
|
||||
entry(k1, v1),
|
||||
entry(k2, v2),
|
||||
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,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8) {
|
||||
return CollectionsFactory.createMap(
|
||||
return new TTemplateCollections.NEtriesMap<>(
|
||||
entry(k1, v1),
|
||||
entry(k2, v2),
|
||||
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,
|
||||
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(k2, v2),
|
||||
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,
|
||||
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(k2, v2),
|
||||
entry(k3, v3),
|
||||
|
@ -269,10 +264,10 @@ public interface TMap<K, V> {
|
|||
|
||||
@SafeVarargs
|
||||
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) {
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
* @param <E>
|
||||
*/
|
||||
import java.util.Objects;
|
||||
|
||||
public interface TSet<E> extends TCollection<E> {
|
||||
|
||||
static <E> TSet<E> of() {
|
||||
|
@ -27,48 +24,53 @@ public interface TSet<E> extends TCollection<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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
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