通过实例解析Java List正确使用方法
list是java中比较常用的集合类,关于list接口有很多实现类,本文就来简单介绍下其中几个重点的实现arraylist、linkedlist和vector之间的关系和区别。
list
list 是一个接口,它继承于collection的接口。它代表着有序的队列。当我们讨论list的时候,一般都和set作比较。
list中元素可以重复,并且是有序的(这里的有序指的是按照放入的顺序进行存储。如按照顺序把1,2,3存入list,那么,从list中遍历出来的顺序也是1,2,3)。
set中的元素不可以重复,并且是无序的(从set中遍历出来的数据和放入顺序没有关系)。
下面是java中的集合类的关系图。从中可以大致了解集合类之间的关系
java-collection-hierarchy
arraylist、 linkedlist 和 vector之间的区别
从上图可以看出,arraylist、 linkedlist 和 vector都实现了list接口,是list的三种实现,所以在用法上非常相似。他们之间的主要区别体现在不同操作的性能上。后面会详细分析。
arraylist
arraylist底层是用数组实现的,可以认为arraylist是一个可改变大小的数组。随着越来越多的元素被添加到arraylist中,其规模是动态增加的。
linkedlist
linkedlist底层是通过双向链表实现的。所以,linkedlist和arraylist之前的区别主要就是数组和链表的区别。
数组中查询和赋值比较快,因为可以直接通过数组下标访问指定位置。
链表中删除和增加比较快,因为可以直接通过修改链表的指针(java中并无指针,这里可以简单理解为指针。其实是通过node节点中的变量指定)进行元素的增删。
所以,linkedlist和arraylist相比,增删的速度较快。但是查询和修改值的速度较慢。同时,linkedlist还实现了queue接口,所以他还提供了offer(), peek(), poll()等方法。
vector
vector和arraylist一样,都是通过数组实现的,但是vector是线程安全的。和arraylist相比,其中的很多方法都通过同步(synchronized)处理来保证线程安全。
如果你的程序不涉及到线程安全问题,那么使用arraylist是更好的选择(因为vector使用synchronized,必然会影响效率)。
二者之间还有一个区别,就是扩容策略不一样。在list被第一次创建的时候,会有一个初始大小,随着不断向list中增加元素,当list认为容量不够的时候就会进行扩容。vector缺省情况下自动增长原来一倍的数组长度,arraylist增长原来的50%。
arraylist 和 linkedlist的性能对比
使用以下代码对arraylist和linkedlist中的几种主要操作所用时间进行对比:
arraylist<integer> arraylist = new arraylist<integer>(); linkedlist<integer> linkedlist = new linkedlist<integer>(); // arraylist add long starttime = system.nanotime(); for (int i = 0; i < 100000; i++) { arraylist.add(i); } long endtime = system.nanotime(); long duration = endtime - starttime; system.out.println("arraylist add: " + duration); // linkedlist add starttime = system.nanotime(); for (int i = 0; i < 100000; i++) { linkedlist.add(i); } endtime = system.nanotime(); duration = endtime - starttime; system.out.println("linkedlist add: " + duration); // arraylist get starttime = system.nanotime(); for (int i = 0; i < 10000; i++) { arraylist.get(i); } endtime = system.nanotime(); duration = endtime - starttime; system.out.println("arraylist get: " + duration); // linkedlist get starttime = system.nanotime(); for (int i = 0; i < 10000; i++) { linkedlist.get(i); } endtime = system.nanotime(); duration = endtime - starttime; system.out.println("linkedlist get: " + duration); // arraylist remove starttime = system.nanotime(); for (int i = 9999; i >=0; i--) { arraylist.remove(i); } endtime = system.nanotime(); duration = endtime - starttime; system.out.println("arraylist remove: " + duration); // linkedlist remove starttime = system.nanotime(); for (int i = 9999; i >=0; i--) { linkedlist.remove(i); } endtime = system.nanotime(); duration = endtime - starttime; system.out.println("linkedlist remove: " + duration);
结果:
arraylist add: 13265642
linkedlist add: 9550057
arraylist get: 1543352
linkedlist get: 85085551
arraylist remove: 199961301
linkedlist remove: 85768810
arraylist-vs-linkedlist1
他们的表现的差异是显而易见的。在添加和删除操作上linkedlist更快,但在查询速度较慢。
如何选择
如果涉及到多线程,那么就选择vector(当然,你也可以使用arraylist并自己实现同步)。
如果不涉及到多线程就从linkedlist、arraylist中选。 linkedlist更适合从中间插入或者删除(链表的特性)。 arraylist更适合检索和在末尾插入或删除(数组的特性)。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。