Java集合相关

在Java开发中,会经常使用到集合,那么何为集合呢?

集合是用于存储批量数据的容器工具,可以将其看做一个可变长度的数组。

在Java的API中集合被包含在java.util包中,被称作collection框架。

Collection

我们先从Collection接口说起,接口Collection是collection层次结构的根接口,表示一组对象,一些collection是允许重复,一些则不可以。一些是有序的,而一些则是无序的。

所有通用的Collection实现类(通常通过它的一个子接口间接实现Collection)应该提供两个“标准”构造方法:一个是 void(无参数)构造方法,用于创建空 collection;另一个是带有Collection类型单参数的构造方法,用于创建一个具有与其参数相同元素新的 collection。实际上,后者允许用户复制任何 collection,以生成所需实现类型的一个等效 collection。尽管无法强制执行此约定(因为接口不能包含构造方法),但是 Java 平台库中所有通用的Collection实现都遵从它。——官网介绍

下图是常用Collection集合的简化UML类图:

图一 Collection

Set接口

Set类型的集合存储的元素是无序的且不可重复。

HashSet

对于HashSet,是基于HashMap(我们将会在后面介绍)实现的。HashSet底层采用HashMap来保存所有元素。主要用来做高性能的集运算,为快速查找而设计。存入HashSet的对象必须重写hashCode()方法。

当我们向HashSet集合添加元素时,它是按照hash算法来存储集合中的元素。首先HashSet会调用该对象的hashCode()方法来获取到该对象的hashCode值,然后根据hashCode值决定该对象在Set集合中的存储位置。HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,同时两个元素的hashCode()方法返回值也相等。因此如果两个元素通过equals方法比较返回为true,但它们通过hashCode()方法返回的值的比较不相等,那么HashSet会将这两个元素存储在不同的位置,仍然能够添加成功。

TreeSet

TreeSet是一种可指定排序方式的Set集合。其底层数据结构是二叉树。通过比较两元素的结果是否为0来保证元素的唯一性。

对于TreeSet的指定排序方式的方法有两种:

方式一:让元素自身具备比较性。只要让元素实现Comparable接口,并覆盖compareTo方法即可,当compareT方法的返回值为0时,就是相同元素。

方式二:让集合自身具备比较性。该方式通过自定义比较器来实现,自定义类实现Comparator接口,覆盖compare方法,将该Comparator接口实现类的对象作为参数传递给TreeSet的构造方法即可。


List接口

List类型的集合存储的元素时有序且可重复。

ArrayList

ArrayList底层采用一个可变长度的数组实现,可存储所有的元素,包括null。由于其实现了Serializable接口,所以其支持序列化。又由于其实现了RandomAccess接口,所以支持快速随机访问。ArrayList集合存储的元素按照存入的先后顺序排列元素,也就是说先进先出。

每个ArrayList实例都有一个容量,即用于存储元素的数组的大小,这个容量可随着不断添加新元素而自动增加,。但是增长算法并没有定义。当需要插入大量元素的时候,再插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。

ArrayList岁支持快速随机访问,但向集合中插入与移除元素的操作速度很慢。

LinkedList

LinkList在的底层是一个链表结构,因此LinkList对于集合增删操作来说会更加占有优势,只需要对指针(注:在Java中没有指针的概念,这里是可以更形象地进行说明)操作即可。又因为链表的结构,LinkList可以被用作堆栈,队列或双向队列。

Vector

Vector同ArrayList一样底层是一个可变长度的数组。(下文有详细的介绍)

Stack

Stack集合继承于Vector类,Stack底层是一个堆栈结构,遵循后进先出(LIFO)原则,只能在一端执行插入操作(称为入栈)或删除操作(称为出栈)

peek()//查看栈顶元素                                                                                                     pop()//出栈,从栈顶移除一个元素                                                                                     push(E Object)//入栈,将一个Object压入栈顶                                                                   search(E Object)//查询某个元素在栈中的位置


下图是常用Map集合简化的UML类图


图二 Map

Map接口

Map类型的集合以键值对的形式存储数据。不允许键的重复和从键到值的一对多映射。

HashMap

在HashMao内部通过一个哈希表来管理所有元素,同上文叙述的HashSet类似(其实应该说HashSet同HashMap类似),通过hashCode()方法和equals()方法来保证键的唯一性。也因此HashMap通过键的hashCode来快速的存取元素。

LinkedHashMap

LinkedHashMap继承于HashMap,在底层是以哈希表和链接列表相结合而实现的.该集合类型保留插入顺序,如果需要输入顺序与输出顺序相同,可以采用此集合。在LinkedHashMap内部有两种排序方式,一种是插入顺序(默认),一种是访问顺序(即近期访问最少到近期访问最多的顺序),这两种方式通过一个布尔值accessOrder进行切换,在LinkedHashMap的构造方法publicLinkedHashMap(intinitialCapacity,floatloadFactor,booleanaccessOrder) {   super(initialCapacity, loadFactor);                                         this.accessOrder = accessOrder;} 中,如果accessOrder为true,表示按照访问顺序存储元素,如果为false表示按照插入顺序访问元素。

Hashtable

同样HashMap在底层是通过一个哈希表来实现的。

Properties

Properties继承于Hashtable,该类表示一个持久的属性值,可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。该类主要用于读取Java中的配置文件,在Java中,其配置文件常为.properties文件,格式为文本文件,文件的内容的格式是“键=值”的格式,文本注释信息可以用"#"来注释。了解Properties的详细用法,点我

TreeMap

TreeMap实现了SortedMap接口,该集合根据键的自然顺序进行排序,或根据创建集合时传入的Comparator进行排序,具体取决于使用的构造方法。

