一、  容器类:

下图摘自《Java编程思想》,很好地展示了整个容器类的结构。

由上图可知,容器类库可分为两大类,各自实现了Collection接口和Map接口,下面就常见的类进行一下分类:

实现Collection接口的容器类

Collection 

├List 

│├LinkedList 

│├ArrayList 

│└Vector 

│ └Stack 

├Set

│├TreeSet

│└HashSet

└LinkedHashSet

├Queue

│├LinkedList

│├DelayQueue

│└PriorityQueue

实现Map接口的容器类

Map 

├HashMap

└LinkedHashMap

├Hashtable

├IdentityHashMap

├TreeMap

└WeakHashMap

容器类由两个顶层接口自上而下扩展:

  • Collection:
    存放独立元素的序列
  • Map:存放key—value类型的键值对元素。

  其中值得注意的是:Collection提供了Iterable()模式,可以获取到Iterator对集合内的元素进行遍历,而Map则需要先得到Collection进而得到Iterator进行遍历。

  其中
接口List、Set、Queue实现了Collection接口,对应的List、Set和Queue又有其具有实现的类。实现了Map接口的主要有HashMap、LinkedHashMap、Hashtable、IdentityHashMap、TreeMap、WeakHashMap。

二、  实现Collection接口的容器类

  下面就List、Set和Queue下的几种常见容器展开简要的介绍

2.1  List接口

  两种典型实现:

  • LinkedList:

  底层实现为链表,对于这种实现结构而言,插入和删除操作效率高,而随机访问元素时效率较ArrayList低。

  同时,又由于LinkedList实现了Deque接口,故而它还能提供List接口中没有定义的方法,专门用于操作表头和表尾的元素,可以当做堆栈和队列使用。

  • ArrayList:

底层实现为数组,此种结构在随机访问和查询时效率高,而在进行插入和删除操作时效率较低。此外,由于其底层实现是数组,故而当数组大小不足需要增加存储空间时,就需要将现有数组中已有的数据复制到新的存储空间中。

两种弃用的List实现:

  • Vector:

Vector和ArrayList一样也是通过数组实现的,故而其特性和ArrayList类似(Vector底层数组实现在扩容时是扩展1倍,而ArrayList则扩展50%+1个),其中值得特别注意的一点是Vector是一种线程安全的容器,即在某一时刻只有一个线程能够写Vector,避免在多线程同时写时引起的不一致性,但由于实现同步(synchronized关键字)需要较高的代价,故访问速度较慢。

  • Stack:

是Vector的一个子类,实现了一个标准的后进先出的栈。(现在实现堆栈的功能一般使用LinkedList)

2.2 Set接口

是一种不包含重复元素的Collection,同时Set允许null元素。加入set的元素必须定义equals()方法来确保对象的唯一性。

几种典型的实现:

  • Hashset:

利用哈希函数进行了查询效率上的优化,是一种为快速查找而设计的Set,存入其中的元素必须定义hashCode();

  • LinkedHashSet:

具有Hashset的查询速度,且内部使用链表来维护元素的顺序。元素同样必须定义HashCode()方法

  • TreeSet:

保持有序的Set(实现了SortedSet接口),底层结构为红黑树,使用它可以从Set中得到有序的序列。元素必须实现Comparable接口

2.3  Queue接口:

  • PriorityQueue:

存储在其中的元素该需要实现Comparable接口,即自己完成优先级的定义

  • Deque:

双向队列,可以在任何一段添加或移除元素。其中LinkedList实现了Deque接口,可实现队列或栈的数据结构。

三、实现Map接口的容器类

  Map没有继承Collection的接口,其提供了key到value的映射,一个Map中不能包含相同的key,每个key只能映射一个value。

  几种典型的实现:

  • Hashtable:

  线程安全

  任何非空(non-null)的对象都可作为key或者value。

  添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。

通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。

由于key的对象将通过计算其散列函数确定与之对应的value的位置,因此任何作为key的对象必须实现hashcode和equeals方法。

  • HashMap:

