文档章节

Collection:List、SetMap:HashMap、HashTable

颖辉小居
 颖辉小居
发布于 2016/01/29 17:08
字数 3174
阅读 7
收藏 1
点赞 1
评论 0

基础知识

在 Java2中,有一套设计优良的接口和类组成了Java集合框架Collection,使程序员操作成批的数据或对象元素极为方便。这些接口和类有很多对抽象数据类型操作的API,而这是我们常用的且在数据结构中熟知的。例如Map,Set,List等。并且Java用面向对象的设计对这些数据结构和算法进行了封装,这就极大的减化了程序员编程时的负担。程序员也可以以这个集合框架为基础,定义更高级别的数据抽象,比如栈、队列和线程安全的集合等,从而满足自己的需要。 

Java2的集合框架,抽其核心,主要有三种:List、Set和Map。如下图所示: 

需要注意的是,这里的 Collection、List、Set和Map都是接口(Interface),不是具体的类实现。 List lst = new ArrayList(); 这是我们平常经常使用的创建一个新的List的语句,在这里, List是接口,ArrayList才是具体的类。 

常用集合类的继承结构如下: 
Collection<--List<--Vector 
Collection<--List<--ArrayList 
Collection<--List<--LinkedList 
Collection<--Set<--HashSet 
Collection<--Set<--HashSet<--LinkedHashSet 
Collection<--Set<--SortedSet<--TreeSet 
Map<--SortedMap<--TreeMap 
Map<--HashMap 

-----------------------------------------------SB分割线------------------------------------------ 

List: 
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下 >标)来访问List中的元素,这类似于Java的数组。 

Vector: 
基于数组(Array)的List,其实就是封装了数组所不具备的一些功能方便我们使用,所以它难易避免数组的限制,同时性能也不可能超越数组。所以,在可能的情况下,我们要多运用数组。另外很重要的一点就是Vector是线程同步的(sychronized)的,这也是Vector和ArrayList 的一个的重要区别。 

ArrayList: 
同Vector一样是一个基于数组上的链表,但是不同的是ArrayList不是同步的。所以在性能上要比Vector好一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。 

LinkedList: 
LinkedList不同于前面两种List,它不是基于数组的,所以不受数组性能的限制。 
它每一个节点(Node)都包含两方面的内容: 
1.节点本身的数据(data); 
2.下一个节点的信息(nextNode)。 
所以当对LinkedList做添加,删除动作的时候就不用像基于数组的ArrayList一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了,这是LinkedList的优势。 

List总结: 

  • 所有的List中只能容纳单个不同类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ]

 

  • 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]

 

  • 所有的List中可以有null元素,例如[ tom,null,1 ]

 

  • 基于Array的List(Vector,ArrayList)适合查询,而LinkedList 适合添加,删除操作



--------------------------------------NB分割线------------------------------------ 

Set: 
Set是一种不包含重复的元素的无序Collection。 

HashSet: 
虽然Set同List都实现了Collection接口,但是他们的实现方式却大不一样。List基本上都是以Array为基础。但是Set则是在 HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key作为Set的对应存储项。看看 HashSet的add(Object obj)方法的实现就可以一目了然了。 

Java代码 

public boolean add(Object obj) {   
   return map.put(obj, PRESENT) == null;   
}   

这个也是为什么在Set中不能像在List中一样有重复的项的根本原因,因为HashMap的key是不能有重复的。 

LinkedHashSet: 
HashSet的一个子类,一个链表。 

TreeSet: 
SortedSet的子类,它不同于HashSet的根本就是TreeSet是有序的。它是通过SortedMap来实现的。 

Set总结: 

  • Set实现的基础是Map(HashMap)

 

  • Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象



--------------------------------------2B分割线------------------------------------ 

Map: 
Map 是一种把键对象和值对象进行关联的容器,而一个值对象又可以是一个Map,依次类推,这样就可形成一个多级映射。对于键对象来说,像Set一样,一个 Map容器中的键对象不允许重复,这是为了保持查找结果的一致性;如果有两个键对象一样,那你想得到那个键对象所对应的值对象时就有问题了,可能你得到的并不是你想的那个值对象,结果会造成混乱,所以键的唯一性很重要,也是符合集合的性质的。当然在使用过程中,某个键所对应的值对象可能会发生变化,这时会按照最后一次修改的值对象与键对应。对于值对象则没有唯一性的要求,你可以将任意多个键都映射到一个值对象上,这不会发生任何问题(不过对你的使用却可能会造成不便,你不知道你得到的到底是那一个键所对应的值对象)。 

