From 667adbfc9d778773b592a57ebc9205648f8bb34a Mon Sep 17 00:00:00 2001 From: Bela Ban Date: Tue, 15 Oct 2024 13:43:41 +0200 Subject: [PATCH] - FastArray.resize() now uses the same grow algorithm as ArrayList (new capacity=old capacity *1.5) --- src/org/jgroups/util/FastArray.java | 46 +++++++++---------- .../org/jgroups/tests/FastArrayTest.java | 28 ++++++++--- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/org/jgroups/util/FastArray.java b/src/org/jgroups/util/FastArray.java index 66117ba719..766eeb09e6 100644 --- a/src/org/jgroups/util/FastArray.java +++ b/src/org/jgroups/util/FastArray.java @@ -15,7 +15,7 @@ public class FastArray implements Iterable, List { protected T[] elements; protected int index; // position at which the next element is inserted; only increments, never decrements protected int size; // size: basically index - null elements - protected int increment=5; + protected int increment; // if 0, use the built-in resize (new capacity: old capacity * 1.5) protected int print_limit=20; // max numnber of elements to be printed in toString public FastArray(int capacity) { @@ -33,7 +33,7 @@ public FastArray(T[] elements, int index) { public int size() {return size;} public boolean isEmpty() {return size == 0;} public int increment() {return increment;} - public FastArray increment(int i) {this.increment=ensurePositive(i); return this;} + public FastArray increment(int i) {this.increment=i; return this;} public int printLimit() {return print_limit;} public FastArray printLimit(int l) {this.print_limit=l; return this;} @@ -48,7 +48,7 @@ public boolean add(T el, boolean resize) { if(index == elements.length) { if(!resize) return false; - resize(index + increment); + resize(index +1); } elements[index++]=el; size++; @@ -59,7 +59,7 @@ public boolean add(T el, boolean resize) { public void add(int idx, T el) { checkIndex(idx); if(index+1 > elements.length) - resize(index + 1 + increment); + resize(index +1); System.arraycopy(elements, idx, elements, idx+1, @@ -82,7 +82,7 @@ public boolean addAll(T[] els, int length) { if(length > els.length) length=els.length; if(index + length > elements.length) - resize(index + length + increment); + resize(index + length); System.arraycopy(els, 0, elements, index, length); int added=0, end_index=index+length; while(index < end_index) { @@ -104,7 +104,7 @@ public boolean addAll(Collection list) { return false; int list_size=list.size(); if(index + list_size > elements.length) - resize(index + list_size + increment); + resize(index + list_size); int old_size=size; for(T el: list) { if(el != null) { // null elements need to be handled @@ -126,7 +126,7 @@ public boolean addAll(FastArray fa, boolean resize) { throw new IllegalArgumentException("cannot add FastArray to itself"); int fa_size=fa.size(); if(index+fa_size > elements.length && resize) - resize(index + fa_size + increment); + resize(index + fa_size); int old_size=size; for(T el: fa) { if(index >= elements.length) @@ -174,15 +174,13 @@ public boolean addAll(int idx, Collection c) { * @return The number of non-null elements transferred from other */ public int transferFrom(FastArray other, boolean clear) { - if(other == null || this == other) + if(other == null || this == other || other.isEmpty()) return 0; - int capacity=elements.length, other_size=other.size(), other_capacity=other.capacity(); - if(other_size == 0) - return 0; - if(capacity < other_capacity) - elements=Arrays.copyOf(other.elements, other_capacity); + int capacity=elements.length, other_index=other.index(), other_size=other.size(); + if(capacity < other_index) + elements=Arrays.copyOf(other.elements, other_index); else - System.arraycopy(other.elements, 0, this.elements, 0, other_capacity); + System.arraycopy(other.elements, 0, this.elements, 0, other_index); if(this.index > other.index) for(int i=other.index; i < this.index; i++) elements[i]=null; @@ -339,7 +337,7 @@ public boolean retainAll(Collection c) { @Override public void clear() { - clear(false); + clear(true); } public FastArray clear(boolean null_elements) { @@ -411,11 +409,19 @@ public String print() { public FastArray resize(int new_capacity) { if(new_capacity <= elements.length) return this; - elements=Arrays.copyOf(elements, new_capacity); + int new_cap; + if(increment > 0) + new_cap=new_capacity+increment; + else { + int old_capacity=elements.length; + int min_growth=new_capacity - old_capacity; + int preferred_growth=old_capacity >> 1; // 50% of the old capacity + new_cap=old_capacity + Math.max(min_growth, preferred_growth); + } + elements=Arrays.copyOf(elements, new_cap); return this; } - protected String print(int limit) { boolean first=true; StringBuilder sb=new StringBuilder(); @@ -433,12 +439,6 @@ protected String print(int limit) { return sb.toString(); } - protected static int ensurePositive(int i) { - if(i < 1) - throw new IllegalArgumentException("value needs to be >= 1"); - return i; - } - protected int checkIndex(int idx) { if(idx > index || idx < 0) throw new IndexOutOfBoundsException(String.format("0 >= idx (%d) < index (%d)", idx, index)); diff --git a/tests/junit-functional/org/jgroups/tests/FastArrayTest.java b/tests/junit-functional/org/jgroups/tests/FastArrayTest.java index d3cdb80969..954c367758 100644 --- a/tests/junit-functional/org/jgroups/tests/FastArrayTest.java +++ b/tests/junit-functional/org/jgroups/tests/FastArrayTest.java @@ -137,7 +137,7 @@ public void testAddAllWithIndex() { } public void testAddList() { - FastArray fa=create(3); + FastArray fa=create(3).increment(5); List list=Arrays.asList(3, 4, 5, 6, 7, 8, 9); assert fa.size() == 3; boolean added=fa.addAll(list); @@ -145,7 +145,7 @@ public void testAddList() { assert fa.size() == 10; assert fa.capacity() == 10 + fa.increment(); - fa=new FastArray<>(10); + fa=new FastArray(10).increment(2); added=fa.addAll(Arrays.asList(0, 1, 2)); assert added; added=fa.addAll(list); @@ -156,13 +156,13 @@ public void testAddList() { added=fa.add(11); assert added; assert fa.size() == 11; - assert fa.capacity() == 10 + fa.increment(); + assert fa.capacity() == 11 + fa.increment(); list=new ArrayList<>(); added=fa.addAll(list); assert !added; assert fa.size() == 11; - assert fa.capacity() == 10 + fa.increment(); + assert fa.capacity() == 11 + fa.increment(); } public void testAddFastArray() { @@ -537,13 +537,27 @@ public void testGet() { } public void testResize() { - FastArray fa=create(2); + FastArray fa=create(2).increment(4); int old_cap=fa.capacity(); - assert fa.capacity() == old_cap; fa.add(3); - assert fa.capacity() == old_cap + fa.increment(); + assert fa.capacity() == old_cap + 1 + fa.increment(); } + public void testResize2() { + FastArray fa=create(128); + assert fa.capacity() == 128; + fa.add(128); + int new_capacity=fa.capacity() + fa.capacity() >> 1; + assert fa.capacity() == new_capacity; + IntStream.rangeClosed(128,192).forEach(fa::add); + new_capacity=fa.capacity() + fa.capacity() >> 1; + assert fa.capacity() == new_capacity; + IntStream.rangeClosed(129,288).forEach(fa::add); + new_capacity=fa.capacity() + fa.capacity() >> 1; + assert fa.capacity() == new_capacity; + } + + public void testSimpleIteration() { FastArray fa=create(10); List l=new ArrayList<>(10);