Skip to content

Commit

Permalink
Optimize immutable primitive ArrayList creation from primitive iterab…
Browse files Browse the repository at this point in the history
…les.
  • Loading branch information
donraab committed Jul 14, 2024
1 parent 68aed16 commit f6141ed
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,26 @@ public interface <name>Iterable extends PrimitiveIterable
/**
* Converts the <name>Iterable to a primitive <type> array.
*/
<type>[] toArray();
default <type>[] toArray()
{
return this.toSizedArray(this.size());
}

/**
* Converts the <name>Iterable to a primitive <type> array up to the specified size.
*
* @since 12.0
*/
default <type>[] toSizedArray(int size)
{
<type>[] array = new <type>[size];
int i = 0;
for (<name>Iterator it = this.<type>Iterator(); it.hasNext() && size > i;)
{
array[i++] = it.next();
}
return array;
}

/**
* Converts the <name>Iterable to a primitive <type> array. If the collection fits into the provided array it is used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -723,12 +723,18 @@ public class <name>HashBag
@Override
public <type>[] toArray()
{
<type>[] array = new <type>[this.size()];
return this.toSizedArray(this.size());
}

@Override
public <type>[] toSizedArray(final int size)
{
<type>[] array = new <type>[size];
int[] index = {0};

this.forEachWithOccurrences((<type> each, int occurrences) ->
{
for (int i = 0; i \< occurrences; i++)
for (int i = 0; index[0] \< size && i \< occurrences; i++)
{
array[index[0]] = each;
index[0]++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,6 @@ public abstract class AbstractLazy<name>Iterable implements Lazy<name>Iterable
return new Chunk<name>Iterable(this, size);
}

@Override
public <type>[] toArray()
{
return this.toList().toArray();
}

@Override
public Mutable<name>List toList()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public class Tap<name>Iterable
this.procedure = procedure;
}

@Override
public <type>[] toArray()
{
return this.toSizedArray(this.adapted.size());
}

@Override
public void each(<name>Procedure procedure)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ final class Immutable<name>ArrayList
return new Immutable<name>ArrayList(iterable.toArray());
}

public static Immutable<name>ArrayList newList(<name>Iterable iterable, int size)
{
return new Immutable<name>ArrayList(iterable.toSizedArray(size));
}

public static Immutable<name>ArrayList newListWith(<type>... elements)
{
<type>[] newArray = new <type>[elements.length];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,20 @@ public class Immutable<name>ListFactoryImpl implements Immutable<name>ListFactor
{
return (Immutable<name>List) items;
}
if (items == null || items.size() == 0)
if (items == null)
{
return this.with();
}
if (items.size() == 1)
int size = items.size();
if (size == 0)
{
return this.with(items.toArray()[0]);
return this.with();
}
if (size == 1)
{
return this.with(items.<type>Iterator().next());
}
return Immutable<name>ArrayList.newList(items);
return Immutable<name>ArrayList.newList(items, size);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,15 @@ public class <name>ArrayList extends Abstract<name>Iterable
@Override
public <type>[] toArray()
{
<type>[] newItems = new <type>[this.size];
System.arraycopy(this.items, 0, newItems, 0, this.size);
return this.toSizedArray(this.size);
}

@Override
public <type>[] toSizedArray(int s)
{
<type>[] newItems = new <type>[s];
int newSize = Math.min(s, this.size);
System.arraycopy(this.items, 0, newItems, 0, newSize);
return newItems;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,28 @@ public void sumConsistentRounding()
Assert.assertArrayEquals(new <type>[]{<(literal.(type))("32")>}, this.newWith(<(literal.(type))("32")>).toArray()<(delta.(type))>);
}

@Test
public void toSizedArray()
{
<name>Iterable iterable = this.newWith(<["1", "2"]:(literal.(type))(); separator=", ">);
<type>[] sizeThree = iterable.toSizedArray(3);
Assert.assertTrue(Arrays.equals(new <type>[]{<["1", "2", "0"]:(literal.(type))(); separator=", ">}, sizeThree)
|| Arrays.equals(new <type>[]{<["2", "1", "0"]:(literal.(type))(); separator=", ">}, sizeThree)
|| Arrays.equals(new <type>[]{<["0", "1", "2"]:(literal.(type))(); separator=", ">}, sizeThree)
|| Arrays.equals(new <type>[]{<["0", "2", "1"]:(literal.(type))(); separator=", ">}, sizeThree)
|| Arrays.equals(new <type>[]{<["2", "0", "1"]:(literal.(type))(); separator=", ">}, sizeThree)
|| Arrays.equals(new <type>[]{<["1", "0", "2"]:(literal.(type))(); separator=", ">}, sizeThree)
);
<type>[] sizeTwo = iterable.toSizedArray(2);
Assert.assertTrue(Arrays.equals(new <type>[]{<["1", "2"]:(literal.(type))(); separator=", ">}, sizeTwo)
|| Arrays.equals(new <type>[]{<["2", "1"]:(literal.(type))(); separator=", ">}, sizeTwo));
<type>[] sizeOne = iterable.toSizedArray(1);
Assert.assertTrue(Arrays.equals(new <type>[]{<["1"]:(literal.(type))(); separator=", ">}, sizeOne)
|| Arrays.equals(new <type>[]{<["2"]:(literal.(type))(); separator=", ">}, sizeOne));
<type>[] sizeZero = iterable.toSizedArray(0);
Assert.assertTrue(Arrays.equals(new <type>[]{}, sizeZero));
}

@Test
public void toArrayWithTargetArray()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ public static ImmutableBooleanArrayList newList(BooleanIterable iterable)
return new ImmutableBooleanArrayList(iterable.toArray());
}

public static ImmutableBooleanArrayList newList(BooleanIterable iterable, int size)
{
return new ImmutableBooleanArrayList(iterable.toSizedArray(size));
}

public static ImmutableBooleanArrayList newListWith(boolean... elements)
{
return new ImmutableBooleanArrayList(elements);
Expand Down Expand Up @@ -289,8 +294,15 @@ public <V> ImmutableList<V> collect(BooleanToObjectFunction<? extends V> functio
@Override
public boolean[] toArray()
{
boolean[] newItems = new boolean[this.size];
for (int i = 0; i < this.size; i++)
return this.toSizedArray(this.size);
}

@Override
public boolean[] toSizedArray(int s)
{
boolean[] newItems = new boolean[s];
int newSize = Math.min(s, this.size);
for (int i = 0; i < newSize; i++)
{
newItems[i] = this.items.get(i);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -797,8 +797,15 @@ public <V> MutableList<V> collect(BooleanToObjectFunction<? extends V> function)
@Override
public boolean[] toArray()
{
boolean[] newItems = new boolean[this.size];
for (int i = 0; i < this.size; i++)
return this.toSizedArray(this.size);
}

@Override
public boolean[] toSizedArray(int s)
{
boolean[] newItems = new boolean[s];
int newSize = Math.min(s, this.size);
for (int i = 0; i < newSize; i++)
{
newItems[i] = this.items.get(i);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,19 @@ public void toArray()
|| Arrays.equals(new boolean[]{true, false}, this.newWith(true, false).toArray()));
}

@Test
public void toSizedArray()
{
assertEquals(0L, this.newWith().toSizedArray(0).length);
assertEquals(1L, this.newWith().toSizedArray(1).length);
assertEquals(0L, this.newWith(true).toSizedArray(0).length);
assertTrue(Arrays.equals(new boolean[]{true}, this.newWith(true).toSizedArray(1)));
assertTrue(Arrays.equals(new boolean[]{true, false}, this.newWith(true).toSizedArray(2))
|| Arrays.equals(new boolean[]{false, true}, this.newWith(true).toSizedArray(2)));
assertTrue(Arrays.equals(new boolean[]{false, true}, this.newWith(true, false).toSizedArray(2))
|| Arrays.equals(new boolean[]{true, false}, this.newWith(true, false).toSizedArray(2)));
}

@Test
public void testEquals()
{
Expand Down

0 comments on commit f6141ed

Please sign in to comment.