Hashmaps foreach (#513)

This commit is contained in:
Ivan Hetman 2020-07-06 11:29:56 +03:00 committed by GitHub
parent 9cf21825fc
commit 3aaefdf23a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 130 additions and 2 deletions

View File

@ -33,7 +33,8 @@
package org.teavm.classlib.java.util;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.*;
import org.teavm.interop.Rename;
@ -101,7 +102,7 @@ public class THashMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
return false;
}
final void checkConcurrentMod() throws ConcurrentModificationException {
final void checkConcurrentMod() throws TConcurrentModificationException {
if (expectedModCount != associatedMap.modCount) {
throw new TConcurrentModificationException();
}
@ -237,6 +238,23 @@ public class THashMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
public TIterator<TMap.Entry<K, V>> iterator() {
return new EntryIterator<>(associatedMap);
}
@Override
public void forEach(Consumer<? super Entry<K, V>> action) {
if (associatedMap.elementCount > 0) {
int prevModCount = associatedMap.modCount;
for (int i = 0; i < associatedMap.elementData.length; i++) {
HashEntry<K, V> entry = associatedMap.elementData[i];
while (entry != null) {
action.accept(entry);
entry = entry.next;
if (prevModCount != associatedMap.modCount) {
throw new TConcurrentModificationException();
}
}
}
}
}
}
@SuppressWarnings("unchecked")
@ -425,6 +443,21 @@ public class THashMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
@Override public TIterator<K> iterator() {
return new KeyIterator<>(THashMap.this);
}
@Override public void forEach(Consumer<? super K> action) {
if (elementCount > 0) {
int prevModCount = modCount;
for (int i = 0; i < elementData.length; i++) {
HashEntry<K, V> entry = elementData[i];
while (entry != null) {
action.accept(entry.key);
entry = entry.next;
if (prevModCount != modCount) {
throw new TConcurrentModificationException();
}
}
}
}
}
};
}
return cachedKeySet;
@ -598,11 +631,43 @@ public class THashMap<K, V> extends TAbstractMap<K, V> implements TCloneable, TS
@Override public TIterator<V> iterator() {
return new ValueIterator<>(THashMap.this);
}
@Override public void forEach(Consumer<? super V> action) {
if (elementCount > 0) {
int prevModCount = modCount;
for (int i = 0; i < elementData.length; i++) {
HashEntry<K, V> entry = elementData[i];
while (entry != null) {
action.accept(entry.value);
entry = entry.next;
if (prevModCount != modCount) {
throw new TConcurrentModificationException();
}
}
}
}
}
};
}
return cachedValues;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
if (elementCount > 0) {
int prevModCount = modCount;
for (int i = 0; i < elementData.length; i++) {
HashEntry<K, V> entry = elementData[i];
while (entry != null) {
action.accept(entry.key, entry.value);
entry = entry.next;
if (prevModCount != modCount) {
throw new TConcurrentModificationException();
}
}
}
}
}
static int computeHashCode(Object key) {
return key.hashCode();
}

View File

@ -31,6 +31,8 @@
*/
package org.teavm.classlib.java.util;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.teavm.classlib.java.lang.TIllegalStateException;
public class TLinkedHashMap<K, V> extends THashMap<K, V> implements TMap<K, V> {
@ -177,6 +179,22 @@ public class TLinkedHashMap<K, V> extends THashMap<K, V> implements TMap<K, V> {
public TIterator<Entry<K, V>> iterator() {
return new EntryIterator<>((TLinkedHashMap<K, V>) hashMap());
}
@Override
public void forEach(Consumer<? super Entry<K, V>> action) {
TLinkedHashMap<K, V> map = (TLinkedHashMap<K, V>) hashMap();
if (map.elementCount > 0) {
int prevModCount = map.modCount;
LinkedHashMapEntry<K, V> entry = map.head;
do {
action.accept(entry);
entry = entry.chainForward;
if (map.modCount != prevModCount) {
throw new TConcurrentModificationException();
}
} while (entry != null);
}
}
}
static final class LinkedHashMapEntry<K, V> extends HashEntry<K, V> {
@ -427,6 +445,21 @@ public class TLinkedHashMap<K, V> extends THashMap<K, V> implements TMap<K, V> {
public TIterator<K> iterator() {
return new KeyIterator<>(TLinkedHashMap.this);
}
@Override
public void forEach(Consumer<? super K> action) {
if (elementCount > 0) {
int prevModCount = modCount;
LinkedHashMapEntry<K, V> entry = head;
do {
action.accept(entry.key);
entry = entry.chainForward;
if (modCount != prevModCount) {
throw new TConcurrentModificationException();
}
} while (entry != null);
}
}
};
}
return cachedKeySet;
@ -455,6 +488,21 @@ public class TLinkedHashMap<K, V> extends THashMap<K, V> implements TMap<K, V> {
public TIterator<V> iterator() {
return new ValueIterator<>(TLinkedHashMap.this);
}
@Override
public void forEach(Consumer<? super V> action) {
if (elementCount > 0) {
int prevModCount = modCount;
LinkedHashMapEntry<K, V> entry = head;
do {
action.accept(entry.value);
entry = entry.chainForward;
if (modCount != prevModCount) {
throw new TConcurrentModificationException();
}
} while (entry != null);
}
}
};
}
return cachedValues;
@ -481,6 +529,21 @@ public class TLinkedHashMap<K, V> extends THashMap<K, V> implements TMap<K, V> {
return m.value;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
if (elementCount > 0) {
int prevModCount = modCount;
LinkedHashMapEntry<K, V> entry = head;
do {
action.accept(entry.key, entry.value);
entry = entry.chainForward;
if (modCount != prevModCount) {
throw new TConcurrentModificationException();
}
} while (entry != null);
}
}
protected boolean removeEldestEntry(@SuppressWarnings("unused") Entry<K, V> eldest) {
return false;
}