浅谈Java 容器类(Set、List、Map)

Java.util中有许多经常能用到的又好用的容器类。就让我们来缕一缕其中的关系。

根据上图我们详细地看到各个容器类的之间的继承,和实现关系。

也许有人要问:我知道的Array怎么没在这?

没错,数组的确也是常用的数据结构,但是其只能放基本数据类型,所以并算不是容器类。(值得一提的是java.util包中确实有一个Arrays类,其中包含许多针对基本类型数组 [] 的静态实用工具方法,而在java.lang.reflect包中也有一个Array类,其中也包含了访问及创建数组的静态方法,只不过对基本类型数组和集合型数组都可用)

import java.reflect.Array;
import java.util.*;

//仅为展示,跳过步骤
ArrayList<Integer> arr=new ArrayList<Integer>();
int [] arr2=new int[5];

//类Array访问数组,对两者皆有效
int get2=Array.getInt(arr.2);
//get2  =Array.getInt(arr2.2);

//工具类Arrays 折半查找
get2  =Arrays.binarySearch(arr, 2);

从上图可以了解到,Collection和Map是Java容器中两个基本数据类型。这两者的区别也很明确:

  • Collection 单列集合,即每个位置只能保存一个元素。

  • Map 双列集合,以键值对映射的形式存储,且不能包含重复的键、每个键最多只能映射一个值。
    上面两种均是接口,不能实例化。同样为接口的还有Set、List。

  • Set (集)即是一组没有重复对象的集合(不一定是有序)。

  • List (链表)其实和数组一样是相当基础数据结构,上一个元素指向下一个元素。
    接下来才是我们常使用到的容器类:

  • ArrayList

  • LinkList

  • Vector

  • HashSet

  • TreeSet

  • HashTable

  • HashMap

  • TreeMap
     

ArrayList、LinkList、Vector

这三兄弟都实现了List接口,而其中 ArrayList、Vector两者则都是基于Array的List。具体的功能和异同:

ArrayList:也叫动态数组,继承自AbstractList类,实现List接口

  • 其大小可以动态地增加、减少,也可以随着放入的元素而增加大小(当然你也可以在构造的时候指定大小)

  • 可以放置不同类型、重复的对象(这样不方便使用)

  • 其维护插入顺序(根据检索),但是随机访问(基于内存)

  • 函数并不是同步加锁的

  • Vector*:也叫向量类

  • 其大小也是可以动态地变化

  • 可以放置不同类型、重复的对象

  • 同样也是维护插入顺序

  • 维护插入顺序,同样也是随机访问(这是Vector、ArrayList通过检索访问速度快的优势)

  • 函数实现了同步加锁(线程安全)

  • LinkList*:是继承于AbstractSequentialList的双向链表(大小可变),实现List、Deque、Queue接口

  • 可以被当作堆栈、队列或双端队列(实现了接口)

  • 维护插入顺序(基于检索),但是顺序访问(链表性质:顺序访问速度快,检索访问速度慢)

  • 可以放置不同类型、重复的对象

  • 函数不是同步的

HashMap、TreeMap、HashTable

这三者都实现了Map接口,都是以键值对形式存储元素,同时这三者也是将键的值作为自变量,使用一套算法计算值的存储位置以实现键值对映射,和解决冲突。均可放置不同类型的,不重复的对象。

HashTable:也叫哈希表,扩展了Dictionary类

  • 包含唯一的元素,其键和值都不能为空

  • 函数是同步加锁的

  • 遍历时可以使用Enumeration,也可以使用Iterator

  • HashMap*:和哈希表很相似,哈希值的处理方法

  • 最多只允许一条记录的键为空,允许多条记录的值为空

  • 遍历时使用Iterator

  • 函数不是同步加锁的

  • TreeMap*:和前两者最大不同就是可以保存插入顺序

  • TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。

  • 最多只允许一条记录的键为空,允许多条记录的值为空

  • 函数并不是同步的

  • 遍历时也是使用Iterator

HashSet、TreeSet

这两者都是实现了Set接口。均可放置不同类型的对象。

HashSet:扩展了AbstractSet,并实现了Set接口。

  • 既不允许存储相同的元素,也不保存元素的顺序

  • 基于HashMap实现的,将其中的值存储了一个 PRESENT,它是一个静态的 Object 对象

  • 检索速度快,遍历时使用Iterator

  • 函数不是同步的

  • TreeSet*:和上面HashMap、TreeMap之间关系很像。

  • 不允许存储相同的元素,但是能保存元素的顺序

  • 函数不同步
    仅为整理关系,提供选择资料,不提供各容器类方法注记。

2017-03-20 更新:自己用脑洞图画的关系图(包含Java中基本数据结构)

相关资料:

HashSet用法:http://blog.csdn.net/tingzhiyi/article/details/52152487

HashMap,HashTable,TreeMap区别和用法

Map总结:http://www.chawenti.com/articles/20110.html

Java 容器类讲解

API: http://docs.oracle.com/javase/8/docs/api/

觉得不错不妨打赏一笔