From 0350a77dff037f79699f08b7c4c7d9f70e910879 Mon Sep 17 00:00:00 2001 From: Speiger Date: Mon, 11 Apr 2022 03:20:28 +0200 Subject: [PATCH] Finishing the ConcurrentMap implementation This though isn't finishing the rest because the interface still needs to be implemented. -Added: Rest of the ConcurrentMap implementation -Fixed: LinkedOpenHashMap Count method was returning prematurely. --- .../concurrent/ConcurrentOpenHashMap.template | 1063 ++++++++++++++++- .../maps/impl/hash/LinkedOpenHashMap.template | 7 +- 2 files changed, 1058 insertions(+), 12 deletions(-) diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template index 1b51ad11..db48b3c2 100644 --- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template +++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/concurrent/ConcurrentOpenHashMap.template @@ -1,18 +1,74 @@ package speiger.src.collections.PACKAGE.maps.impl.concurrent; import java.util.Arrays; +import java.util.Map; +import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; +import java.util.function.BiFunction; -import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_SUPPLIER; -import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_UNARY_OPERATOR; +#if !TYPE_OBJECT +import speiger.src.collections.PACKAGE.collections.BI_ITERATOR; +#if SAME_TYPE +import speiger.src.collections.PACKAGE.collections.ITERATOR; +#endif +import speiger.src.collections.PACKAGE.functions.CONSUMER; +import speiger.src.collections.objects.functions.consumer.BI_FROM_OBJECT_CONSUMER; +#endif import speiger.src.collections.PACKAGE.functions.consumer.BI_CONSUMER; import speiger.src.collections.PACKAGE.functions.function.FUNCTION; -#if !SAME_TYPE import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; +#if !SAME_TYPE +import speiger.src.collections.PACKAGE.functions.function.SINGLE_UNARY_OPERATOR; +#endif +#if !TYPE_OBJECT && !VALUE_BOOLEAN +import speiger.src.collections.PACKAGE.functions.function.PREDICATE; #endif import speiger.src.collections.PACKAGE.maps.abstracts.ABSTRACT_MAP; import speiger.src.collections.PACKAGE.maps.interfaces.MAP; +#if !TYPE_OBJECT +import speiger.src.collections.PACKAGE.sets.ABSTRACT_SET; +import speiger.src.collections.PACKAGE.sets.SET; +#endif +import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ABSTRACT_COLLECTION; +import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_COLLECTION; +import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_SUPPLIER; +#if !SAME_TYPE +import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_UNARY_OPERATOR; + +#if !VALUE_OBJECT +#if !TYPE_OBJECT +import speiger.src.collections.objects.functions.function.ObjectObjectUnaryOperator; +#endif +import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_ITERATOR; +import speiger.src.collections.VALUE_PACKAGE.collections.VALUE_BI_ITERATOR; +import speiger.src.collections.VALUE_PACKAGE.functions.VALUE_CONSUMER; +#endif +#else if !VALUE_OBJECT +import speiger.src.collections.objects.functions.function.ObjectObjectUnaryOperator; + +#endif +#if !TYPE_OBJECT && !VALUE_OBJECT || !VALUE_OBJECT +import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer; +#endif +#if !TYPE_OBJECT || !VALUE_BOOLEAN +#if !VALUE_OBJECT || SAME_TYPE +import speiger.src.collections.objects.functions.function.Object2BooleanFunction; +#endif +#endif +#if !SAME_TYPE +#if !TYPE_OBJECT +import speiger.src.collections.objects.functions.consumer.VALUE_BI_FROM_OBJECT_CONSUMER; +#endif + +import speiger.src.collections.VALUE_PACKAGE.functions.function.VALUE_PREDICATE; +#endif +#if VALUE_OBJECT +import speiger.src.collections.objects.collections.ObjectIterator; +#endif +import speiger.src.collections.objects.collections.ObjectBidirectionalIterator; +import speiger.src.collections.objects.sets.AbstractObjectSet; import speiger.src.collections.objects.sets.ObjectSet; import speiger.src.collections.utils.HashUtil; @@ -24,6 +80,14 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU protected transient Segment KEY_VALUE_GENERIC_TYPE[] segments; protected transient int segmentShift; protected transient int segmentMask; + /** EntrySet cache */ + protected transient FastEntrySet KEY_VALUE_GENERIC_TYPE entrySet; + /** KeySet cache */ + protected transient SET KEY_GENERIC_TYPE keySet; + /** Values cache */ + protected transient VALUE_COLLECTION VALUE_GENERIC_TYPE values; + + protected CONCURRENT_MAP(boolean unused) {} public CONCURRENT_MAP(int minCapacity, float loadFactor, int concurrencyLevel) { if(minCapacity < 0) throw new IllegalStateException("Minimum Capacity is negative. This is not allowed"); @@ -130,10 +194,16 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU segments[i].forEach(action); } } - + @Override public CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE copy() { - return null;//TODO implement + CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE copy = new CONCURRENT_MAPKV_BRACES(false); + copy.segmentShift = segmentShift; + copy.segmentMask = segmentMask; + copy.segments = new Segment[segments.length]; + for(int i = 0,m=segments.length;i 0) return false; + } + return true; + } + @Override public int size() { long size = 0L; @@ -219,7 +297,24 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU @Override public ObjectSet ENTRY_SET() { - return null; + if(entrySet == null) entrySet = new MapEntrySet(); + return entrySet; + } + + @Override + public SET KEY_GENERIC_TYPE keySet() { + if(keySet == null) keySet = new KeySet(); + return keySet; + } + + @Override + public VALUE_COLLECTION VALUE_GENERIC_TYPE values() { + if(values == null) values = new Values(); + return values; + } + + protected int getSegmentIndex(int hash) { + return (hash >>> segmentShift) & segmentMask; } protected Segment KEY_VALUE_GENERIC_TYPE getSegment(int hash) { @@ -236,6 +331,939 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU return HashUtil.mix(Objects.hashCode(obj)); } + public void test() { + + } + + private class MapEntrySet extends AbstractObjectSet implements MAP.FastEntrySet KEY_VALUE_GENERIC_TYPE { + @Override + public ObjectBidirectionalIterator iterator() { + return new EntryIterator(); + } + + //TODO implement? + public ObjectBidirectionalIterator iterator(MAP.Entry KEY_VALUE_GENERIC_TYPE fromElement) { + return new EntryIterator(fromElement.ENTRY_KEY()); + } + + @Override + public ObjectBidirectionalIterator fastIterator() { + return new FastEntryIterator(); + } + + //TODO implement? + public ObjectBidirectionalIterator fastIterator(KEY_TYPE fromElement) { + return new FastEntryIterator(fromElement); + } + + @Override + public MapEntrySet copy() { throw new UnsupportedOperationException(); } + + @Override + public void forEach(Consumer action) { + for(int i = 0,m=segments.length;i action) { + BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); + for(int i = 0,m=segments.length;i void forEach(E input, ObjectObjectConsumer action) { + Objects.requireNonNull(action); + for(int i = 0,m=segments.length;i filter) { + Objects.requireNonNull(filter); + BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); + for(int i = 0,m=segments.length;i filter) { + Objects.requireNonNull(filter); + BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); + for(int i = 0,m=segments.length;i filter) { + Objects.requireNonNull(filter); + BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); + for(int i = 0,m=segments.length;i E reduce(E identity, BiFunction operator) { + Objects.requireNonNull(operator); + E state = identity; + for(int i = 0,m=segments.length;i operator) { + Objects.requireNonNull(operator); + MAP.Entry KEY_VALUE_GENERIC_TYPE state = null; + boolean empty = true; + for(int i = 0,m=segments.length;i filter) { + Objects.requireNonNull(filter); + BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); + for(int i = 0,m=segments.length;i filter) { + Objects.requireNonNull(filter); + int result = 0; + BasicEntry KEY_VALUE_GENERIC_TYPE entry = new BasicEntryKV_BRACES(); + for(int i = 0,m=segments.length;i= 0) return VALUE_EQUALS(entry.ENTRY_VALUE(), seg.values[index]); + } + else { + Map.Entry entry = (Map.Entry)o; + int hash = getHashCode(entry.getKey()); + Segment KEY_VALUE_GENERIC_TYPE seg = getSegment(hash); + int index = seg.findIndex(hash, entry.getKey()); + if(index >= 0) return Objects.equals(entry.getValue(), VALUE_TO_OBJ(seg.values[index])); + } + } + return false; + } + + @Override + @Deprecated + public boolean remove(Object o) { + if(o instanceof Map.Entry) { + if(o instanceof MAP.Entry) { + MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)o; + return CONCURRENT_MAP.this.remove(entry.ENTRY_KEY(), entry.ENTRY_VALUE()); + } + Map.Entry entry = (Map.Entry)o; + return CONCURRENT_MAP.this.remove(entry.getKey(), entry.getValue()); + } + return false; + } + + @Override + public int size() { + return CONCURRENT_MAP.this.size(); + } + + @Override + public void clear() { + CONCURRENT_MAP.this.clear(); + } + } + + private final class KeySet extends ABSTRACT_SET KEY_GENERIC_TYPE implements SET KEY_GENERIC_TYPE { + + @Override + public boolean add(KEY_TYPE key) { throw new UnsupportedOperationException(); } + +#if TYPE_OBJECT + @Override + @Deprecated + public boolean contains(Object e) { + return containsKey(e); + } + + @Override + public boolean remove(Object o) { + int oldSize = size(); + CONCURRENT_MAP.this.remove(o); + return size() != oldSize; + } + +#else + @Override + public boolean contains(KEY_TYPE e) { + return containsKey(e); + } + + @Override + public boolean remove(KEY_TYPE o) { + int oldSize = size(); + CONCURRENT_MAP.this.remove(o); + return size() != oldSize; + } + +#endif + @Override + public BI_ITERATOR KEY_GENERIC_TYPE iterator() { + return new KeyIterator(); + } + + //TODO implement into interface? + public BI_ITERATOR KEY_GENERIC_TYPE iterator(KEY_TYPE fromElement) { + return new KeyIterator(fromElement); + } + + @Override + public KeySet copy() { throw new UnsupportedOperationException(); } + + @Override + public int size() { + return CONCURRENT_MAP.this.size(); + } + + @Override + public void clear() { + CONCURRENT_MAP.this.clear(); + } + + @Override + public void forEach(CONSUMER KEY_SUPER_GENERIC_TYPE action) { + Objects.requireNonNull(action); + for(int i = 0,m=segments.length;i void forEach(E input, BI_FROM_OBJECT_CONSUMER KSK_GENERIC_TYPE action) { + Objects.requireNonNull(action); + for(int i = 0,m=segments.length;i KEY_SPECIAL_TYPE reduce(KEY_SPECIAL_TYPE identity, BiFunction operator) { + Objects.requireNonNull(operator); + KEY_SPECIAL_TYPE state = identity; + for(int i = 0,m=segments.length;i void forEach(E input, VALUE_BI_FROM_OBJECT_CONSUMER VSV_GENERIC_TYPE action) { + Objects.requireNonNull(action); + for(int i = 0,m=segments.length;i VALUE_SPECIAL_TYPE reduce(VALUE_SPECIAL_TYPE identity, BiFunction operator) { + Objects.requireNonNull(operator); + VALUE_SPECIAL_TYPE state = identity; + for(int i = 0,m=segments.length;i { + MapEntry entry = new MapEntry(); + + public FastEntryIterator() {} + public FastEntryIterator(KEY_TYPE from) { + super(from); + } + + @Override + public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { + entry.set(nextEntry(), currentSegment()); + return entry; + } + + @Override + public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() { + entry.set(previousEntry(), currentSegment()); + return entry; + } + } + + private class EntryIterator extends MapIterator implements ObjectBidirectionalIterator { + MapEntry entry; + + public EntryIterator() {} + public EntryIterator(KEY_TYPE from) { + super(from); + } + + @Override + public MAP.Entry KEY_VALUE_GENERIC_TYPE next() { + return entry = new MapEntry(nextEntry(), currentSegment()); + } + + @Override + public MAP.Entry KEY_VALUE_GENERIC_TYPE previous() { + return entry = new MapEntry(previousEntry(), currentSegment()); + } + + @Override + public void remove() { + super.remove(); + entry.clear(); + } + } + + private class ValueIterator extends MapIterator implements VALUE_BI_ITERATOR VALUE_GENERIC_TYPE { + public ValueIterator() {} + + @Override + public VALUE_TYPE VALUE_PREVIOUS() { + return entry(previousEntry(), currentSegment()); + } + + @Override + public VALUE_TYPE VALUE_NEXT() { + return entry(nextEntry(), currentSegment()); + } + + protected VALUE_TYPE entry(int entry, int segment) { + return segments[segment].values[entry]; + } + } + + private class KeyIterator extends MapIterator implements BI_ITERATOR KEY_GENERIC_TYPE { + + public KeyIterator() {} + public KeyIterator(KEY_TYPE from) { + super(from); + } + + @Override + public KEY_TYPE PREVIOUS() { + return entry(previousEntry(), currentSegment()); + } + + @Override + public KEY_TYPE NEXT() { + return entry(nextEntry(), currentSegment()); + } + + protected KEY_TYPE entry(int entry, int segment) { + return segments[segment].keys[entry]; + } + } + + private class MapIterator { + int previous = -1; + int next = -1; + int current = -1; + int previousSegment = -1; + int nextSegment = -1; + int currentSegment = -1; + + MapIterator() { + nextSegment = getFirstSegment(); + if(nextSegment != -1) next = segments[nextSegment].firstIndex; + } + + MapIterator(KEY_TYPE from) { + int hash = getHashCode(from); + previousSegment = currentSegment = nextSegment = getSegmentIndex(hash); + Segment KEY_VALUE_GENERIC_TYPE seg = segments[currentSegment]; + current = previous = seg.findIndex(hash, from); + if(current == -1) throw new NoSuchElementException("The element was not found"); + findNextIndex(); + current = -1; + currentSegment = -1; + } + + public boolean hasNext() { + return next != -1; + } + + public boolean hasPrevious() { + return previous != -1; + } + + public int currentSegment() { + return currentSegment; + } + + public int previousEntry() { + if(!hasPrevious()) throw new NoSuchElementException(); + next = current = previous; + nextSegment = currentSegment = previousSegment; + findPreviousIndex(); + return current; + } + + public int nextEntry() { + if(!hasNext()) throw new NoSuchElementException(); + previous = current = next; + previousSegment = currentSegment = nextSegment; + findNextIndex(); + return current; + } + + public void remove() { + if(current == -1) throw new IllegalStateException(); + Segment KEY_VALUE_GENERIC_TYPE seg = segments[currentSegment]; + seg.lock(); + try { + if(current == previous) findPreviousIndex(); + else findNextIndex(); + seg.size--; + if(previousSegment != currentSegment) seg.firstIndex = next; + else seg.links[previous] ^= ((seg.links[previous] ^ (next & 0xFFFFFFFFL)) & 0xFFFFFFFFL); + + if(nextSegment != currentSegment) seg.lastIndex = previous; + else seg.links[next] ^= ((seg.links[next] ^ ((previous & 0xFFFFFFFFL) << 32)) & 0xFFFFFFFF00000000L); + + if(current == seg.nullIndex) { + current = -1; + currentSegment = -1; + seg.containsNull = false; + seg.keys[seg.nullIndex] = EMPTY_KEY_VALUE; + seg.values[seg.nullIndex] = EMPTY_VALUE; + } + else { + int slot, last, startPos = current; + current = -1; + currentSegment = -1; + KEY_TYPE current; + while(true) { + startPos = ((last = startPos) + 1) & seg.mask; + while(true){ + if(KEY_EQUALS_NULL((current = seg.keys[startPos]))) { + seg.keys[last] = EMPTY_KEY_VALUE; + seg.values[last] = EMPTY_VALUE; + return; + } + slot = HashUtil.mix(KEY_TO_HASH(current)) & seg.mask; + if(last <= startPos ? (last >= slot || slot > startPos) : (last >= slot && slot > startPos)) break; + startPos = ++startPos & seg.mask; + } + seg.keys[last] = current; + seg.values[last] = seg.values[startPos]; + if(next == startPos) next = last; + if(previous == startPos) previous = last; + seg.onNodeMoved(startPos, last); + } + } + } + finally { + seg.unlock(); + } + } + + protected void findPreviousIndex() { + previous = (int)(segments[currentSegment].links[current] >> 32); + if(previous == -1) { + previousSegment = findPreviousSegment(currentSegment-1); + if(previousSegment != -1) previous = segments[previousSegment].lastIndex; + } + } + + protected void findNextIndex() { + next = (int)(segments[currentSegment].links[current]); + if(next == -1) { + nextSegment = findNextSegment(currentSegment+1); + if(nextSegment != -1) next = segments[nextSegment].firstIndex; + } + } + + private int getFirstSegment() { + for(int i = 0,m=segments.length;i= segments.length ? -1 : index; + } + + private int findPreviousSegment(int index) { + for(;index >= 0 && segments[index].lastIndex == -1;index--); + return index >= 0 ? index : -1; + } + } + + protected class MapEntry implements MAP.Entry KEY_VALUE_GENERIC_TYPE, Map.Entry { + int index = -1; + int segmentIndex = -1; + + public MapEntry() {} + public MapEntry(int index, int segmentIndex) { + set(index, segmentIndex); + } + + public void set(int index, int segmentIndex) { + this.index = index; + this.segmentIndex = segmentIndex; + } + + public void clear() { + index = -1; + segmentIndex = -1; + } + + @Override + public KEY_TYPE ENTRY_KEY() { + return segments[segmentIndex].keys[index]; + } + + @Override + public VALUE_TYPE ENTRY_VALUE() { + return segments[segmentIndex].values[index]; + } + + @Override + public VALUE_TYPE setValue(VALUE_TYPE value) { + Segment KEY_VALUE_GENERIC_TYPE seg = segments[segmentIndex]; + seg.lock(); + try + { + VALUE_TYPE oldValue = ENTRY_VALUE(); + seg.values[index] = value; + return oldValue; + } + finally { + seg.unlock(); + } + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof Map.Entry) { + if(obj instanceof MAP.Entry) { + MAP.Entry KEY_VALUE_GENERIC_TYPE entry = (MAP.Entry KEY_VALUE_GENERIC_TYPE)obj; + return KEY_EQUALS(ENTRY_KEY(), entry.ENTRY_KEY()) && VALUE_EQUALS(ENTRY_VALUE(), entry.ENTRY_VALUE()); + } + Map.Entry entry = (Map.Entry)obj; + Object key = entry.getKey(); + Object value = entry.getValue(); +#if TYPE_OBJECT && VALUE_OBJECT + return KEY_EQUALS(ENTRY_KEY(), key) && VALUE_EQUALS(ENTRY_VALUE(), value); +#else if TYPE_OBJECT + return value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(ENTRY_KEY(), key) && VALUE_EQUALS(ENTRY_VALUE(), CLASS_TO_VALUE(value)); +#else if VALUE_OBJECT + return key instanceof CLASS_TYPE && KEY_EQUALS(ENTRY_KEY(), CLASS_TO_KEY(key)) && VALUE_EQUALS(ENTRY_VALUE(), value); +#else + return key instanceof CLASS_TYPE && value instanceof CLASS_VALUE_TYPE && KEY_EQUALS(ENTRY_KEY(), CLASS_TO_KEY(key)) && VALUE_EQUALS(ENTRY_VALUE(), CLASS_TO_VALUE(value)); +#endif + } + return false; + } + + @Override + public int hashCode() { + return KEY_TO_HASH(ENTRY_KEY()) ^ VALUE_TO_HASH(ENTRY_VALUE()); + } + + @Override + public String toString() { + return KEY_TO_STRING(ENTRY_KEY()) + "=" + VALUE_TO_STRING(ENTRY_VALUE()); + } + } + protected static class Segment KEY_VALUE_GENERIC_TYPE extends ReentrantLock { private static final long serialVersionUID = -446894977795760975L; @@ -265,6 +1293,10 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU /** How full the Arrays are allowed to get before resize */ protected float loadFactor; + protected Segment(CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE map) { + this.map = map; + } + protected Segment(CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE map, int minCapacity, float loadFactor, boolean isNullContainer) { this.map = map; this.minCapacity = minCapacity; @@ -278,6 +1310,23 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU links = new long[arraySize]; } + protected Segment KEY_VALUE_GENERIC_TYPE copy(CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE newMap) { + Segment KEY_VALUE_GENERIC_TYPE copy = new SegmentKV_BRACES(newMap); + copy.keys = Arrays.copyOf(keys, keys.length); + copy.values = Arrays.copyOf(values, values.length); + copy.links = Arrays.copyOf(links, links.length); + copy.firstIndex = firstIndex; + copy.lastIndex = lastIndex; + copy.containsNull = containsNull; + copy.nullIndex = nullIndex; + copy.maxFill = maxFill; + copy.mask = mask; + copy.size = size; + copy.minCapacity = minCapacity; + copy.loadFactor = loadFactor; + return copy; + } + protected VALUE_TYPE getDefaultReturnValue() { return map.getDefaultReturnValue(); } @@ -397,7 +1446,7 @@ public class CONCURRENT_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALU } #if TYPE_OBJECT && VALUE_OBJECT - public VALUE_TYPE getOrDefault(int hash, Object key, VALUE_TYPE defaultValue) { + protected VALUE_TYPE getOrDefault(int hash, Object key, VALUE_TYPE defaultValue) { int slot = findIndex(hash, key); return slot < 0 ? defaultValue : values[slot]; } diff --git a/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template b/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template index c4fd59bf..eb31fd95 100644 --- a/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template +++ b/src/builder/resources/speiger/assets/collections/templates/maps/impl/hash/LinkedOpenHashMap.template @@ -905,9 +905,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G #endif @Override - public boolean add(KEY_TYPE o) { - throw new UnsupportedOperationException(); - } + public boolean add(KEY_TYPE o) { throw new UnsupportedOperationException(); } @Override public boolean addAndMoveToFirst(KEY_TYPE o) { throw new UnsupportedOperationException(); } @@ -1089,7 +1087,7 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G int result = 0; int index = firstIndex; while(index != -1){ - if(filter.TEST_VALUE(keys[index])) return result++; + if(filter.TEST_VALUE(keys[index])) result++; index = (int)links[index]; } return result; @@ -1371,7 +1369,6 @@ public class LINKED_HASH_MAP KEY_VALUE_GENERIC_TYPE extends HASH_MAP KEY_VALUE_G @Override public void add(VALUE_TYPE e) { throw new UnsupportedOperationException(); } - } private class MapIterator {