java面试总结(五) —— Collection、List、ArrayList、LinkList、Vector、Set

Collection

Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些 Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类, Java SDK提供的类都是继承自Collection的“子接口”如List和Set。
  所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的 Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。
  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:

terator it = collection.iterator(); // 获得一个迭代子
while(it.hasNext()) {
  Object obj = it.next(); // 得到下一个元素
}

  由Collection接口派生的两个接口是List和Set。collection的其子类如下所示:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set

注:Collection与Collections的不同,Collection是最基本的集合接口,其子类提供各种集合,但是Collections则是一个工具类,提供了操作集合的方法,如用于对集合中元素进行排序、搜索、取最小值、最大值以及线程安全等各种操作,它是服务于Collection的。

List

一个 List 是一个元素有序的、可以重复、可以为 null 的集合(有时候我们也叫它“序列”)。

Java 集合框架中最常使用的几种 List 实现类是 ArrayList,LinkedList 和 Vector。在各种 List 中,最好的做法是以 ArrayList 作为默认选择。 当插入、删除频繁时,使用 LinkedList,Vector 总是比 ArrayList 慢,所以要尽量避免使用它,具体实现后续文章介绍。

List 的数据结构就是一个序列,存储内容时直接在内存中开辟一块连续的空间,然后将空间地址与索引对应。List 接口的实现类在实现插入元素时,都会根据索引进行排列,List 的元素在存储时互不干扰,没有什么依赖关系,所以其能保证 List 中的元素 “有序”、“可以重复”的。

除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个 ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。

list与Array对比

相似之处

都可以表示一组同类型的对象
都使用下标进行索引

不同之处

list array
数组可以存任何类型元素 List 不可以存基本数据类型,必须要包装
数组容量固定不可改变 List 容量可动态增长
数组效率高 List 由于要维护额外内容,效率相对低一些

ArrayList

ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本。

它提供了动态的增加和减少元素,它允许所有元素,包括null。实现了Collection和List接口,可以灵活的设置数组的大小。要注意的是ArrayList并不是线程安全的,因此一般建议在单线程中使用ArrayList。

由于其底层使用数组保存所有元素所以其操作基本上是对数组的操作。

ArrayList 提供了三种方式的构造器:

public ArrayList():可以构造一个默认初始容量为10的空列表;
public ArrayList(int initialCapacity) : 构造一个指定初始容量的空列表;
public ArrayList(Collection<? extends E> c) : 构造一个包含指定 collection 的元素的列表,这些元素按照该collection的迭代器返回它们的顺序排列的。

在对 ArrayList 中存储元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容,扩容原来的一半,以满足添加数据的需求。数组扩容有两个方法,其中开发者可以通过一个 public 的方法ensureCapacity(int minCapacity)来增加 ArrayList 的容量,而在存储元素等操作过程中,如果遇到容量不足,会调用priavte方法private void ensureCapacityInternal(int minCapacity)实现。

LinkedList

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈队列双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作,允许null元素
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆
LinkedList 是非同步的,即非线程安全的,一种解决方法是在创建List时构造一个同步的List:List list = Collections.synchronizedList(new LinkedList(...));

LinkedList是通过节点直接彼此连接来实现的。每一个节点都包含前一个节点的引用,后一个节点的引用和节点存储的值。当一个新节点插入时,只需要修改其中保持先后关系的节点的引用即可,当删除记录时也一样。

LinkedList相对于ArrayList来说,是可以快速添加,删除元素ArrayList添加删除元素的话需移动数组元素,可能还需要考虑到扩容数组长度

linkList ArrayList
允许null元素 允许null元素
非线程安全 非线程安全
节点连接实现 数组实现
添加、删除元素速度快 添加、删除元素慢
读取元素慢 读取元素快
链式存储 顺序存储

Vector

Vector非常类似ArrayList,是可实现自动增长的对象数组。

Vector**是有序的,可以重复的**。

Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的 Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常(fail-fast机制)。

Vector也需要进行扩容,Vector默认增长为原来一倍。由于扩容需要的性能问题,所以如果我们知道数据的大概数量,我们可以指定其初始容量。

Vector ArrayList
线程安全 非线程安全
扩容默认扩容一倍 扩容默认扩0.5倍

Set

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。

同时因为其是一个抽象的接口:所以不能直接实例化一个set对象。(Set s = new Set() )错误

Set接口最长用的两大实现:HashSet TreeSet
TreeSet:会将里面的元素默认排序。

猜你喜欢

转载自blog.csdn.net/qq_33206732/article/details/80364033
今日推荐