线程不安全

HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低

  • IdentityHashMap:

比较键(和值)时使用引用“==”代替equal。即在 IdentityHashMap 中,当且仅当 (k1==k2) 时,才认为两个键 k1 和 k2 相等

而在正常 Map 实现(如 HashMap)中,当且仅当满足下列条件时才认为两个键 k1 和 k2 相等:(k1==null ? k2==null : e1.equals(e2)))。

该类是应用于特定场景下,即当我们必须使用地址相等来判断值相等的场合,以及我们确定只要其地址不相等,则其equals方法的结果也必定不相等的场合。

一个很好的例子就是线程本地存储中的ThreadLocal类,该类的原理是根据Thread从其内部的Map中获取线程独立的值,那么当我们使用只判断地址相等的IdentityHashMap就会比HashMap要快一些。

  • WeakHashMap:
    WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。
  • ConcurrentHashMap

线程安全的Map,与HashTable不同的,它的线程安全的实现不涉及到同步加锁,它引入了一个“分段锁”的概念,即将一个大的Map拆分成多个”HashTable”(实质上是Segment),当多线程访问容器中不同数据段的数据时,线程间就不存在锁的竞争关系。

ConcurrentHashMap是由Segment数组和HashEntry数组结构组成。其中Segment是一种可重入锁,HashEntry则用于存储键值对数据。

Segment的结构和HashMap类似,是一种数组和链表的结构。一个Segment中包含一个HashEntry数组。每个HashEntry是一个链表结构的元素。每个Segment守护着 一个HashEntry中的元素,当要对HashEntry数组的数据进行修改时,必须首先获得与它对应的Segment锁。

三、怎么选用容器类

  在日常开发中,怎么选用合适的容器类关乎到程序的性能以及正确性等,所以怎么选用合适的容器类很关键。

  首先一点,容器类中存储的都是对象的引用,而非对象本身。出于便利的角度,一般简称对象的引用为对象。正如上面讲到的不同的容器存储的对象类型不同,并且具有的方法也不同,或是在进行相同操作时的效率也存在差异。

  简单来讲,我们将存储的对象分为元素和键值对两种。

  元素一般采用实现Collection接口的容器类存储。又根据元素是否有序(TreeSet),元素是否唯一有所区别(实现Set接口的类),是否要求线程安全(Vector),常进行的操作(ArrayList和LinkedList的选用)等要求进行筛选;

  而键值对则采用实现Map接口的容器类进行存储,又根据是否要求线程安全(ConcurrentHashMap)、是否有必要进行内存的释放(针对内存优化的WeakHashMap)、是否要求有序(TreeMap)、IdentityHashMap(是否可以用==替换equals来提示效率)等要求来进行筛选。

