当我们需要创建一个数组的时候,可能通常会想到[],但是很多大牛是不建议用默认的这个数组的,因为他太不灵活了。java有自带的动态数组,就是从Collection继承来的几个list--- Arraylist Linkedlist 和vector
记得我原来一直用vector(不知道为啥,第一眼看他最顺眼)。后来被大牛鄙视过。。 被教育说Arraylist效率是最高的,于是网上搜资料,自己测试这三个类的效率。
arraylist是基于数组实现的。数组大家都清楚,他的随机读取是最快的,顺序添加的话,他跟linkedlist不相上下,但是如果是随机的添加数,因为要涉及到数组随机位置添加后,后边的数统一往后移一位,所以效率超低,如果用arraylist的话,最好避免这种情况。
Linkedlist是基于链表实现的,如果程序有随机位置添加的需求,最好用这个。不过这个动态数组的随机访问效率不高,但是如果是遍历的话,他可以借助迭代器。如果你的程序里很少用到随机访问的话,他是个不错的选择。
Vector是线程安全的,他跟arraylist的关系,就像hashtable跟hashmap的关系一样。如果你的程序需要一个多线程共同访问和赋值的动态数组,那vector是个不错的选择。
接下来,附上测试代码和结果:
private static void arrayTest(){ List<String> l = new ArrayList<String>(); long start = System.currentTimeMillis(); //赋值一百万个数 for(int i = 0; i< 1000000; i++){ l.add(""+new Random().nextInt(1000000)); } long end1 = System.currentTimeMillis(); //随机插入10000个数 for(int i = 0; i< 10000; i++){ l.add(new Random().nextInt(100000), ""); } long end2 = System.currentTimeMillis(); //随机获取10000个数 for(int i = 0; i< 10000; i++){ l.get(new Random().nextInt(100000)); } long end3 = System.currentTimeMillis(); //遍历 Iterator<String> i = l.iterator(); while(i.hasNext()){ String s = i.next(); } long end4 = System.currentTimeMillis(); System.out.println("arrayList:"); System.out.println("赋值一百万个数:\t"+(end1 - start)); System.out.println("随机插入10000个数:\t"+(end2 - end1)); System.out.println("随机获取10000个数:\t"+(end3 - end2)); System.out.println("遍历:\t"+(end4 - end3)); } private static void linkedListTest(){ List<String> l = new LinkedList<String>(); long start = System.currentTimeMillis(); //赋值一百万个数 for(int i = 0; i< 1000000; i++){ l.add(""+new Random().nextInt(1000000)); } long end1 = System.currentTimeMillis(); //随机插入10000个数 for(int i = 0; i< 10000; i++){ l.add(new Random().nextInt(100000), ""); } long end2 = System.currentTimeMillis(); //随机获取10000个数 for(int i = 0; i< 10000; i++){ l.get(new Random().nextInt(100000)); } long end3 = System.currentTimeMillis(); //遍历 Iterator<String> i = l.iterator(); while(i.hasNext()){ String s = i.next(); } long end4 = System.currentTimeMillis(); System.out.println("LinkedList:"); System.out.println("赋值一百万个数:\t"+(end1 - start)); System.out.println("随机插入10000个数:\t"+(end2 - end1)); System.out.println("随机获取10000个数:\t"+(end3 - end2)); System.out.println("遍历:\t"+(end4 - end3)); } private static void vectorTest(){ Vector<String> l = new Vector<String>(); long start = System.currentTimeMillis(); //赋值一百万个数 for(int i = 0; i< 1000000; i++){ l.add(""+new Random().nextInt(1000000)); } long end1 = System.currentTimeMillis(); //随机插入10000个数 for(int i = 0; i< 10000; i++){ l.add(new Random().nextInt(100000), ""); } long end2 = System.currentTimeMillis(); //随机获取10000个数 for(int i = 0; i< 10000; i++){ l.get(new Random().nextInt(100000)); } long end3 = System.currentTimeMillis(); //遍历 Iterator<String> i = l.iterator(); while(i.hasNext()){ String s = i.next(); } long end4 = System.currentTimeMillis(); System.out.println("vectorList:"); System.out.println("赋值一百万个数:\t"+(end1 - start)); System.out.println("随机插入10000个数:\t"+(end2 - end1)); System.out.println("随机获取10000个数:\t"+(end3 - end2)); System.out.println("遍历:\t"+(end4 - end3)); }
arrayList: 赋值一百万个数: 237 随机插入10000个数: 3663 随机获取10000个数: 1 遍历: 13 linkedList: 赋值一百万个数: 439 随机插入10000个数: 6947 随机获取10000个数: 8364 遍历: 29 vectorList: 赋值一百万个数: 273 随机插入10000个数: 4083 随机获取10000个数: 2 遍历: 27
赋值一百万个数 | 随机插入10000个 | 随机获取10000个 | 遍历 | |
ArrayLisst | 237 |
3663 | 1 | 13 |
LinkedList | 439 | 6947 | 8364 | 29 |
Vector | 273 | 4083 | 2 | 27 |
从表里可以看到,Arraylist表现得最优秀。
好像跟预想不太一样。。 arraylist的随机插入应该是比linkedlist慢的。。 回头看代码,发现随机插入的时候,用的是取十万以内的随机数,随机性很强,而且linkedlist如果要找第十万个数,是从前往后依次遍历的,效率很低。修改一下代码,让linkedlist和arraylist分别插入前1000个位置数据,结果arraylist耗时518毫秒,linkedlist耗时4毫秒。。。
如果你的数组不大,而且插入很频繁,那么linkedlist是不错的选择。不过如果你的数组很大(比如程序里面的100万),而且插入的位置不一定,可能前可能后也可能中间位置,那么linkedlist未必是最好的选择,这时候如果要考虑效率的话,最好自己写一个动态数组,兼顾arraylist和linkedlist的优点-- 数组查找的速度,链表插入的效率。