遍历方式有以下几种:
最佳实践:Java Collections 框架中提供了一个 RandomAccess 接口,用来标 记 List 实现是否支持
Random Access。如果一个数据集合实现了该接口,就意味着它支持 Random Access,按位置读 取元素的平均时间复杂度为 O(1),如ArrayList。如果没有实现该接口,表示不支持 Random Access,如LinkedList。 推荐的做法就是,支持Random Access 的列表可用 for 循环遍历,否则建议 用 Iterator 或 foreach 遍历。
例如ArrayList推荐使用for循环遍历,LinkedList推荐使用Iterator或者foreach遍历。
ArrayList的优点如下:
ArrayList 的缺点如下:
数组转 List:使用 Arrays. asList(array) 进行转换。
List 转数组:使用 List 自带的 toArray() 方法。代码示例:
1 // list to array
2 List list = new ArrayList();
3 list.add("123");
4 list.add("456");
5 list.toArray();
6
7 // array to list
8 String[] array = new String[]{"123","456"};
9 Arrays.asList(array);
综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。
补充:数据结构基础之双向链表
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合。
速度:
ArrayList、Vector 底层的实现都是使用数组方式存储数据。数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。
而LinkedList 使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但插入数据时只需要记录当前项的前后项即可,所以 LinkedList插入速度较快。
特性:
Vector 中的方法由于加了 synchronized 修饰,因此 Vector是线程安全容器,但性能上较ArrayList差。
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常消耗性能。
LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引,但是缺点就是查找非常麻烦,要丛第一个索引开始。
ArrayList和Vector都是用数组方式存储数据,此数组元素数要大于实际的存储空间,以便进行元素增加和插入操作,他们都允许直接用序号索引元素,但是插入数据元素涉及到元素移动等内存操作,所以查询数据快而插入数据慢。
LinkedList使用双向链表方式存储数据,按序号索引数据需要前向或后向遍历数据,所以查询数据慢,是插入数据时只需要记录前后项即可,所以插入的速度快。
ArrayList 不是线程安全的,如果遇到多线程场景,可以通过 Collections 的synchronizedList 方法将其转换成线程安全的容器后再使用。例如像下面这样:
1 List synchronizedList = Collections.synchronizedList(list);
2 synchronizedList.add("aaa");
3 synchronizedList.add("bbb");
4
5 for (int i = 0; i < synchronizedList.size(); i++) {
6 System.out.println(synchronizedList.get(i));
7 }
ArrayList 中的数组定义如下:
private transient Object[] elementData;
再看一下 ArrayList 的定义:
public class ArrayList extends AbstractList
implements List, RandomAccess, Cloneable, java.io.Serializable
可以看到 ArrayList 实现了 Serializable 接口,这意味着 ArrayList 支持序列化。
transient 的作用是说不希望 elementData 数组被序列化,重写了 writeObject 实现:
1 private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOE
xception{
2 *// Write out element count, and any hidden stuff*
3 int expectedModCount = modCount;
4 s.defaultWriteObject();
5 *// Write out array length*
6 s.writeInt(elementData.length);
7 *// Write out all elements in the proper order.*
8 for (int i=0; i
11 throw new ConcurrentModificationException();
12 }
每次序列化时,先调用 defaultWriteObject() 方法序列化 ArrayList 中的非transient 元素,然后再遍历
elementData。只序列化已存入的元素,这样既加快了序列化的速度,又减小了序列化之后的文件大
小。
List , Set 都是继承自Collection 接口
List 特点:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。
Set 特点:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是HashSet、LinkedHashSet 以及 TreeSet。
另外 List 支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,
无法用下标来取得想要的值。
Set和List对比
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
Set篇