Map有两种比较常用的实现:HashMap和TreeMap。 

HashMap也用到了哈希码的算法,以便快速查找一个键, 

TreeMap则是对键按序存放,因此它便有一些扩展的方法,比如firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。 
键和值的关联很简单,用put(Object key,Object value)方法即可将一个键与一个值对象相关联。用get(Object key)可得到与此key对象所对应的值对象。 

--------------------------------------JB分割线------------------------------------ 

其它: 
一、几个常用类的区别 
1.ArrayList: 元素单个,效率高,多用于查询 
2.Vector: 元素单个,线程安全,多用于查询 
3.LinkedList:元素单个,多用于插入和删除 
4.HashMap: 元素成对,元素可为空 
5.HashTable: 元素成对,线程安全,元素不可为空 

二、Vector、ArrayList和LinkedList 
大多数情况下,从性能上来说ArrayList最好,但是当集合内的元素需要频繁插入、删除时LinkedList会有比较好的表现,但是它们三个性能都比不上数组,另外Vector是线程同步的。所以: 
如果能用数组的时候(元素类型固定,数组长度固定),请尽量使用数组来代替List; 
如果没有频繁的删除插入操作,又不用考虑多线程问题,优先选择ArrayList; 
如果在多线程条件下使用,可以考虑Vector; 
如果需要频繁地删除插入,LinkedList就有了用武之地; 
如果你什么都不知道,用ArrayList没错。 

三、Collections和Arrays 
在 Java集合类框架里有两个类叫做Collections(注意,不是Collection!)和Arrays,这是JCF里面功能强大的工具,但初学者往往会忽视。按JCF文档的说法,这两个类提供了封装器实现(Wrapper Implementations)、数据结构算法和数组相关的应用。 
想必大家不会忘记上面谈到的“折半查找”、“排序”等经典算法吧,Collections类提供了丰富的静态方法帮助我们轻松完成这些在数据结构课上烦人的工作: 
binarySearch:折半查找。 

sort:排序,这里是一种类似于快速排序的方法,效率仍然是O(n * log n),但却是一种稳定的排序方法。 

reverse:将线性表进行逆序操作,这个可是从前数据结构的经典考题哦! 

rotate:以某个元素为轴心将线性表“旋转”。 

swap:交换一个线性表中两个元素的位置。 
…… 
Collections还有一个重要功能就是“封装器”(Wrapper),它提供了一些方法可以把一个集合转换成一个特殊的集合,如下: 

unmodifiableXXX:转换成只读集合,这里XXX代表六种基本集合接口:Collection、List、Map、Set、SortedMap和SortedSet。如果你对只读集合进行插入删除操作,将会抛出UnsupportedOperationException异常。 

synchronizedXXX:转换成同步集合。 

singleton:创建一个仅有一个元素的集合,这里singleton生成的是单元素Set, 
singletonList和singletonMap分别生成单元素的List和Map。 

空集:由Collections的静态属性EMPTY_SET、EMPTY_LIST和EMPTY_MAP表示。 

如何在它们之间选择?

一、Array , Arrays

Java所有“存储及随机访问一连串对象”的做法,array是最有效率的一种。

1、
效率高,但容量固定且无法动态改变。
array还有一个缺点是,无法判断其中实际存有多少元素,length只是告诉我们array的容量。

2、Java中有一个Arrays类,专门用来操作array。
arrays中拥有一组static函数,
equals():比较两个array是否相等。array拥有相同元素个数,且所有对应元素两两相等。
fill():将值填入array中。
sort():用来对array进行排序。
binarySearch():在排好序的array中寻找元素。
System.arraycopy():array的复制。

二、Collection , Map

若撰写程序时不知道究竟需要多少对象,需要在空间不足时自动扩增容量,则需要使用容器类库,array不适用。

1、Collection 和 Map 的区别