各种集合的比较

1.同步性

以上介绍的集合中,除Vector、Stack、HashTable和Properties外,其他集合类型(HashSet、TreeSet、ArrayList、LinkedList、LinkedHashMap、TreeMap)都是非线程安全的。那么当多个线程同时访问这些非线程的集合类型时,我们必须自己实现访问同步,一种解决方案是在构造这些集合时构造一个同步集合,通过Collections类的静态方法synchronizedCollection()                                                                                                    synchronizedList()                                                                                                              synchronizedMap()                                                                                                            synchronizedSet()                                                                                                              synchronizedSortedMap()                                                                                                  synchronizedSortedSet()

2.ArrayList与Vector的比较

同步性方面,如1所述,Vector不需要自己实现同步方案,而ArrayList需要自己实现同步方案。ArrayList和Vector都是使用可变长数组来保存数据,当数组空间不足时,两者就需要扩展其大小,ArrayList增加50%的大小,而Vector在默认情况下增长一倍的大小,但Vector可以自己设定这个增长幅度,在这方面Vector确实是有优势的,根据情况设定增长幅度,对程序的性能来说会更加友好。

3.LinkedList与ArrayList、Vector的比较

这三种集合类型都支持快速随机访问,在集合的首或末对元素进行更重操作,三者并没有什么的区别,但当从其他任意位置对元素进行操作,在性能上就会产生很大的差异。上文有叙述到LinkList是一个链表结构,在任意位置的对元素的操作都在一个常数级的时间,而Arrayl与Vecotr却颇为费时。

4.HashMap和Hashtable的区别

Hashtable与HashMap类似,但Hashtable不允许键与值为null,HashMap却允许。Hashtable是线程安全的,HashMap是县城非安全的。相比较下,HashMap比Hashtable效率要高下,所以要根据具体情况选择使用。。

5.TreeMap和HashMap的比较

针对于TreeMap,HashMap使用起来性能更好,因为在HashMap的构造方法中,可以自己调优初始容量和负载因子,这样我们就可以根据具体的开发环境去优化我们的HashMap。TreeMap可以自定义顺序遍历元素,这更是与使用在需要具体排序的情况下。但是TreeMap的性能不是很好,TreeMap的get操作的时间复杂度是O(log(n)),针对于HashMap的O(1)差的还是比较多的。因此为了中和两者,出现了LinkedHashMap。

6.各集合的性能比较

单线程模式下,测试元素在100~1000的情况下:

添加  HashMap效率最高,ArrayList最低,其他的效高的还有Stack、HashSet和Vector,较低的有LinkedList和TreeSet和TreeMap

删除 HashMap效率最高,LinkedList最低,其他的HashSet、TreeMap和TreeSet效率较高,较低的有Vector、ArrayList和Stack

查找  HashMap效率最高,LinkedList最低,HashXXX和TreeXXX效率都比较高,而基于List类效率耗时是Map或Set的十倍左右。

多线程模式下,测试元素100~1000,线程数10的情况下:

添加 HashSet效率最高,LinkedList最低,HashXXX和TreeXXX效率都比较高,这里ArrayList效率较低,整体相差不大。

删除 HashSet效率最高,LinkedList最低,整体性能同添加相似,但HashXXX或TreeXXX性能比List系列高出3倍。

查找 仍然是HashSet性能最好,LinkedList最低,性能较差的是ArrayList,其他的均表现很好。

                                                                                                    ——摘自Adroid中文网

请根据具体情况具体选择。

7.移动开发给出的建议

在谷歌官方推出的Android性能优化典范系列视频中提到,Android为移动操作系统特意编写了一些更加高效的容器,其中包括SparseArray和ArrayMap。

SparseArray采用二分法的方式存储数据,所以SparseArray内的元素时按照键从小到大排列的,SparseArray只接受int类型的键

put(int key, E value)//增                                                                                              append(int key, E value)//增,其中的key是大于所有现有的键的数组,以便于提升性能              E get(int key)//查                                                                                                              E get(int key, E valueIfKeyNotFound)//查                                                                        delete(int key)//删                                                                                                        remove(int key)//删,实际上remove和delete是一样的,remove方法中调用了delete方法      setValueAt(int index, E value)//改                                                                                  put(int key, E value)//改

ArrayMap,该类是在API19中出现的,单位了兼容低版本support.v4中也有ArrayMap类。ArrayMap在内部使用两个数组进行工作,其中一个数组记录key hash过后的顺序列表,另外一个数组按key的顺序记录Key-Value值。首先要清楚ArrayMap针对于移动设备的优化是在内存上进行的优化,也就是说使用这个容器比起HashMap会占用更少的内存,因为ArrayMap中的内存占用是连续不间断的,但随着数组中元素的增多,查找访问单个对象的花费也会跟着增长,同时ArrayMap的插入与删除的效率是不够高的,但如果你需要的是在一百这个数量级上时,则完全不用担心这些。

以上是自己对集合知识学习的总结,如果有不正确的地方,感谢指正,我也会及时修改。后面也会逐渐完善这方面的知识分享给大家。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • 1、介绍Collection框架的结构Collection FrameWork如下:Collection├List...
    岳小川阅读 272评论 0 0
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX阅读 869评论 0 1
  • 集合类简介 为什么出现集合类?面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就要对对象进...
    阿敏其人阅读 1,401评论 0 7
  • title: java集合框架学习总结 tags:集合框架 categories:总结 date: 2017-03...
    行径行阅读 1,673评论 0 2
  • 3.3 集合 一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另...
    闫子扬阅读 713评论 0 1