一、  容器类:

下图摘自《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. 使用github+hexo搭建博客笔记

    听说github上可以搭博客,而且不用自己提供空间和维护,哈哈哈 作为一名程序猿,github搭博客对我有种神奇的吸引力,赶紧动手试一试 关于如何使用hexo搭建博客网上好的教程多如牛毛,而且这篇博客 ...

  2. MySQL大数据量分页查询

    mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 测试实验 1.   直接用limit start, count分页语句, 也是我程序中用的方法: select * from p ...

  3. 记录一次坑爹的VM连接主机的路程

    因为之前电脑配置过虚拟机连接主机的过程,所以没有太在意,换电脑了之后配了两天结果没有配置成功; 首先配置静态ip: 1,编辑第一个文件/etc/sysconfig/network-scripts/if ...

  4. QQ第三方登录教程

    教程戳这里

  5. instance 网卡是如何被拉起来的?- 每天5分钟玩转 OpenStack(172)

    instance 的网卡是如何被配置并拉起的?这是理解和用好 cloud-init 非常关键的一步.我们先讨论一个最简单基础的场景:镜像中没有安装 cloud-init. 此时 instance 启动 ...

  6. 提高 webpack 构建 Vue 项目的速度

    前言 最近有人给我的 Vue2 后台管理系统解决方案 提了 issue ,说执行 npm run build 构建项目的时候极其慢,然后就引起我的注意了.在项目中,引入了比较多的第三方库,导致项目大, ...

  7. java 基础知识一 初识java

    java  基础知识一初识java 1.java语言的特点 (1)简洁有效(2)可移植性(3)面向对象(4)解释型(5)适合分布式计算 2.java的源文件扩展名为.java 编译后的扩展名为.cla ...

  8. 跟着刚哥梳理java知识点——IO(十五)

    凡是与输入.输出相关的类.接口都定义在java.io包下 java.io.File类 1.File是一个类,可以有构造器创建其对象.此对象对应着一个文件或者一个目录. 2.File中的类,仅涉及到如何 ...

  9. 通过一个小游戏开始接触Python!

    之前就一直嚷嚷着要找视频看学习Python,可是一直拖到今晚才开始....好好加油吧骚年,坚持不一定就能有好的结果,但是不坚持就一定是不好的!! 看着视频学习1: 首先,打开IDLE,在IDLE中新建 ...

  10. 关于/var/run/docker.sock

    译者按: 这篇博客介绍了什么是/var/run/docker.sock,以及如何使用/var/run/docker.sock与Docker守护进程通信,并且提供了两个简单的示例.理解这些,我们就可以运 ...