如何按存储在另一个列表中的索引值排序一个列表

时间:2018-01-04 18:49:30

标签: java list sorting

我有BigDecimal List,例如:

[50.0,26.2,29.3]

然后,我有另一个List Integers

[2,1,0]

这些整数是指我想要对第一个列表重新排序的索引。所以,我想重新排序第一个列表:

[29.3,26.2,50.0]

我正在使用Java 8.

2 个答案:

答案 0 :(得分:8)

原始解决方案

让第一个BigDecimal列表被调用decList,第二个Integer列表被称为intList

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

这将获取第二个列表的每个值,并将其用作访问第一个列表值的索引。然后将这些收集到新的List<BigDecimal>

(编辑)使用LinkedList s

检查效率

这是值得深思的,上面的解决方案通常就足够了

TLDR

唯一的地方LinkedList会损害我的原始解决方案是“值列表”(在这种情况下ListBigDecimals)是LinkedList。< / p>

此测试的推理

由于get上的ArrayListO(1)get上的LinkedListO(N),因此可能存在备用,更快的解决方案

我想检查Iterator使用LinkedList的解决方案是否会更快。我阅读了所有类型的Javadoc,无法找到运行linkedList.stream().map(..)是否会.iterator使用LinkedList而不是get 。因此,我决定进行实际测试。

测试用例

  1. 使用ArrayList s。
  2. 测试上面的原始解决方案,使用流媒体和映射
  3. 使用LinkedList s。
  4. 测试上面的原始解决方案,使用流媒体和映射
  5. 使用明确的.iteratorLinkedList s。
  6. 测试解决方案
  7. 使用流媒体和映射测试上述原始解决方案,使用ArrayList作为索引,使用LinkedList作为值。
  8. 使用流媒体和映射测试上述原始解决方案,使用LinkedList作为索引,使用LinkedList作为值。
  9. 测试结果

    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 vs LinkedList,我O(N)的原始解决方案比O(N^2)快得多。
    • 似乎 stream已使用iterator或类似的增强功能来解释get效率差异。通过测试用例2和3之间的相似性可以明显看出这一点。
    • LinkedList只会影响此算法中包含值的效率,因为迭代器优化了流。请注意测试用例#5与仅使用ArrayList的速度一样快,尽管它如何使用LinkedList作为索引。

    效率测试的来源

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

答案 1 :(得分:-1)

嗯,首先要访问BigDecimal中的值。 使用父类给出的BigDecimal属性。

IF NOT EXISTS(
    SELECT
        1
    FROM
        Payments
    WHERE
        Payments.CustomerID = '145300' 
) INSERT 
    INTO
        Payments(Amount)
    VALUES(12.33);

BigDecimal的对象应该根据索引重新排序到正确的值。但是,该功能在2N运行。