java容器类的更多相关文章

  1. Java容器类接口的选择

    我们知道Java容器类实际提供了四类接口:Map,List,Set和Queue,如下图所示,每种接口都有不止一个版本的实现,如果在实际编写程序时需要使用某种接口时该如何选择. 从Oracle的Java ...

  2. Java容器类概述

    1.简介 容器是一种在一个单元里处理一组复杂元素的对象.使用集合框架理论上能够减少编程工作量,提高程序的速度和质量,毕竟类库帮我们实现的集合在一定程度上时最优的.在Java中通过java.util为用 ...

  3. java 容器类大集结

    这个世界是程序员的世界,归根到底是数据的世界,要统治这个世界,首先要学会征服数据. 没有最好的,只有最合适的,如何在不同的环境先选择最优的存储的结构呢?且看下文分解: 以下内容部分来自网络,参考: h ...

  4. 【转】java 容器类使用 Collection,Map,HashMap,hashTable,TreeMap,List,Vector,ArrayList的区别

    原文网址:http://www.360doc.com/content/15/0427/22/1709014_466468021.shtml java 容器类使用 Collection,Map,Hash ...

  5. java容器类3:set/HastSet/MapSet深入解读

    介绍 Set:集合,是一个不包含重复数据的集合.(A collection that contains no duplicate elements. ) set中最多包含一个null元素,否者包含了两 ...

  6. java容器类4:Queue深入解读

    Collection的其它两大分支:List和Set在前面已近分析过,这篇来分析一下Queue的底层实现. 前三篇关于Java容器类的文章: java容器类1:Collection,List,Arra ...

  7. Java容器类List、ArrayList、Vector及map、HashTable、HashMap的区别与用法

    Java容器类List.ArrayList.Vector及map.HashTable.HashMap的区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数 ...

  8. java容器类---概述

    1.容器类关系图 虚线框表示接口. 实线框表示实体类. 粗线框表示最经常使用的实体类. 点线的箭头表示实现了这个接口. 实线箭头表示类能够制造箭头所指的那个类的对象. Java集合工具包位于Java. ...

  9. Java容器类Collection,List,Set,Map.,Iterator,Collections工具类,Arrays工具类,Comparable

    Java容器类Collection,List,Set,Map.,Iterator,Collections工具类,Arrays工具类,Comparable接口,泛型 Collection,List,Se ...

  10. java容器类总结

    1.java容器分类图 说明:左图为简化图(其中粗线部分是重点的容器),右图为完整容器分类图                          2.容器类接口和抽象容器类 2.1 说明 容器接口是容器 ...

随机推荐

  1. for语句输出三角形

    public class yuju { public static void main(String[] args) { ; i<; i++) { ; j<=i;j++) { System ...

  2. EntityFramework Core高并发深挖详解,一纸长文,你准备好了吗?

    前言 之前有关EF并发探讨过几次,但是呢,博主感觉还是有问题,为什么会觉得有问题,其实就是理解不够透彻罢了,于是在项目中都是用的存储过程或者SQL语句来实现,利用放假时间好好补补EF Core并发的问 ...

  3. 【算法功底】LeetCode 292 Nim Game

    You are playing the following Nim Game with your friend: There is a heap of stones on the table, eac ...

  4. 使用FSharp 探索Dotnet图像处理功能1--反色变化

    坚持写博客是最近的目标.加油. 业余学习fsharp以来一直觉得这才是Dotnet开发,或者说所有开发者应该拥有的语言.配合Visual Studio的代码提示,即时执行窗口.开发程序有着极大的乐趣. ...

  5. WebService基础学习(三)—CXF

    一.什么是CXF?      Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF.Apache ...

  6. Git版本管理荟萃

    用惯了svn,突然转到git难免有点不适,写个笔记好好备忘总结一番. 一.先看历史(imooc上的一个图): 二.git与svn GIT跟SVN一样有自己的集中式版本库或服务器.但,GIT更倾向于被使 ...

  7. OCR文字识别帮助录入文字信息

    OCR文字识别是指将图片.照片上的文字内容,直接转换为可编辑文本的过程.目前各行各业不断地应用文字识别产品,解决文字录入工作的烦恼,提高工作效率. OCR文字识别用在哪里? 一个做社区工作的朋友透露, ...

  8. 自动生成数学题型一 (框架Struts2) 题型如(a+b=c)

    1. 加减乘除 1.1 随机生成制定范围的整数 /** * 随机产生一个被限定范围的整数 * * @param num1 * 定义起始范围 num1 * @param num2 * 定义终止范围 nu ...

  9. netcore实践:跨平台动态加载native组件

    缘起netcore框架下实现基于zmq的应用. 在.net framework时代,我们进行zmq开发由很多的选择,比较常用的有clrzmq4和NetMQ. 其中clrzmq是基于libzmq的Int ...

  10. 纯JS实现图片验证码功能并兼容IE6-8

    最近要搞一个图片验证码功能,但是又不想自己写后台代码.于是自己准备搞一个纯前端的验证码功能,于是网上搜索了一下,找到一个插件gVerify.js,简单好用,实现完美.不过后面接到说要兼容IE8,想想也 ...