Java - 容器详解
一、ArrayList
长度可变数组,类似于c++ STL中的vector.
元素以线性方式连续存储,内部允许存放重复元素。
允许对元素进行随机的快速访问,但是向ArrayList中插入和删除元素的速度较慢。
ArrayList是非线程安全的,若要成为线程安全,可以使用:List list=Collections.synchronizedList(new ArrayList());
数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。
这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。
当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。
二、LinkedList
内部采用双向循环链表实现,类似于c++ STL中的list.
插入和删除元素的速度较快,随机访问的速度较慢.
LinkedList单独具有addFirst(),addLast(),getFirst(),getLast(),removeFirst()和removeLast()方法.
这些方法使得它可以作为堆栈、队列和双向队列来使用.
LinkedList也是非线程安全的.
三、HashMap
基于哈希表的Map接口实现,类似于c++ STL中的unordered_map.
元素是无序的.
采用拉链法来处理哈希冲突,注意:链表中存储的仍然是key值,而非value,对于同一个key,value的新值会替换旧值.
当哈希表中的条目数超过了加载因子与当前容量的乘积时,则要对该哈希表进行rehash操作(重建内部数据结构),将哈希的桶数量扩大两倍左右.
HashMap是基于HashCode的,HashMap也是非线程安全的,若要线程安全,可用:Map m=Collections.synchronizedMap(new HashMap());
自己实现,最好使用局部锁:把HashMap进行拆分,拆分成了多个独立的块,这样在高并发的情况下减少了锁冲突的可能,增加了并发性.
四、TreeMap
基于红黑树,类似于c++ STL中的map.
使用了SortedMap接口.
确保key键是有序的,无重复的.
也是非线程安全的.
五、HashSet
基于Hash表的Set接口实现,类似于c++ STL中的unordered_set,采用hash散列存储.
元素是无序的,无重复的.
也是非线程安全的.
六、TreeSet
基于红黑树实现,类似于c++ STL中的set.
TreeSet 底层实际使用的存储容器就是TreeMap.
元素是有序的,无重复的.
也是非线程安全的.
七、总结
Java中的容器大多在c++ STL中都有实现,实现方法和使用方法都大同小异.
在Java容器中,只有HashTable和Vector是线程安全(同步)的,同步实现的方法是:
将状态封闭起来,并对每个共有方法进行同步,是的每次只有一个线程能访问容器状态,并发性较差.
------------------------------------------------------------------------------------------
什么是Map.
在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对.
HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的).
HashMap 非线程安全 TreeMap 非线程安全
线程安全
在Java里,线程安全一般体现在两个方面:
1. 多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized.
如ArrayList和Vector,HashMap和Hashtable(后者每个方法前都有synchronized关键字)。
如果你在interator一个List对象时,其它线程remove一个element,问题就出现了.
2. 每个线程都有自己的字段,而不会在多个线程之间共享. 它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static. transient那样.
1.AbstractMap抽象类和SortedMap接口
AbstractMap抽象类:(HashMap继承AbstractMap)覆盖了equals()和hashCode()方法以确保两个相等映射返回相同的哈希码. 如果两个映射大小相等. 包含同样的键且每个键在这两个映射中对应的值都相同,则这两个映射相等. 映射的哈希码是映射元素哈希码的总和,其中每个元素是Map.Entry接口的一个实现. 因此,不论映射内部顺序如何,两个相等映射会报告相同的哈希码.
SortedMap接口:(TreeMap继承自SortedMap)它用来保持键的有序顺序. SortedMap接口为映像的视图(子集),包括两个端点提供了访问方法. 除了排序是作用于映射的键以外,处理SortedMap和处理SortedSet一样. 添加到SortedMap实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个Comparator接口的实现. TreeMap类是它的唯一一份实现.
2.两种常规Map实现
HashMap:基于哈希表实现. 使用HashMap要求添加的键类明确定义了hashCode()和equals().
可以重写hashCode()和equals()。为了优化HashMap空间的使用,您可以调优初始容量和负载因子.
- HashMap(): 构建一个空的哈希映像
- HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
- HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
- HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像
TreeMap:基于红黑树实现. TreeMap没有调优选项,因为该树总处于平衡状态.
- TreeMap():构建一个空的映像树
- TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
- TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
- TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序
3.两种常规Map性能
- HashMap:适用于在Map中插入. 删除和定位元素.
- Treemap:适用于按自然顺序或自定义顺序遍历键(key).
4.总结
HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap.
------------------------------------------------------------------------------------------
一、Collection:存放独立元素
Collection中的接口都是可选操作,事实上现类 并不一定实现了其全部接口,这是为了防止“接口爆炸”。
最常见的Unsupported Operation都源自于背后由固定尺寸的数据结构支持的容器,比方使用ArrayList.asList将数组转换成List的时候,就会得到这种容器。
(1)Collection之List
List较之Collection添加了非常多额外的接口,特别是LinkedList。
长处 |
缺点 |
保存元素的顺序 |
应用 |
|
ArrayList |
随机訪问速度快,内部使用数组实现。 |
迭代,插入和删除元素慢, 尤其是当List尺寸比較大的时候。 |
插入顺序 |
可变长数组 |
LinkedList |
迭代(顺序訪问经过优化),插入、删除都非常快 内部使用双向链表实现 |
随机訪问速度慢 |
插入顺序 |
顺序訪问, 批量插入删除元素的场合 |
(2)Collection之Set
存入Set的每个元素都必须是唯一的,由于Set不保存重复元素。
可是存入Set的元素必须要定义equals()方法以确保对象的惟一性。
另外Set与Collection有着全然同样的接口。
Set并不保证维护元素的次序,所以须要注意。
Set不包括随机訪问的get方法。由于Set是自己维护内部顺序的,不须要随机訪问。
长处 |
保存元素的顺序 |
要求 |
|
HashSet |
为快速查找设计 |
散列存储 |
必须定义hashCode()方法 |
LinkedHashSet |
和HashSet一样的查询速度, 可是插入要比HashSet慢一些, 由于它通过维护链表形式维护元素。 |
使用链表维护元素顺序(插入顺序) |
必须定义hashCode()方法 |
TreeSet |
保存有序的Set,底层通过TreeMap来实现的 |
依照排序顺序维护元素 |
必须实现Comparable接口(包括compareTo方法) |
注意,假设没有特别的限制,HashSet就应该是你的默认选择,由于它对速度进行了优化。
(3)Collection之Queue:
特点 |
保存元素的顺序 |
|
LinkedList |
LinkedList除了普通List之外, 还加入了<队列、栈、双向队列>三种数据结构的方法。 尤其是模拟Queue的时候在两端插入删除元素非常快(经过了优化)。 |
插入的顺序 |
PriorityQueue |
依照排序顺序取出元素,所以要求必须实现Comparable接口。 |
排序顺序 |
二、Map:存放键-值对
为了保证Map中的唯一性,不论什么“键”都须要有一个equals()方法,推断当前键是否与表中的键同样。
特点 |
保存元素的顺序 |
要求 |
|
HashMap |
Map基于散列存储。插入和查询“键值对”的开销是固定的。 |
散列存储 |
存入的键须要具备hashCode()方法,当然,返回的标识不一定要唯一 |
LinkedHashMap |
为了提快速度散列了全部元素,插入查询仅仅比HashMap慢一点点,由于它在维护散列数据结构的同一时候还要维护链表(插入顺序)。 可是迭代訪问的时候更快。由于内部使用链表维护次序。 |
插入顺序 |
同样须要键实现hashCode()方法 |
TreeMap |
Map基于红黑树的实现。所以所得的结果是经过排序的。 |
红黑树 |
为了排序。必须实现Comparable接口。 |
其它为解决特殊问题设计的Map还有IdentityHashMap。WeakHashMap,ConcurrentHashMap等。
实验证明。除了IdentityHashMap之外的其它全部Map,随着Map的尺寸变大,插入会明显变慢。可是查找的代价小非常多。我推測这是由于每次插入都要通过equals方法来确保键值的唯一性导致的,只是Map最经常使用的操作是查询操作,所以情况还比較乐观。
总结:
(1)要想让你的容器类型安全,须要使用泛型(否则编译器同意你向容器中插入各种不同类型,仅仅要是Object就可以);
(2)创建容器的时候尽量将其向上转型为接口,像这样:
List<Apple> apples = newArrayList<Apple>();
使用接口的目的在于当你决定改动你的实现的时候。仅仅须要在创建的地方改动它就能够了。
(3)Java有大量的用于容器的卓越的方法,他们被封装到java.util.Collections类中,全部都是static方法。
比方Collections类中有unmodifiableMap/List/Set()方法设置Collection和Map为不可改动。还有synchronizedCollection/List/Set/Map等方法同步整个容器。
另外排序,填充,逆置,最大最小值等非常多方法也能够找到。
--------------------------------------------------------- End.
转载请注明:http://www.cnblogs.com/crazyacking/
Java - 容器详解的更多相关文章
- Java容器详解
线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.在Java中,容器的类型主要有:List.Set ...
- 【Java入门提高篇】Day34 Java容器类详解(十五)WeakHashMap详解
源码详解系列均基于JDK8进行解析 说明 在Java容器详解系列文章的最后,介绍一个相对特殊的成员:WeakHashMap,从名字可以看出它是一个 Map.它的使用上跟HashMap并没有什么区别,所 ...
- 黑马----JAVA迭代器详解
JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...
- Java ClassLoad详解
Java ClassLoad详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1. ...
- Java NIO 详解(一)
一.基本概念描述 1.1 I/O简介 I/O即输入输出,是计算机与外界世界的一个借口.IO操作的实际主题是操作系统.在java编程中,一般使用流的方式来处理IO,所有的IO都被视作是单个字节的移动,通 ...
- [Spring学习笔记 1 ] Spring 简介,初步知识--Ioc容器详解 基本原理。
一.Spring Ioc容器详解(1) 20131105 1.一切都是Bean Bean可是一个字符串或者是数字,一般是一些业务组件. 粒度一般比较粗. 2.Bean的名称 xml配置文件中,id属性 ...
- Java List详解,面试中应该如何解答关于List的问题
对于面试,我们在介绍Java的List的时候,一般需要介绍到,什么是List?List包括什么?各自在用法上有什么区别,在存储上有什么区别?List需要注意什么?把这些问题串起来,我们可以这样介绍: ...
- Java集合详解8:Java的集合类细节精讲
Java集合详解8:Java集合类细节精讲 今天我们来探索一下Java集合类中的一些技术细节.主要是对一些比较容易被遗漏和误解的知识点做一些讲解和补充.可能不全面,还请谅解. 本文参考:http:// ...
- Java集合详解3:Iterator,fail-fast机制与比较器
Java集合详解3:Iterator,fail-fast机制与比较器 今天我们来探索一下LIterator,fail-fast机制与比较器的源码. 具体代码在我的GitHub中可以找到 https:/ ...
随机推荐
- android知识杂记(三)
记录项目中的android零碎知识点,用以备忘. 1.android 自定义权限 app可以自定义属于自己的权限: <permission android:description="s ...
- 【原创】GC/垃圾回收简介
GC简介 1 GC机制 1.1 对象 从计算机的角度,装有数据的内存空间 1.2 作用 将内存垃圾的释放自动化 1.3 本质 将已经引用不到的对象视为死亡,将死亡的对象找出来并且作为垃圾进行回收 2 ...
- nim的引用和指针
nim语言的引用和其他语言的指针有点相似 可以提供一种“多对一”的关系 这就意味着不同的引用可以指向同一个内存位置 nim区分可被追踪的引用和不可被追踪的引用 不可被追踪的引用又称为指针 可被追踪的引 ...
- 支持断点续传的文件上传插件——Huploadify-V2.0来了
之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...
- Git学习笔记(9)——自定义配置
本文主要记录了Git的一些易用化的配置和别名的使用 配置Git的命令输出带有颜色,更加醒目 //配置输出颜色 $ git config --global color.ui true //取消输出颜色 ...
- VC++中开发汇编语言(转)
汇编程序结构 一个显示字符串的汇编程序 程序格式 一.模式定义 二.includelib语句 三.函数声明语句 四.数据和代码部分 Visual C/C++环境 建立工程 汇编程序的调试 一.设置断点 ...
- 写js写傻了,明天研究一下异步
在html某元素上绑定一个click事件,该事件是一个执行事件很长的函数,比如执行几十亿或几百亿次加法,那么在这个函数执行的过程中,其他元素绑定的事件,是如何触发的呢,异步触发还是同步,触发时是怎么执 ...
- 爱上MVC系列~过滤器实现对响应流的处理
回到目录 MVC的过滤器相信大家都用过,一般用来作权限控制,因为它可以监视你的Action从进入到最后View的渲染,整个过程ActionFilter这个过滤器都参与了,而这给我们的开发带来了更多的好 ...
- 每天一个linux命令(41):ps命令
Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...
- webapp启动流程
webapp启动流程 看了这个教程,其实所有的webapp大致都是这个流程了.