容器内每个为之所存储的元素个数不同。
Collection类型者,每个位置只有一个元素。
Map类型者,持有 key-value pair,像个小型数据库。

2、各自旗下的子类关系

Collection
--List: 将以特定次序存储元素。所以取出来的顺序可能和放入顺序不同。
--ArrayList / LinkedList / Vector
--Set : 不能含有重复的元素
--HashSet / TreeSet
Map
--HashMap
--HashTable
--TreeMap

3、其他特征

* List,Set,Map将持有对象一律视为Object型别。
* Collection、List、Set、Map都是接口,不能实例化。
继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。
* vector容器确切知道它所持有的对象隶属什么型别。vector不进行边界检查。

三、Collections

Collections是针对集合类的一个帮助类。提供了一系列静态方法实现对各种集合的搜索、排序、线程完全化等操作。
相当于对Array进行类似操作的类——Arrays。
如,Collections.max(Collection coll); 取coll中最大的元素。
Collections.sort(List list); 对list中元素排序

四、如何选择?

1、容器类和Array的区别、择取
* 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置。
* 一旦将对象置入容器内,便损失了该对象的型别信息。

2、
* 在各种Lists中,最好的做法是以ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList();
Vector总是比ArrayList慢,所以要尽量避免使用。
* 在各种Sets中,HashSet通常优于HashTree(插入、查找)。只有当需要产生一个经过排序的序列,才用TreeSet。
HashTree存在的唯一理由:能够维护其内元素的排序状态。
* 在各种Maps
HashMap用于快速查找。
* 当元素个数固定,用Array,因为Array效率是最高的。

结论:最常用的是ArrayList,HashSet,HashMap,Array。

注意:

1、Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。
2、Set和Collection拥有一模一样的接口。
3、List,可以通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...。(add/get)
4、一般使用ArrayList。用LinkedList构造堆栈stack、队列queue。

5、Map用 put(k,v) / get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。
HashMap会利用对象的hashCode来快速找到key。
* hashing
哈希码就是将对象的信息经过一些转变形成一个独一无二的int值,这个值存储在一个array中。
我们都知道所有存储结构中,array查找速度是最快的。所以,可以加速查找。

发生碰撞时,让array指向多个values。即,数组每个位置上又生成一个梿表。

6、Map中元素,可以将key序列、value序列单独抽取出来。
使用keySet()抽取key序列,将map中的所有keys生成一个Set。
使用values()抽取value序列,将map中的所有values生成一个Collection。

为什么一个生成Set,一个生成Collection?那是因为,key总是独一无二的,value允许重复

参考:Java Collection

本文转载自:http://zhidao.baidu.com/link?url=pIKLGwSeXoGSk1JK6N53ZxVYZCZo1cRsudwK2ONj0tg9xy_C3QQUsSqZydjSZI2X...

共有 人打赏支持
颖辉小居
粉丝 29
博文 141
码字总数 69459
作品 0
东城
高级程序员
java 集合类简单的分析1

java中的集合类是很常见的,ArrayList,HashSet,HashMap等,现在就让我们来看下他们的各个类之间的关系图。 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set...

leeOwnWell ⋅ 2014/03/23 ⋅ 0

java容器学习

java容器: 容器,顾名思义,就是用来存放东西的道具,但是在我们程序开发中容器的概念就是用来存在我们数据对象的引用。 往常的数组存储,由于数组开始的长度已经指定,开发过程中不能随意修...

四月李 ⋅ 2015/12/17 ⋅ 0

Map、Set、List集合差别及联系详解

         一、集合   集合类存放于java.util包中。   集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)。  ...

Romane ⋅ 06/05 ⋅ 0

JAVA集合小结

集合类说明及区别 Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection接口   Collection是最基本的集合接...

亮liang ⋅ 2015/04/14 ⋅ 0

JAVA容器类解析

jdk1.4容器类关系图 虚线框表示接口。 实线框表示实体类。 粗线框表示最常用的实体类。 点线的箭头表示实现了这个接口。 实线箭头表示类可以制造箭头所指的那个类的对象。 容器类持有对象方式...

executor ⋅ 2014/10/21 ⋅ 0

List,Set,Map用法以及区别

