How to order one list by index values ​​stored in another list

I have a BigDecimal List , for example:

 [50.0,26.2,29.3] 

Then I have another List of Integers :

 [2,1,0] 

These integers refer to the index at which I want to reorder the first list. So, I would like to reorder the first list:

 [29.3,26.2,50.0] 

I am using Java 8.

+5
source share
2 answers

Original solution

Let the first BigDecimal list be called decList and the second Integer list be called intList .

 intList.stream().map(decList::get).collect(Collectors.toList()); 

This takes each value of the second list and uses it as an index to access the value of the first list. Then they are assembled into a new List<BigDecimal> .

(Edit) Learning performance with LinkedList s

This is food for thought, and the solution above will usually be .

TL; DR

The only place LinkedList hurt my initial decision is when the "list of values" ( List with BigDecimals in this case) is a LinkedList .

Reasoning for this testing

Since get on ArrayList is O(1) , but get on LinkedList is O(N) , there may be alternative, faster solutions.

I wanted to check if using the solution with Iterator would be faster for LinkedList s. I read all kinds of Javadocs and could not find if running linkedList.stream().map(..) would use .iterator for LinkedList instead of calling get . So I decided the actual test time.

Control cases

  • Check out the original solution above with streaming and mapping using ArrayList s.
  • Check out the original solution above with streaming and display using LinkedList s.
  • Test the solution using explicit .iterator and LinkedList s.
  • Check out the original solution above with streaming and mapping using ArrayList for indexes and LinkedList for values.
  • Check out the original solution above with streaming and display using LinkedList for indexes and LinkedList for values.

Test results

 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 

conclusions

  • My initial solution is much faster for ArrayList than LinkedList s, due to O(N) vs O(N^2) .
  • It would seem that stream already using Iterator s or similar improvements to account for the difference in get performance . This is evident due to the similarities between test cases 2 and 3.
  • LinkedList only affect performance when they contain a value in this algorithm, due to optimization of the iterator with threads. Note that test case # 5 is as fast as using ArrayList s, even though it uses LinkedList for indexes.

Performance Testing Source

 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"); } } 
+8
source

Well, the first thing to do would be to access the values ​​in BigDecimal. Using properties in BigDecimal defined by the parent class.

 **Loop the values**: BigDecimal.add(BigDecimal.get(List.get(int index))); **Delete the amount of times that the loop ran:** BigDecimal.remove(int index); 

The BigDecimal object should be reordered to the correct index base. However, the function works on 2N.

-1
source

Source: https://habr.com/ru/post/1274508/


All Articles