List家族的三个最常用实现类: 1.ArrayList (非同步) 2.linkedList (非同步) 3.Vector(同步)
下面我们重点对ArrayList和LinkedList这俩个进行讲解。 ArrayList:
1.从单词上看前面是Array后面是List,他就是以数组实现的列表。他有个不好的地方就是不是线程安全的。
2.因为他的底层是数组形式实现的,所以使用类似于a[0],a[1],a[2]可以快速访问元素,这是一个非常重要的特点。
3.也因为底层的数组结构,不适合在指定位置插入和删除操作,中间插入一个元素的时候后面的元素就要向右挪动。中间删除一个元素的时候就要向左挪动。当ArrayList中的元素很多时,指定位置插入删除会早上庞大的元素挪动,效率很差。
4.ArrayList适合存储变动不大,主要用于查询的数据。
5.ArrayList在元素填满容器时会自动扩充容器大小的50%。
LinkedList:
1.是由双向链表实现的列表,链表支持快速插入删除操作,不支持同步。
2.顺序访问高效,插入删除高效,随机访问需要遍历效率差。
3.适用于经存储经常变化的数据。
两种集合的构造方法:LinkedList没有指定长度的构造方法,也没有扩容的行为,他可以是内存允许情况下的任意长度。 ArrayList的构造方法:
public ArrayList(int initialCapacity)
public ArrayList()
public ArrayList(Collection<? extends E> c)
LinkedList的构造方法:
public LinkedList()
public LinkedList(Collection<? extends E> c)
ArrayList和LinkedList的几种循环遍历: 方式一:
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
方式二:
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
方式三:
for(Object item : list) {
System.out.println(item);
}
方式四(Java 8):
list.forEach(new Consumer<Object>() {
@Override
public void accept(Object item) {
System.out.println(item);
}
});
方式五(Java 8 Lambda):
list.forEach(item -> {
System.out.println(item);
});
结论: 方式一的遍历方法对于RandomAccess接口的实现类ArrayList来说是一种性能很好的遍历方式。但是对于 LinkedList 这样的基于链表实现的 List,通过 list.get(i) 获取元素的性能差。
方式二和方式三两种方式的本质是一样的,都是通过 Iterator迭代器来实现的遍历。
方式三是增强版的 for循环,可以看作是方式二的简化形式。
方式四和方式五本质也是一样的,都是使用Java 8新增的 forEach 方法来遍历。
方式五是方式四的一种简化形式,使用了Lambda表达式。
综上:我们推荐使用Lambda遍历,不允许用方式一遍历LinkedList。