简体   繁体   English

为什么ArrayList的排序方法比Java中的Arrays更快?

[英]Why is ArrayList's sort method faster than Arrays' in Java?

The goal of the following code is to sort 300,000 int numbers. 以下代码的目标是对300,000个int数字进行排序。 I find that the duration of ArrayList's sort() is less than Arrays' sort(). 我发现ArrayList的sort()的持续时间小于Arrays的sort()。 Internally, they use the same algorithm to sort. 在内部,他们使用相同的算法进行排序。 ArrayList uses Arrays' sort() to sort its element data. ArrayList使用Arrays的sort()来对其元素数据进行排序。

public class EasySort {
    public static void main(String args[]) {
        // Read data from file, number split by ","
        FileReader fr = null;
        try {
            fr = new FileReader("testdata2.txt");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        BufferedReader  bufferedReader=new BufferedReader(fr);
        String line=null;
        try {
            line=bufferedReader.readLine();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // use split method to generate a String array to save numbers
        String[] strArray=line.split(",");

        //Convert string array to ArrayList<Integer>
        ArrayList<Integer> integerList=new ArrayList<>();
        for(String str:strArray){
            integerList.add(Integer.parseInt(str));
        }

        //Sort by ArrayList
        long t0=System.currentTimeMillis();
        integerList.sort(((p1,p2)->(p1.intValue()<p2.intValue()?-1:p1.intValue()>p2.intValue()?1:0)));
        long t1=System.currentTimeMillis();
        System.out.println("ArrayList Sort duration:"+(t1-t0));

        //Convert string array to Integer array
        Integer[] integerArray=new Integer[strArray.length];
        int i=0;
        for(String str:strArray){
            integerArray[i++]=Integer.parseInt(str);
        }

        //Sort by Arrays
        t0=System.currentTimeMillis();
        Arrays.sort(integerArray, ((p1,p2)->(p1.intValue()<p2.intValue()?-1:p1.intValue()>p2.intValue()?1:0)));
        t1=System.currentTimeMillis();
        System.out.println("Arrays duration:"+(t1-t0));
    }
}

The result is as follows: 结果如下:
ArrayList Sort duration:211 ArrayList排序持续时间:211
Arrays duration:435 阵列持续时间:435

I checked the source code of ArrayList. 我检查了ArrayList的源代码。 It use Arrays.sort() in its own sort method. 它在自己的排序方法中使用Arrays.sort()。

 @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

So, in my opinion, my code should show the same duration. 所以,在我看来,我的代码应该显示相同的持续时间。 But I tried many times, and the results are similar. 但我尝试了很多次,结果很相似。 What happened? 发生了什么?

Java version: 8 Java版本:8
Operating System: Windows 7 操作系统:Windows 7

This is a warm-up issue - but exactly why I don't know. 这是一个热身问题 - 但究竟为什么我不知道。

Using this code: 使用此代码:

public void test() {
    Integer[] a = randomData(10000000);

    ArrayList<Integer> integerList = new ArrayList<>();
    for (Integer i : a) {
        integerList.add(i);
    }

    long t0, t1;
    //Sort by ArrayList
    t0 = System.currentTimeMillis();
    integerList.sort(((p1, p2) -> (p1.intValue() < p2.intValue() ? -1 : p1.intValue() > p2.intValue() ? 1 : 0)));
    t1 = System.currentTimeMillis();
    System.out.println("ArrayList duration:" + (t1 - t0));


    //Sort by Arrays
    Integer[] integerArray = Arrays.copyOf(a, a.length);
    t0 = System.currentTimeMillis();
    Arrays.sort(integerArray, ((p1, p2) -> (p1.intValue() < p2.intValue() ? -1 : p1.intValue() > p2.intValue() ? 1 : 0)));
    t1 = System.currentTimeMillis();
    System.out.println("Arrays duration:" + (t1 - t0));

}

Random r = new Random(System.currentTimeMillis());

private Integer[] randomData(int n) {
    Integer[] a = new Integer[n];
    for (int i = 0; i < n; i++) {
        a[i] = r.nextInt();
    }
    return a;
}

and moving the two sorts into different orders I get: 并将两种不同的顺序移动到我得到的顺序:

Arrays duration:4209 阵列持续时间:4209

ArrayList duration:4570 ArrayList持续时间:4570

ArrayList duration:6776 ArrayList持续时间:6776

Arrays duration:4684 阵列持续时间:4684

So if ArrayList is sorted first it takes longer. 因此,如果ArrayList首先排序,则需要更长时间。

So @AndyTurner's comment is correct - refer to How do I write a correct micro-benchmark in Java? 所以@AndyTurner的评论是正确的 - 参考我如何在Java中编写正确的微基准测试?

Java 8 - Windows 10 Java 8 - Windows 10

They should be the same, I dont know why you had different results. 他们应该是一样的,我不知道你为什么会有不同的结果。 Below is my code and I have almost the same time. 下面是我的代码,我几乎是同一时间。 For T[] and ArrayList<T> both will invoke Arrays.sort(T[], ...) which will then use merge sort or tim sort. 对于T[]ArrayList<T>它们都将调用Arrays.sort(T[], ...) ,然后使用合并排序或时间排序。

Random rand = new Random();
Integer[] array = new Integer[300000];
for (int i = 0; i < array.length; i++)
    array[i] = rand.nextInt(array.length);  
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(array));    

long a = System.currentTimeMillis();
Arrays.sort(array, 0 ,array.length);
long b = System.currentTimeMillis();
list.sort(null);
long c = System.currentTimeMillis();

System.out.println(b - a);
System.out.println(c - b);

This is something I tried using Java 8. Note that there is an array is of int s, an array of Integer s and the List is of Integer s. 这是我尝试使用Java 8的东西。注意,有一个数组是int ,一个是Integer的数组, ListInteger的。 In addition the Integer array is sorted using the Arrays.parallelSort() . 此外,使用Arrays.parallelSort()Integer数组进行排序。

import java.util.*;
import java.util.stream.*;
public class TestingSorts {
    public static void main(String[] args) {
        long t0 = 0L;
        long t1 = 0L;
        // Run this procedure 10 times
        for (int i = 1; i < 11; i++) {
            // Create an int array and Integer List filled with random numbers
            int [] intArray = IntStream.generate(() -> new Random().nextInt())
                        .limit(300_000)
                        .toArray();
            Integer [] integerArray = IntStream.generate(() -> new Random().nextInt())
                        .limit(300_000)
                        .boxed()
                        .toArray(n -> new Integer[n]);
            Integer [] integerArrayP = IntStream.generate(() -> new Random().nextInt())
                        .limit(300_000)
                        .boxed()
                        .toArray(n -> new Integer[n]);
            List<Integer> intList = IntStream.generate(() -> new Random().nextInt())
                        .limit(300_000)
                        .boxed()
                        .collect(Collectors.toCollection(ArrayList::new));
            // Sort the List and the arrays
            t0 = System.currentTimeMillis();
            intList.sort(null);
            t1 = System.currentTimeMillis();
            System.out.println(i + ") ArrayList<Integer> sort duration: " + (t1 - t0));
            t0 = System.currentTimeMillis();
            Arrays.sort(integerArray, Comparator.naturalOrder());
            t1 = System.currentTimeMillis();
            System.out.println(i + ") Integer[ ] sort duration: " + (t1 - t0));
            t0 = System.currentTimeMillis();
            Arrays.parallelSort(integerArrayP, Comparator.naturalOrder());
            t1 = System.currentTimeMillis();
            System.out.println(i + ") Integer[ ] PARALLEL sort duration: " + (t1 - t0));
            t0 = System.currentTimeMillis();
            Arrays.sort(intArray);
            t1 = System.currentTimeMillis();
            System.out.println(i + ") int[ ] sort duration: " + (t1 - t0));
        }
    }
}



Results (on a Windows 7 64 bit OS running on CORE i3 processor): 结果 (在CORE i3处理器上运行的Windows 7 64位操作系统上):

1) ArrayList<Integer> sort duration: 200
1) Integer[ ] sort duration: 424
1) Integer[ ] PARALLEL sort duration: 414
1) int[ ] sort duration: 136
2) ArrayList<Integer> sort duration: 143
2) Integer[ ] sort duration: 101
2) Integer[ ] PARALLEL sort duration: 56
2) int[ ] sort duration: 33
3) ArrayList<Integer> sort duration: 124
3) Integer[ ] sort duration: 118
3) Integer[ ] PARALLEL sort duration: 96
3) int[ ] sort duration: 42
4) ArrayList<Integer> sort duration: 108
4) Integer[ ] sort duration: 102
4) Integer[ ] PARALLEL sort duration: 92
4) int[ ] sort duration: 57
5) ArrayList<Integer> sort duration: 142
5) Integer[ ] sort duration: 113
5) Integer[ ] PARALLEL sort duration: 118
5) int[ ] sort duration: 31
6) ArrayList<Integer> sort duration: 113
6) Integer[ ] sort duration: 103
6) Integer[ ] PARALLEL sort duration: 58
6) int[ ] sort duration: 32
7) ArrayList<Integer> sort duration: 115
7) Integer[ ] sort duration: 116
7) Integer[ ] PARALLEL sort duration: 57
7) int[ ] sort duration: 33
8) ArrayList<Integer> sort duration: 115
8) Integer[ ] sort duration: 115
8) Integer[ ] PARALLEL sort duration: 58
8) int[ ] sort duration: 31
9) ArrayList<Integer> sort duration: 114
9) Integer[ ] sort duration: 101
9) Integer[ ] PARALLEL sort duration: 52
9) int[ ] sort duration: 32
10) ArrayList<Integer> sort duration: 113
10) Integer[ ] sort duration: 114
10) Integer[ ] PARALLEL sort duration: 57
10) int[ ] sort duration: 32

EDIT : Added functionality to sort a Integer array. 编辑 :添加了对Integer数组进行排序的功能。
EDIT : Added functionality to sort a Integer array using Parallel sort. 编辑 :添加了使用并行排序对Integer数组进行排序的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM