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:/ ...
随机推荐
- node(redis)
给出node下redis操作的简单例子: var redis = require("redis"), client = redis.createClient(6379,'127.0 ...
- http学习笔记(三)
几乎所有的http通信都是由TCP/IP承载的.http好比一辆汽车,而TCP是一条公路,所有的汽车都要在公路上跑,看看http是如何在tcp这条公路上往返的. 首先简单地看看tcp,TCP连接是通过 ...
- 解决URL中文乱码问题
在做一个HTTPS连接时, 要客户端合成一段HTTPS地址 如果地址含中文的话程序会crash, 检查发现原来是中文没有转码的原因 在NSString库里面找到了下面两个方法 - (NSString ...
- PMO到底什么样?(2)
接上一篇,继续聊一聊PMO到底什么样. 交付功能,8大典型责任 1监控.评定和报告 项目办理单位从交付的视点必定要有监控评定.每个项目在要害的期间上它的进展是不是跟按期的相同:是不是有要害的专家在要害 ...
- _学生选课数据库SQL语句练习题
1. 查询Student表中的所有记录的Sname.Ssex和Class列. select Sname,Ssex,t.sclass from STUDENT t 2. 查询教师所有的单位即不重复的De ...
- SQL SERVER 2005/2008 中关于架构的理解(二)
本文上接SQL SERVER 2005/2008 中关于架构的理解(一) 架构的作用与示例 用户与架构(schema)分开,让数据库内各对象不再绑在某个用户账号上,可以解决SQL SERVE ...
- django创建项目
django创建项目 安装django pip install django==1.9 Note: C:\Python34\Scripts\pip.exe 创建项目 django-admin star ...
- IOS开发之控件篇UICollectionViewControllor第一章 - 普通介绍
1.介绍 UICollectionView和UICollectionViewControllor是IOS6.0后引入的新控件 使用UICollectionView必须实现三个接口: UICollect ...
- 隐藏自定义tabbar(关于tabbar的hide属性对于自定义无效)
背景: 最近在做一个项目中 需要在tabbar中的一个子控制器中隐藏tabbar. 我是tabbar我是自定义的XIB 视图addsubview到tabbar上. 首先po 一个在网上查到的解决方法: ...
- JTMz换路径导致MySQL服务不能启动的问题
问题: JTMz解压到我的机器上,运行一次后,把服务停止了,然后移到了另外一个路径,JTMz中自带的MySQL服务启动不起来了. 解决: 在注册表中修改 HKEY_LOCAL_MACHINE\SYST ...