java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java中的容器

Java中的ArrayList、LinkedList、HashSet等容器详解

作者:haihui_yang

这篇文章主要介绍了Java中的ArrayList、LinkedList、HashSet等容器详解,集合表示一组对象,称为其元素,有些集合允许重复元素,而另一些则不允许,有些是有序的,有些是无序的,需要的朋友可以参考下

Java 容器的继承关系图

java容器的继承关系图

集合表示一组对象,称为其元素。有些集合允许重复元素,而另一些则不允许。有些是有序的,有些是无序的。

JDK 没有提供这个接口的任何直接实现:它提供了更具体的子接口(如 Set、List 和 Queue)的实现。

一、List

有序的元素序列,可以通过索引(即下标)访问元素。

1、ArrayList

基于索引的动态数组

(1)实现了可变大小的数组,允许所有元素,包括 null 值,底层使用数组(array)保存所有元素,所以随机访问很快,可以直接通过元素的下标值获取元素的值(size、isEmpty、get、set、iterator、listIterator 这些方法的时间复杂度均为 O(1)),但插入和删除较慢,因为需要移动 array 里的元素(即 add、remove 的时间复杂度为 O(n)),未实现同步。

(2)每一个 ArrayList 实例都有一个容量(capacity),使用 Lists.newArrayList() 创建的是一个 capacity = 0 的 List,当在添加第一个元素的时候会扩展到默认的初始化容量(10),当对其添加的数据大于它的 capacity 就必须改变 ArrayList 的 capacity(一般是原来大小的 1.5 倍),而这种 resize 操作是有开销的,所以如果事先知道数组的大小为 actualSize,可以按照下面的方式初始化一个大小固定的 ArrayList,以减去 resize 的开销:

int actualSize = 100;
List<Object> objectArrayList = Lists.newArrayListWithCapacity(actualSize);

(3)iterator() 和 listIterator(int) 返回的迭代器是快速失败(fail-fast)的:

如果在迭代器创建之后,原始的 List 被修改了,迭代器会抛一个 ConcurrentModificationException,原因是 Iterator 里的 expectedModCount 和 List 的 modCount 不一致。在迭代的时候如果需要修改 List,只能通过 Iterator 的 remove 方法修改。

(4)从 Array 创建 ArrayList 的坑:

Object[] array = new Object[10];
List<Object> arrayList1 = Lists.newArrayList(Arrays.asList(array));
List<Object> arrayList2 = Arrays.asList(array);
// 需要注意的是:Arrays.asList(array) 返回的是一个 fixed size array(上面的arrayList2),如果不用 Lists.newArrayList(Arrays.asList(array))(上面的arrayList2)包装起来的话,对它进行 add 或 remove 操作就会报 java.lang.UnsupportedOperationException

2、LinkedList

双链表数据结构

(1)实现了 List 接口,允许 null 值,底层使用链表保存所有元素(除了要存数据外,还需存 next 和 pre 两个指针,因此占用的内存比 ArrayList 多),因此,向 LinkedList 里面插入或移除元素时会特别快,但是对于随机访问方面相对较慢(需要遍历链表,遍历的时候会根据 index 选择从前往后或从后往前遍历,如果 index < (size >> 1) 则从前往后),无同步,想要实现同步可以这样:

List list = Collections.synchronizedList(new LinkedList(...)); 

(2)LinkedList 还拥有了可以使其用作堆栈(stack),队列(queue)或者双向队列(deque)的方法(拥有 pop、push,从 LinkedList 的首部或尾部添加或删除元素等方法)。

3、Vector

实现了同步的 ArrayList

和 ArrayList 几乎一模一样,除开以下两点:

4、Stack

Java 的堆栈实现是糟糕的,它继承了 Vector

Stack 表示后进先出(LIFO)堆栈,继承于 Vector ,新增了五个方法:

Deque<Integer> stack = new ArrayDeque<Integer>();

5、ArrayList、LinkedList 和 Vector 总结

(1)当集合内的元素需要频繁插入,删除操作时应使用 LinkedList;当需要频繁查询时,使用 ArrayList(大部分情况是使用 ArrayList);

(2)ArrayList 和 LinkedList 都未实现同步,Vector 是在 ArrayList 的基础上实现了同步,是线程安全的;

(3)相比而言,LinkedList 占的内存要比 ArrayList 大(因为它必须维护下一个和前一个节点的链接)。

二、Set

不包含重复元素的集合。

1、HashSet

2、LinkedHashSet

3、SortedSet

4、TreeSet(SortedSet 的实现)

三、Queue

为在处理之前保存元素而设计的集合。

1、PriorityQueue

2、Deque

双向队列,支持两端元素的插入与删除。Deque 也可以用作 LIFO(后进先出)堆栈。这个接口应优先于传统的 Stack 类使用。

不支持通过索引访问元素。

虽然 Deque 实现不是严格要求禁止插入 null 值,强烈建议任何允许 null 元素的 Deque 实现的用户不要利用插入空值的能力,因为null被一些方法用作特殊返回值来指示该双端队列是空的。

3、ArrayDeque(Deque 的实现)

到此这篇关于Java中的ArrayList、LinkedList、HashSet等容器详解的文章就介绍到这了,更多相关Java中的容器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文