mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
parent
05454380d9
commit
bcc2c0ff35
|
@ -292,7 +292,7 @@ public abstract class TAbstractMap<K, V> extends TObject implements TMap<K, V> {
|
|||
private class KeySet extends TAbstractSet<K> {
|
||||
@Override
|
||||
public TIterator<K> iterator() {
|
||||
final TIterator<TMap.Entry<K, V>> it = TAbstractMap.this.entrySet().iterator();
|
||||
final TIterator<TMap.Entry<K, V>> it = entrySet().iterator();
|
||||
return new TIterator<>() {
|
||||
@Override public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
|
@ -320,16 +320,16 @@ public abstract class TAbstractMap<K, V> extends TObject implements TMap<K, V> {
|
|||
|
||||
@Override
|
||||
public TIterator<V> iterator() {
|
||||
final TIterator<TMap.Entry<K, V>> iter = TAbstractMap.this.entrySet().iterator();
|
||||
return new TIterator<V>() {
|
||||
final TIterator<TMap.Entry<K, V>> it = entrySet().iterator();
|
||||
return new TIterator<>() {
|
||||
@Override public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
return it.hasNext();
|
||||
}
|
||||
@Override public V next() {
|
||||
return iter.next().getValue();
|
||||
return it.next().getValue();
|
||||
}
|
||||
@Override public void remove() {
|
||||
iter.remove();
|
||||
it.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.function.Predicate;
|
||||
import org.teavm.classlib.java.lang.TIterable;
|
||||
|
@ -59,7 +58,7 @@ public interface TCollection<E> extends TIterable<E> {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
default TStream<E> stream() {
|
||||
return new TStreamOverSpliterator<>((Spliterator<E>) spliterator());
|
||||
return new TStreamOverSpliterator<>(spliterator());
|
||||
}
|
||||
|
||||
default boolean removeIf(Predicate<? super E> filter) {
|
||||
|
|
|
@ -57,4 +57,14 @@ public interface TNavigableMap<K, V> extends TSortedMap<K, V> {
|
|||
TNavigableMap<K, V> headMap(K toKey, boolean inclusive);
|
||||
|
||||
TNavigableMap<K, V> tailMap(K fromKey, boolean inclusive);
|
||||
|
||||
@Override
|
||||
default TSequencedSet<K> sequencedKeySet() {
|
||||
return navigableKeySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
default TNavigableMap<K, V> reversed() {
|
||||
return descendingMap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,4 +42,27 @@ public interface TNavigableSet<E> extends TSortedSet<E> {
|
|||
TNavigableSet<E> headSet(E toElement, boolean inclusive);
|
||||
|
||||
TNavigableSet<E> tailSet(E fromElement, boolean inclusive);
|
||||
|
||||
@Override
|
||||
default E removeFirst() {
|
||||
if (isEmpty()) {
|
||||
throw new TNoSuchElementException();
|
||||
} else {
|
||||
return pollFirst();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default E removeLast() {
|
||||
if (isEmpty()) {
|
||||
throw new TNoSuchElementException();
|
||||
} else {
|
||||
return pollLast();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default TNavigableSet<E> reversed() {
|
||||
return descendingSet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* Copyright 2023 ihromant.
|
||||
*
|
||||
* 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;
|
||||
|
||||
class TReversedSortedSet<E> extends TAbstractSet<E> implements TSortedSet<E> {
|
||||
private final TSortedSet<E> base;
|
||||
|
||||
TReversedSortedSet(TSortedSet<E> base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIterator<E> iterator() {
|
||||
return new DescendingSortedSetIterator<>(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
base.add(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(TCollection<? extends E> c) {
|
||||
return base.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
base.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return base.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(TCollection<?> c) {
|
||||
return base.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return base.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return base.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeFirst() {
|
||||
return base.removeLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E removeLast() {
|
||||
return base.removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(TCollection<?> c) {
|
||||
return base.removeAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(TCollection<?> c) {
|
||||
return base.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return base.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TComparator<? super E> comparator() {
|
||||
TComparator<? super E> comp = base.comparator();
|
||||
return comp != null ? comp.reversed() : TCollections.reverseOrder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E first() {
|
||||
return base.last();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E last() {
|
||||
return base.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getFirst() {
|
||||
return base.last();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E getLast() {
|
||||
return base.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSortedSet<E> headSet(E to) {
|
||||
return new DescSubset<>(base, null, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSortedSet<E> subSet(E from, E to) {
|
||||
return new DescSubset<>(base, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSortedSet<E> tailSet(E from) {
|
||||
return new DescSubset<>(base, from, null);
|
||||
}
|
||||
|
||||
static class DescSubset<E> extends TAbstractSet<E> implements TSortedSet<E> {
|
||||
final TSortedSet<E> base;
|
||||
final E head;
|
||||
final E tail;
|
||||
private final TComparator<E> reversed;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DescSubset(TSortedSet<E> base, E head, E tail) {
|
||||
this.base = base;
|
||||
this.head = head;
|
||||
this.tail = tail;
|
||||
this.reversed = (TComparator<E>) TCollections.reverseOrder(base.comparator());
|
||||
}
|
||||
|
||||
private boolean aboveHeadInc(E e) {
|
||||
return head == null || reversed.compare(e, head) >= 0;
|
||||
}
|
||||
|
||||
private boolean belowTailExc(E e) {
|
||||
return tail == null || reversed.compare(e, tail) < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIterator<E> iterator() {
|
||||
return new TIterator<>() {
|
||||
private final TIterator<E> it = new DescendingSortedSetIterator<>(base);
|
||||
private E current;
|
||||
private boolean finished;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (finished) {
|
||||
return false;
|
||||
}
|
||||
if (current != null) {
|
||||
return true;
|
||||
}
|
||||
while (it.hasNext()) {
|
||||
E e = it.next();
|
||||
if (!aboveHeadInc(e)) {
|
||||
continue;
|
||||
}
|
||||
if (!belowTailExc(e)) {
|
||||
finished = true;
|
||||
return false;
|
||||
}
|
||||
current = e;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (hasNext()) {
|
||||
E e = current;
|
||||
current = null;
|
||||
return e;
|
||||
} else {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
if (aboveHeadInc(e) && belowTailExc(e)) {
|
||||
return base.add(e);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
E e = (E) o;
|
||||
if (aboveHeadInc(e) && belowTailExc(e)) {
|
||||
return base.remove(o);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int size = 0;
|
||||
for (var it = iterator(); it.hasNext(); it.next()) {
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TComparator<? super E> comparator() {
|
||||
TComparator<? super E> comp = base.comparator();
|
||||
return comp != null ? comp.reversed() : TCollections.reverseOrder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E first() {
|
||||
return iterator().next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E last() {
|
||||
TIterator<E> it = iterator();
|
||||
if (!it.hasNext()) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
E last = it.next();
|
||||
while (it.hasNext()) {
|
||||
last = it.next();
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSortedSet<E> subSet(E from, E to) {
|
||||
if (aboveHeadInc(from) && belowTailExc(from)
|
||||
&& aboveHeadInc(to) && belowTailExc(to)
|
||||
&& reversed.compare(from, to) <= 0) {
|
||||
return new DescSubset<>(base, from, to);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSortedSet<E> headSet(E to) {
|
||||
if (aboveHeadInc(to) && belowTailExc(to)) {
|
||||
return new DescSubset<>(base, head, to);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSortedSet<E> tailSet(E from) {
|
||||
if (aboveHeadInc(from) && belowTailExc(from)) {
|
||||
return new DescSubset<>(base, null, tail);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DescendingSortedSetIterator<E> implements TIterator<E> {
|
||||
private final TSortedSet<E> base;
|
||||
private TSortedSet<E> remaining;
|
||||
private E current;
|
||||
|
||||
private DescendingSortedSetIterator(TSortedSet<E> base) {
|
||||
this.base = base;
|
||||
this.remaining = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !remaining.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
if (remaining.isEmpty()) {
|
||||
throw new TNoSuchElementException();
|
||||
}
|
||||
current = remaining.last();
|
||||
remaining = base.headSet(current);
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (current == null) {
|
||||
throw new IllegalStateException();
|
||||
} else {
|
||||
base.remove(current);
|
||||
current = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ package org.teavm.classlib.java.util;
|
|||
* @param <K>
|
||||
* @param <V>
|
||||
*/
|
||||
public interface TSortedMap<K, V> extends TMap<K, V> {
|
||||
public interface TSortedMap<K, V> extends TSequencedMap<K, V> {
|
||||
TComparator<? super K> comparator();
|
||||
|
||||
TSortedMap<K, V> subMap(K fromKey, K toKey);
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.teavm.classlib.java.util;
|
|||
* @author Alexey Andreev
|
||||
* @param <E>
|
||||
*/
|
||||
public interface TSortedSet<E> extends TSet<E> {
|
||||
public interface TSortedSet<E> extends TSet<E>, TSequencedSet<E> {
|
||||
TComparator<? super E> comparator();
|
||||
|
||||
TSortedSet<E> subSet(E fromElement, E toElement);
|
||||
|
@ -32,4 +32,33 @@ public interface TSortedSet<E> extends TSet<E> {
|
|||
E first();
|
||||
|
||||
E last();
|
||||
|
||||
@Override
|
||||
default E getFirst() {
|
||||
return first();
|
||||
}
|
||||
|
||||
@Override
|
||||
default E getLast() {
|
||||
return last();
|
||||
}
|
||||
|
||||
@Override
|
||||
default E removeFirst() {
|
||||
E e = this.first();
|
||||
this.remove(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
default E removeLast() {
|
||||
E e = this.last();
|
||||
this.remove(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
default TSortedSet<E> reversed() {
|
||||
return new TReversedSortedSet<>(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -364,10 +364,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
|
||||
@Override
|
||||
public TSet<Entry<K, V>> entrySet() {
|
||||
if (cachedEntrySet == null) {
|
||||
cachedEntrySet = new EntrySet<>(this, null, true, false, null, true, false, false);
|
||||
}
|
||||
return cachedEntrySet;
|
||||
return sequencedEntrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -469,7 +466,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
public Entry<K, V> pollFirstEntry() {
|
||||
TreeNode<K, V> node = firstNode(false);
|
||||
if (node != null) {
|
||||
root = deleteNode(root, node.getKey());
|
||||
remove(node.getKey());
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
@ -478,11 +475,32 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
public Entry<K, V> pollLastEntry() {
|
||||
TreeNode<K, V> node = firstNode(true);
|
||||
if (node != null) {
|
||||
root = deleteNode(root, node.getKey());
|
||||
remove(node.getKey());
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TCollection<V> values() {
|
||||
return sequencedValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSequencedCollection<V> sequencedValues() {
|
||||
if (cachedValues == null) {
|
||||
cachedValues = new NavigableMapValues<>(this);
|
||||
}
|
||||
return (TSequencedCollection<V>) cachedValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSequencedSet<Entry<K, V>> sequencedEntrySet() {
|
||||
if (cachedEntrySet == null) {
|
||||
cachedEntrySet = new EntrySet<>(this, null, true, false, null, true, false, false);
|
||||
}
|
||||
return cachedEntrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TNavigableMap<K, V> descendingMap() {
|
||||
return new MapView<>(this, null, false, false, null, false, false, true);
|
||||
|
@ -542,7 +560,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
return copy;
|
||||
}
|
||||
|
||||
static class EntrySet<K, V> extends TAbstractSet<Entry<K, V>> {
|
||||
static class EntrySet<K, V> extends TAbstractSet<Entry<K, V>> implements TSequencedSet<Entry<K, V>> {
|
||||
private int modCount = -1;
|
||||
private TTreeMap<K, V> owner;
|
||||
private K from;
|
||||
|
@ -619,7 +637,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
} else {
|
||||
toPath = owner.pathToFirst(true);
|
||||
}
|
||||
return new EntryIterator<>(owner, toPath, from, fromIncluded, fromChecked, true);
|
||||
return new EntryIterator<>(owner, toPath, from, fromChecked, fromIncluded, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -651,6 +669,11 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSequencedSet<Entry<K, V>> reversed() {
|
||||
return new EntrySet<>(owner, from, fromIncluded, fromChecked, to, toIncluded, toChecked, !reverse);
|
||||
}
|
||||
}
|
||||
|
||||
static class EntryIterator<K, V> implements TIterator<Entry<K, V>> {
|
||||
|
@ -772,11 +795,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
|
||||
@Override
|
||||
public TSet<Entry<K, V>> entrySet() {
|
||||
if (entrySetCache == null) {
|
||||
entrySetCache = new EntrySet<>(owner, from, fromIncluded,
|
||||
fromChecked, to, toIncluded, toChecked, reverse);
|
||||
}
|
||||
return entrySetCache;
|
||||
return sequencedEntrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1021,7 +1040,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
public Entry<K, V> pollFirstEntry() {
|
||||
TreeNode<K, V> node = !reverse ? firstNode() : lastNode();
|
||||
if (node != null) {
|
||||
owner.deleteNode(owner.root, node.getKey());
|
||||
owner.remove(node.getKey());
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
@ -1030,11 +1049,33 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
public Entry<K, V> pollLastEntry() {
|
||||
TreeNode<K, V> node = !reverse ? lastNode() : firstNode();
|
||||
if (node != null) {
|
||||
owner.deleteNode(owner.root, node.getKey());
|
||||
owner.remove(node.getKey());
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TCollection<V> values() {
|
||||
return sequencedValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSequencedCollection<V> sequencedValues() {
|
||||
if (cachedValues == null) {
|
||||
cachedValues = new NavigableMapValues<>(this);
|
||||
}
|
||||
return (TSequencedCollection<V>) cachedValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSequencedSet<Entry<K, V>> sequencedEntrySet() {
|
||||
if (entrySetCache == null) {
|
||||
entrySetCache = new EntrySet<>(owner, from, fromIncluded,
|
||||
fromChecked, to, toIncluded, toChecked, reverse);
|
||||
}
|
||||
return entrySetCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TNavigableMap<K, V> descendingMap() {
|
||||
return new MapView<>(owner, from, fromIncluded, fromChecked, to, toIncluded, toChecked, !reverse);
|
||||
|
@ -1086,13 +1127,13 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
if (!reverse) {
|
||||
return new MapView<>(owner, fromKey, inclusive, true, to, toIncluded, toChecked, false);
|
||||
} else {
|
||||
return new MapView<>(owner, from, fromIncluded, toChecked, fromKey, inclusive, true, true);
|
||||
return new MapView<>(owner, from, fromIncluded, fromChecked, fromKey, inclusive, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class NavigableKeySet<K, V> extends TAbstractSet<K> implements TNavigableSet<K> {
|
||||
private TNavigableMap<K, V> map;
|
||||
private final TNavigableMap<K, V> map;
|
||||
|
||||
NavigableKeySet(TNavigableMap<K, V> map) {
|
||||
this.map = map;
|
||||
|
@ -1115,7 +1156,7 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
|
||||
@Override
|
||||
public TSortedSet<K> tailSet(K fromElement) {
|
||||
return map.headMap(fromElement, true).navigableKeySet();
|
||||
return map.tailMap(fromElement, true).navigableKeySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1192,7 +1233,41 @@ public class TTreeMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
|
|||
|
||||
@Override
|
||||
public TNavigableSet<K> tailSet(K fromElement, boolean inclusive) {
|
||||
return map.headMap(fromElement, inclusive).navigableKeySet();
|
||||
return map.tailMap(fromElement, inclusive).navigableKeySet();
|
||||
}
|
||||
}
|
||||
|
||||
static class NavigableMapValues<K, V> extends TAbstractCollection<V> implements TSequencedCollection<V> {
|
||||
private final TNavigableMap<K, V> map;
|
||||
|
||||
NavigableMapValues(TNavigableMap<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIterator<V> iterator() {
|
||||
final TIterator<TMap.Entry<K, V>> it = map.entrySet().iterator();
|
||||
return new TIterator<>() {
|
||||
@Override public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
@Override public V next() {
|
||||
return it.next().getValue();
|
||||
}
|
||||
@Override public void remove() {
|
||||
it.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSequencedCollection<V> reversed() {
|
||||
return new NavigableMapValues<>(map.reversed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.classlib.java.util.stream;
|
|||
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Supplier;
|
||||
import org.teavm.classlib.java.util.TSpliterator;
|
||||
import org.teavm.classlib.java.util.stream.impl.TStreamOverSpliterator;
|
||||
import org.teavm.classlib.java.util.stream.impl.TStreamOverSpliteratorSupplier;
|
||||
|
||||
|
@ -24,7 +25,7 @@ public final class TStreamSupport {
|
|||
private TStreamSupport() {
|
||||
}
|
||||
|
||||
public static <T> TStream<T> stream(Spliterator<T> spliterator, boolean parallel) {
|
||||
public static <T> TStream<T> stream(TSpliterator<T> spliterator, boolean parallel) {
|
||||
return new TStreamOverSpliterator<>(spliterator);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,12 @@ package org.teavm.classlib.java.util.stream.impl;
|
|||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import org.teavm.classlib.java.util.TSpliterator;
|
||||
|
||||
public class TStreamOverSpliterator<T> extends TSimpleStreamImpl<T> {
|
||||
private Spliterator<T> spliterator;
|
||||
private TSpliterator<T> spliterator;
|
||||
|
||||
public TStreamOverSpliterator(Spliterator<T> spliterator) {
|
||||
public TStreamOverSpliterator(TSpliterator<T> spliterator) {
|
||||
this.spliterator = spliterator;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
|
@ -55,15 +56,21 @@ import static org.junit.Assert.assertSame;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.SequencedMap;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
|
@ -728,4 +735,124 @@ public class TreeMapTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final List<Integer> BASE_LIST = Arrays.asList(1, 6, 2, 5, 3, 4);
|
||||
|
||||
private SequencedMap<Integer, String> generateMap() {
|
||||
return BASE_LIST.stream().collect(Collectors.toMap(Function.identity(), i -> Integer.toString(i),
|
||||
(a, b) -> a, TreeMap::new));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequencedMap() {
|
||||
SequencedMap<Integer, String> map = generateMap();
|
||||
assertEquals(Map.entry(1, "1"), map.pollFirstEntry());
|
||||
assertArrayEquals(new Integer[] { 2, 3, 4, 5, 6 }, map.keySet().toArray(new Integer[0]));
|
||||
assertEquals(Map.entry(6, "6"), map.pollLastEntry());
|
||||
assertArrayEquals(new Integer[] { 2, 3, 4, 5 }, map.keySet().toArray(new Integer[0]));
|
||||
assertEquals(Map.entry(5, "5"), map.pollLastEntry());
|
||||
assertArrayEquals(new Integer[] { 2, 3, 4 }, map.keySet().toArray(new Integer[0]));
|
||||
assertEquals(Map.entry(2, "2"), map.firstEntry());
|
||||
assertEquals(Map.entry(4, "4"), map.lastEntry());
|
||||
try {
|
||||
map.putFirst(1, "1");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
map.put(7, "7");
|
||||
try {
|
||||
map.putLast(3, "3");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
assertArrayEquals(new Integer[] { 2, 3, 4, 7 }, map.keySet().toArray(new Integer[0]));
|
||||
map = generateMap().reversed();
|
||||
assertEquals(Map.entry(6, "6"), map.pollFirstEntry());
|
||||
assertArrayEquals(new Integer[] { 5, 4, 3, 2, 1 }, map.keySet().toArray(new Integer[0]));
|
||||
assertEquals(Map.entry(1, "1"), map.pollLastEntry());
|
||||
assertArrayEquals(new Integer[] { 5, 4, 3, 2 }, map.keySet().toArray(new Integer[0]));
|
||||
assertEquals(Map.entry(2, "2"), map.pollLastEntry());
|
||||
assertArrayEquals(new Integer[] { 5, 4, 3 }, map.keySet().toArray(new Integer[0]));
|
||||
assertEquals(Map.entry(5, "5"), map.firstEntry());
|
||||
assertEquals(Map.entry(3, "3"), map.lastEntry());
|
||||
try {
|
||||
map.putFirst(1, "1");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
map.put(7, "7");
|
||||
try {
|
||||
map.putLast(6, "6");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
assertArrayEquals(new Integer[] { 7, 5, 4, 3 }, map.keySet().toArray(new Integer[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequencedIterators() {
|
||||
SequencedMap<Integer, String> map = generateMap();
|
||||
Iterator<Integer> it = map.keySet().iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(1, it.next().intValue());
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(2, it.next().intValue());
|
||||
it.remove();
|
||||
assertArrayEquals(new Integer[] { 1, 3, 4, 5, 6 }, map.keySet().toArray(new Integer[0]));
|
||||
map = map.reversed();
|
||||
it = map.keySet().iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(6, it.next().intValue());
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(5, it.next().intValue());
|
||||
it.remove();
|
||||
assertArrayEquals(new Integer[] { 6, 4, 3, 1 }, map.keySet().toArray(new Integer[0]));
|
||||
map = generateMap();
|
||||
Iterator<String> sit = map.sequencedValues().iterator();
|
||||
assertTrue(sit.hasNext());
|
||||
assertEquals("1", sit.next());
|
||||
assertTrue(sit.hasNext());
|
||||
assertEquals("2", sit.next());
|
||||
sit.remove();
|
||||
assertArrayEquals(new String[] { "1", "3", "4", "5", "6" }, map.values().toArray(new String[0]));
|
||||
map = map.reversed();
|
||||
sit = map.sequencedValues().iterator();
|
||||
assertTrue(sit.hasNext());
|
||||
assertEquals("6", sit.next());
|
||||
assertTrue(sit.hasNext());
|
||||
assertEquals("5", sit.next());
|
||||
sit.remove();
|
||||
assertArrayEquals(new String[] { "6", "4", "3", "1" }, map.values().toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
var empty = new TreeMap<>();
|
||||
assertNull(empty.pollFirstEntry());
|
||||
assertNull(empty.pollLastEntry());
|
||||
assertNull(empty.firstEntry());
|
||||
assertNull(empty.lastEntry());
|
||||
try {
|
||||
empty.entrySet().iterator().next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
empty.keySet().iterator().next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
empty.values().iterator().next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright 2023 ihromant.
|
||||
*
|
||||
* 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.assertArrayEquals;
|
||||
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.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
public class TreeSetTest {
|
||||
@Test
|
||||
public void testSortedSetReadOnly() {
|
||||
SortedSet<String> set = new TreeSet<>(List.of("1", "2", "3", "4", "5", "6"));
|
||||
SortedSet<String> reversed = set.reversed();
|
||||
Iterator<String> it = reversed.iterator();
|
||||
assertEquals("6", it.next());
|
||||
assertEquals("5", it.next());
|
||||
assertEquals("6", reversed.getFirst());
|
||||
assertEquals("1", reversed.getLast());
|
||||
SortedSet<String> subset = reversed.subSet("3", "1");
|
||||
it = subset.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("3", it.next());
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("2", it.next());
|
||||
try {
|
||||
assertFalse(it.hasNext());
|
||||
it.next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
subset = reversed.headSet("4");
|
||||
it = subset.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("6", it.next());
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("5", it.next());
|
||||
try {
|
||||
assertFalse(it.hasNext());
|
||||
it.next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
subset = reversed.tailSet("2");
|
||||
it = subset.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("2", it.next());
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("1", it.next());
|
||||
try {
|
||||
assertFalse(it.hasNext());
|
||||
it.next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSequencedCollectionIterator() {
|
||||
SortedSet<String> set = new TreeSet<>(List.of("a", "b", "c", "d")).reversed();
|
||||
Iterator<String> it = set.iterator();
|
||||
assertEquals("d", it.next());
|
||||
assertEquals("c", it.next());
|
||||
it.remove();
|
||||
assertArrayEquals(new String[] { "d", "b", "a" }, set.toArray());
|
||||
set = new TreeSet<>(List.of("a", "b", "c", "d")).reversed();
|
||||
it = set.iterator();
|
||||
assertEquals("d", it.next());
|
||||
assertEquals("c", it.next());
|
||||
it.remove();
|
||||
assertEquals("b", it.next());
|
||||
it.remove();
|
||||
assertEquals("a", it.next());
|
||||
try {
|
||||
it.next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
assertArrayEquals(new String[] { "d", "a" }, set.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sequenceCollectionMethodsOnEmpty() {
|
||||
var empty = new TreeSet<>();
|
||||
|
||||
try {
|
||||
empty.getFirst();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
empty.getLast();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
|
||||
try {
|
||||
empty.removeFirst();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
empty.removeLast();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
empty.addFirst("r");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
try {
|
||||
empty.addLast("r");
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMutationsIterator() {
|
||||
SortedSet<String> set = new TreeSet<>(List.of("a", "b", "c", "d"));
|
||||
set.add("e");
|
||||
set.add("f");
|
||||
Iterator<String> it = set.iterator();
|
||||
assertEquals("a", it.next());
|
||||
it.remove();
|
||||
assertEquals("b", it.next());
|
||||
it.remove();
|
||||
assertEquals("c", it.next());
|
||||
it.remove();
|
||||
assertEquals("d", it.next());
|
||||
it.remove();
|
||||
assertEquals("e", it.next());
|
||||
it.remove();
|
||||
assertEquals("f", it.next());
|
||||
it.remove();
|
||||
assertTrue(set.isEmpty());
|
||||
try {
|
||||
it.next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
set = new TreeSet<>(List.of("a", "b", "c", "d"));
|
||||
set.add("e");
|
||||
set.add("f");
|
||||
it = set.reversed().iterator();
|
||||
assertEquals("f", it.next());
|
||||
it.remove();
|
||||
assertEquals("e", it.next());
|
||||
it.remove();
|
||||
assertEquals("d", it.next());
|
||||
it.remove();
|
||||
assertEquals("c", it.next());
|
||||
it.remove();
|
||||
assertEquals("b", it.next());
|
||||
it.remove();
|
||||
assertEquals("a", it.next());
|
||||
it.remove();
|
||||
assertTrue(set.isEmpty());
|
||||
try {
|
||||
it.next();
|
||||
fail();
|
||||
} catch (NoSuchElementException e) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user