List,Set,Map是否继承自Collection接口? 答:List,Set是,Map不是。 如图: Collection   ├List   │├LinkedList   │├ArrayList   │└Vector   │ └Stack   └Set   ...

varchard ⋅ 2015/03/26 ⋅ 3

你所知道的集合类都有哪些?主要方法?(面试都会问)

线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述,向读者阐述各个类的...

aminqiao ⋅ 2014/08/29 ⋅ 0

数据结构(集合和数组)

在使用JAVA的时候经常用到集合类(有时也称容器类),下面对常用的容器类进行一下总结。首先看一张图,了解一下集合类的结构以及他们之间的关系: 一、Collection接口 Collection接口是 Set 、...

微尘鉴 ⋅ 2016/02/22 ⋅ 0

HashMap和Hashtable的区别。

1 HashMap不是线程安全的 hastmap是一个接口 是map接口的实现类,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许null key和null value,而h...

零度的魚 ⋅ 2014/01/01 ⋅ 0

java中 HashMap和Hashtable,list、set和map 的区别

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。 HashMap允许将nul...

飓风2000 ⋅ 2014/05/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring表达式语言(SpEL)

1、SpEL引用 Spring EL在bean创建时执行其中的表达式。此外,所有的Spring表达式都可以通过XML或注解的方式实现。下面将使用Spring表达式语言(SpEL),注入字符串,整数,Bean到属性。 SpEL的...

霍淇滨 ⋅ 37分钟前 ⋅ 0

Gradle使用阿里云镜像

gradle 生命周期中有一个初始化( Initialization )的过程,这个过程运行在 build script 之前,我们可以在这个地方做一点系统全局的设置,如配置仓库地址。 你可以在以下几个位置实现仓库地址...

明MikeWoo ⋅ 45分钟前 ⋅ 0

appium+python3.6

1.安装jdk1.8(不知道为啥只识别1.8,1.10不识别,所以为了少折腾,迁就安装1.8) http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 配置 JAVA_HOME:...

Kampfer ⋅ 今天 ⋅ 0

详解Apache 日志分割教程

一、日志切割 安装cronolog CentOS 5.3中编译安装Apache日志默认是不切割的,需要用用工具Cronnolog进行日志切割。 1.下载及安装 wget http://cronolog.org/download/cronolog-1.6.2.tar.gz ...

dragon_tech ⋅ 今天 ⋅ 0

Keepalived介绍

负载均衡器(Load Balancer, LB )是一组能够将IP数据流以负载均衡形式转发到多台物理服务器的集成软件。有硬件负载均衡器和软件负载均衡器之分,硬件负载均衡器主要是在访问网络和服务器之间...

寰宇01 ⋅ 今天 ⋅ 0

java8-Collections and Streams

stream和集合的区别是什么? 1.在计算的时候处理不同, 2.every element should be computed in the memory and then to be part of collections stream Stream apis filter with a predica......

writeademo ⋅ 今天 ⋅ 0

Confluence 6 重新获得附件指南

每一个文件在恢复上传到 Confluence 的时候必须单独重命名,你可以通过下面说明的 3 个方法中选择一个进行操作: 选择 A - 通过文件名恢复附件 如果你知道你需要恢复的每一个文件名,尤其是你...

honeymose ⋅ 今天 ⋅ 0

【每天一个JQuery特效】根据状态确定是否滑入或滑出被选元素

主要效果: 本文主要采用slideToggle()方法实现以一行代码同时实现以展开或收缩的方式显示或隐藏被选元素。 主要代码如下: <!DOCTYPE html><html><head><meta charset="UTF-8">...

Rhymo-Wu ⋅ 今天 ⋅ 0

度量.net framework 迁移到.net core的工作量

把现有的.net framework程序迁移到.net core上,是一个非常复杂的工作,特别是一些API在两个平台上还不能同时支持。两个类库的差异性,通过人工很难识别全。好在微软的工程师们考虑到了我们顾...

李朝强 ⋅ 今天 ⋅ 0

请不要在“微服务”的狂热中迷失自我!

微服务在过去几年一直是一个非常热门的话题(附录1)。何为“微服务的疯狂”,举个例子: 众所周知,Netflix在DevOps上的表现非常棒。Netfix可以做微服务。因此:如果我做微服务,我也将非常...

harries ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部