Given a List instance, what is the most efficient way of increasing the size of the List by a factor of f such that the new elements are duplicates of the original elements, interleaved with the original array?
e.g.
f = 2
Original = [a,b,c,...,x,y,z]
New = [a,a,b,b,c,c,...,x,x,y,y,z,z]
My current implementation is this:
List< Foo > interleave( List< Foo > original, int f ) {
int newSize = original.size() * f;
List< Foo > interleaved = new ArrayList< Foo >( newSize );
for( Foo foo : original ) {
for( int j = 0; j < factor; j++ ) {
interleaved.add( new Foo( foo ) );
}
}
}
The problem is that my original list can be quite large, so performance isn’t very good. I have a hunch that there is a much more efficient way to do this; does anyone have any suggestions?
The code you provide is well optimized, but there are some improvements that can be made; The significant ones depending on your exact needs.
First, if your cloned elements are going to stay with the same value as the original, or otherwise just a few of them (compared to the total) are going to have their values changed, you might want to consider a reference-based cloning instead of the current “true-clone it all” code, if not a completely different approach that doesn’t even create new lists.
In case you are going to need just a few of your clones to change value, it might be better for your interleaved list to be reference-based, and the elements that need to be changed to be replaced individually later on.
Note however, that the effectiveness of this approach will be highly dependent on how much of your original list’s elements will need to be changed; And that if too many need changes, this method, although still better in memory-footprint, will be worse in speed performance (which seems to be your main concern).
The “later on individual cloning” can be achieved with something similar to this:
If most of every element is going to have independent values in the course of your program’s execution, then your current method is pretty accurate already.
There are two improvements that can be made. It will be easier to show it in the code directly, so that’s what I’ll do:
With an original list of two million elements, and a factor of 2, I get the following average speeds over 10 runs:
2000000 different elements.
interleaveByReference()method.interleaveByClone()method.original()method.