I have a BigDecimal
List
such as:
[50.0,26.2,29.3]
Then, I have another List
of Integers
:
[2,1,0]
These integers refer to the index by which I want to reorder the first list. So, I would like to reorder the first list to be:
[29.3,26.2,50.0]
I'm using Java 8.
Let the first list of BigDecimal
be called decList
and the second list of Integer
be called intList
.
intList.stream().map(decList::get).collect(Collectors.toList());
This takes each value of the second list and uses it as the index for accessing the value of the first list. These are then collected into a new List<BigDecimal>
.
LinkedList
sThis is food for thought and the solution above will normally suffice.
The only place LinkedList
s will hurt my original solution is when the "values list" (the List
with BigDecimals
in this case) is a LinkedList
.
Since get
on ArrayList
s is O(1)
, but get
on LinkedList
s is O(N)
, there may be alternate, faster solutions.
I wanted to examine if using a solution with Iterator
would be faster for LinkedList
s. I read through all kinds of Javadocs and couldn't find if running linkedList.stream().map(..)
would use .iterator
for LinkedList
s instead of calling get
. Therefore I decided to time an actual test.
ArrayList
s.LinkedList
s..iterator
and LinkedList
s.ArrayList
for the indexes and a LinkedList
for the values.LinkedList
for the indexes and a LinkedList
for the values.ArrayList Implementation:
Duration: 70 milliseconds
Duration: 15 milliseconds
Duration: 16 milliseconds
Duration: 15 milliseconds
Duration: 15 milliseconds
Average duration: 26 milliseconds
LinkedList Implementation with Stream and Map:
Duration: 1359 milliseconds
Duration: 1387 milliseconds
Duration: 1309 milliseconds
Duration: 1302 milliseconds
Duration: 1304 milliseconds
Average duration: 1332 milliseconds
LinkedList Implementation with Iterator:
Duration: 2806 milliseconds
Duration: 2173 milliseconds
Duration: 1305 milliseconds
Duration: 1305 milliseconds
Duration: 1305 milliseconds
Average duration: 1778 milliseconds
Mix test case #4:
Duration: 1281 milliseconds
Duration: 1278 milliseconds
Duration: 1278 milliseconds
Duration: 1278 milliseconds
Duration: 1278 milliseconds
Average duration: 1278 milliseconds
Mix test case #5:
Duration: 13 milliseconds
Duration: 7 milliseconds
Duration: 7 milliseconds
Duration: 7 milliseconds
Duration: 7 milliseconds
Average duration: 8 milliseconds
ArrayList
s than LinkedList
s, due to O(N)
vs O(N^2)
.stream
s already use iterator
s, or similar enhancements to account for the get
efficiency difference. This is apparent through the similarity between test cases 2 and 3.LinkedList
s only affect the efficiency when they contain the value in this algorithm, due to the iterator optimization with streams. Notice how test case #5 is just as fast as only using ArrayList
s, despite how it uses a LinkedList
for the indexes.import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.math.BigDecimal;
import java.util.stream.Collectors;
import java.lang.Math;
import java.util.Iterator;
class Test {
public static void main(String[] args) {
testArrayListImplementation();
testLinkedListImplementation();
testCaseFourMixed();
testCaseFiveMixed();
}
static void testArrayListImplementation() {
List<BigDecimal> bigDecList = new ArrayList<BigDecimal>();
List<Integer> ndxList = new ArrayList<Integer>();
System.out.println("ArrayList Implementation:");
timeListImplementation(bigDecList, ndxList, false);
}
static void testLinkedListImplementation() {
List<BigDecimal> bigDecList = new LinkedList<BigDecimal>();
List<Integer> ndxList = new LinkedList<Integer>();
System.out.println("LinkedList Implementation with Stream and Map:");
timeListImplementation(bigDecList, ndxList, false);
System.out.println("LinkedList Implementation with Iterator:");
timeListImplementation(bigDecList, ndxList, true);
}
static void testCaseFourMixed() {
//Test case 4
List<BigDecimal> bigDecList = new LinkedList<BigDecimal>();
List<Integer> ndxList = new ArrayList<Integer>();
System.out.println("Mix test case #4:");
timeListImplementation(bigDecList, ndxList, false);
}
static void testCaseFiveMixed() {
//Test case 5
List<BigDecimal> bigDecList = new ArrayList<BigDecimal>();
List<Integer> ndxList = new LinkedList<Integer>();
System.out.println("Mix test case #5:");
timeListImplementation(bigDecList, ndxList, false);
}
static void timeListImplementation(List<BigDecimal> bigDecList, List<Integer> ndxList, boolean useIterator) {
for (int i = 0; i < 10000; i++) {
bigDecList.add(new BigDecimal(123.4));
ndxList.add((int) (Math.random() * 1000));
}
long totalDuration = 0;
for (int linkedTrial = 0; linkedTrial < 5; linkedTrial++) {
long startTime = System.nanoTime();
for (int numComputations = 0; numComputations < 100; numComputations++) {
if (useIterator) {
Iterator<Integer> ndxIter = ndxList.iterator();
List<BigDecimal> specializedList = new LinkedList<BigDecimal>();
while (ndxIter.hasNext()) {
specializedList.add(bigDecList.get(ndxIter.next()));
}
} else {
List<BigDecimal> specializedList = ndxList.stream().map(bigDecList::get).collect(Collectors.toList());
}
}
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1000000; //milliseconds
System.out.println("Duration: " + duration + " milliseconds");
totalDuration += duration;
}
System.out.println("Average duration: " + (totalDuration / 5) + " milliseconds");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With