Java Collections Framework是Java提供的对集合进行定义,操做,和管理的包含一组接口,类的体系结构。html
1. 总体框架java
Java容器类库一共有两种主要类型:Collection和Map。层次结构以下: 程序员
蓝色椭圆框为接口类(不可实例化),黑色矩形框为实现类或子类。面试
Map map = new HashMap(); map.put("key1","lisi1"); map.put("key2","lisi2"); map.put("key3","lisi3"); //Map的keySet()方法先获取全部键的set集合,并经过Set的迭代器进行迭代遍历 Iterator it = map.keySet().iterator(); while(it.hasNext()){ Object key = it.next(); //经过迭代器遍历Map的值对象 System.out.println(map.get(key));
}
3.2 Map.entrySet()算法
Set<Map.Entry<K,V>> entrySet(); //把(key-value)做为一个总体一对一对地存放到Set集合当中的。Map.Entry表示映射关系。entrySet():迭代后能够e.getKey(),e.getValue()两种方法来取key和value。返回的是Entry接口。示例:编程
Map map = new HashMap(); map.put("key1","lisi1"); map.put("key2","lisi2"); map.put("key3","lisi3"); //将map集合中的映射关系存入到Set集合,并获取迭代器用来遍历 Iterator it = map.entrySet().iterator(); while(it.hasNext()){ //迭代遍历,并转类型为Entry Entry e =(Entry) it.next(); //Entry.getKey ()、Entry.getValue()能够分别获得Entry对象的键和值 System.out.println("键"+e.getKey () + "的值为" + e.getValue()); }
对比:推荐使用entrySet(),由于效率更高。数组
对于keySet()方法,遍历了两次Map,一次用来从HashMap中取出全部key到Set集合,一次从HashMap中取出全部key对应的value。而entrySet()只遍历了一次,由于直接将key-value做为总体放入了Entry对象中,因此效率更高。安全
4. 主要实现类对比数据结构
4.1 Vector和ArrayList并发
相同点:都实现了List接口,元素有序可重复;都基于数组的数据结构实现,都容许直接序号索引元素,因此随机性较好,适合用于查询,可是增删移动数据比较慢(用LinkedList);
不一样点:Vector是线程同步的,因此它也是线程安全的,而ArrayList是线程异步的,是不安全的;Vector因为使用了synchronized方法(线程安全)因此性能上比ArrayList要差;在集合中使用数据量比较大的数据,用Vector有必定的优点。
4.2ArrayList和LinkedList
相同点:都实现了List接口,元素有序可重复;
不一样点:具体实现:ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构;效率:对于随机访问get和set,ArrayList优于LinkedList,但对于新增和删除操做add和remove,LinedList比较占优点。由于LinkedList使用双向链表实现存储,按序号索引数据须要进行向前或向后遍历,可是插入数据时只须要记录本项的先后项便可,而ArrayList每插入一条数据,要移动插入点及以后的全部数据。 这一点要看实际状况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但如果批量随机的插入删除数据,LinkedList的速度大大优于ArrayList。
4.3 HashMap与TreeMap
都实现了Map接口,是一种键值对的映射关系。
HashMap经过hashcode对其内容进行快速查找,而TreeMap中全部的元素都保持着某种固定的顺序,若是你须要获得一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
在Map 中插入、删除和定位元素,HashMap是最好的选择。但若是您要按天然顺序或自定义顺序遍历键,那么TreeMap会更好。
使用HashMap要求添加的键类明肯定义了hashCode()和 equals()的实现。
两个map中的元素同样,但顺序不同,致使hashCode()不同。
一样作测试:
在HashMap中,一样的值的map,顺序不一样,equals时,false;
而在TreeMap中,一样的值的map,顺序不一样,equals时,true,说明,treeMap在equals()时是整理了顺序了的。
4.4 HashTable与HashMap
都实现了Map接口,是一种键值对的映射关系。采用的hash/rehash算法相似,性能差别不大。
HashMap不是同步的,是线程不安全的;容许一个null键和多个null值。HashTable是同步的,线程安全;不容许有null的键或值。
HashTable有contains()方法,在HashMap中只有containsKey()和containsValue()来检测哈希表中是否有某个key或者value,有则返回true。
一、什么是Java集合API
Java集合框架API是用来表示和操做集合的统一框架,它包含接口、实现类、以及帮助程序员完成一些编程的算法。简言之,API在上层完成如下几件事:编程更加省力,提升城程序速度和代码质量;非关联的API提升互操做性;节省学习使用新API成本;节省设计新API的时间;鼓励、促进软件重用。
具体来讲,有7个集合接口,最基本的是Collection接口,由三个接口Set、List、Queue、SortedSet继承,另外两个接口是Map、SortedMap,这两个接口不继承Collection,表示映射而不是真正的集合。
二、什么是Iterator
一些集合类(Set)提供了内容遍历的功能,经过java.util.Iterator接口。这些接口容许遍历对象的集合。依次操做每一个元素对象。当使用 Iterators时,在得到Iterator的时候包含一个集合快照。一般在遍历一个Iterator的时候不建议修改集合本省。
Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,能够双向列表的遍历,一样支持元素的修改。
三、什么是HaspMap和Map?
Map是接口,Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。HashMap是异步的,线程不安全,容许有null键值。
HashMap基于hashing原理,咱们经过put(key,value)和get(key)方法储存和获取对象。当咱们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,而后找到bucket位置来储存值对象(HashMap是在bucket中储存键对象和值对象,做为Map.Entry)。当获取对象时,经过键对象的equals()方法找到正确的键值对,而后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每一个链表节点中储存键值对对象。
(1)首先equals()和hashcode()这两个方法都是从object类中继承过来的。
equals()是对两个对象的地址值进行的比较(即比较引用是否相同)。
hashCode()是一个本地方法,它的实现是根据本地机器相关的。计算出对象实例的哈希码,并返回哈希码,又称为散列函数。hashCode()方法的计算依赖于对象实例的D(内存地址),故每一个Object对象的hashCode都是惟一的;固然,当对象所对应的类重写了hashCode()方法时,结果就大相径庭了。之因此有hashCode方法,是由于在批量的对象比较中,hashCode要比equals来得快,不少集合都用到了hashCode,好比HashTable。
(2)两个对象,若是equals()相等,hashCode()必定相等;两个对象,若是hashCode()相等,equals()不必定相等(Hash散列值有冲突的状况,虽然几率很低)。
能够考虑在集合中,判断两个对象是否相等的规则是:
第一步,若是hashCode()相等,则查看第二步,不然不相等;
第二步,查看equals()是否相等,若是相等,则两obj相等,不然仍是不相等。
(3)覆盖equals()要先覆盖hashCode(),不然在应用HashMap时会出现各类错误。
它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。
(1)HashMap能够经过Map map = Collections.synchronizedMap(hashMap)来达到同步的效果。
(详细的ConcurrentHashMap源码解析:http://www.importnew.com/22007.html)
四、HashMap与HashTable有什么区别?对比Hashtable VS HashMap
二者都是用key-value方式获取数据。Hashtable是原始集合类之一(也称做遗留类)。HashMap做为新集合框架的一部分在Java2的1.2版本中加入。它们之间有一下区别:
● HashMap和Hashtable大体是等同的,除了非同步和空值(HashMap容许null值做为key和value,而Hashtable不能够)。
● HashMap不是同步的,而Hashtable是同步的。
● 由于线程安全、哈希效率的问题,HashMap效率比HashTable的要高。
● HashTable有contains()方法,在HashMap中只有containsKey()和containsValue()来检测哈希表中是否有某个key或者value,有则返回true。
● 迭代HashMap采用快速失败机制,而Hashtable不是,因此这是设计的考虑点。
● HashMap无法保证映射的顺序一直不变,可是做为HashMap的子类LinkedHashMap,若是想要预知的顺序迭代(默认按照插入顺序),你能够很轻易的置换为HashMap,若是使用Hashtable就没那么容易了。
HashTable和ConcurrentHashMap都是hash表,都是同步的,不一样点在于:
HashTable里使用的是synchronized关键字来确保同步,这实际上是对对象加锁,锁住的都是对象总体。意味着在一个时间点只能有一个线程能够修改哈希表,任何线程在执行hashtable的更新操做前须要获取对象锁,其余线程等待锁的释放。当Hashtable的大小增长到必定的时候,性能会急剧降低,由于迭代时须要被锁定很长的时间,效率低下。
ConcurrentHashMap算是对上述问题的优化,它引入了一个“分段锁”的概念来实现高并发。在ConcurrentHashMap中,就是把HashMap分红了N(默认为16)个Segment,诸如get,put,remove等经常使用操做只锁当前须要用到的桶,根据key.hashCode()算出放到哪一个Segment中。在put的时候须要锁住该Segment,get时候不加锁,使用volatile来保证可见性,只有在求size等全局操做时才可能须要锁定整个表。
试想,原来只能一个线程进入,如今却能同时16个写线程进入(写线程才须要锁定,而读线程几乎不受限制),并发性的提高是显而易见的,所以ConcurrentHashMap的效率远高于HashTable。
基本的不一样点是Hashtable同步HashMap不是的,因此不管何时有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。若是在未来有一种可能—你须要按顺序得到键值对的方案时,HashMap是一个很好的选择,由于有HashMap的一个子类 LinkedHashMap。因此若是你想可预测的按顺序迭代(默认按插入的顺序),你能够很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时若是有多个线程访问HashMap,Collections.synchronizedMap()能够代替,总的来讲HashMap更灵活。
五、什么叫作快速失败特性
从高级别层次来讲快速失败是一个系统或软件对于其故障作出的响应。一个快速失败系统设计用来即时报告可能会致使失败的任何故障状况,它一般用来中止正常的操做而不是尝试继续作可能有缺陷的工做。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。若是一个iterator在集合对象上建立了,其它线程欲“结构化”的修改该集合对象,并发修改异常 (ConcurrentModificationException) 抛出。
六、为何Vector类认为是废弃的或者是非官方地不推荐使用?或者说为何咱们应该一直使用ArrayList而不是Vector
你应该使用ArrayList而不是Vector是由于默认状况下你是非同步访问的,Vector同步了每一个方法,你几乎从不要那样作,一般有想要同步的是整个操做序列。同步单个的操做也不安全(若是你迭代一个Vector,你仍是要加锁,以免其它线程在同一时刻改变集合).并且效率更慢。固然一样有锁的开销即便你不须要,这是个很糟糕的方法在默认状况下同步访问。你能够一直使用Collections.sychronizedList来装饰一个集合。
事实上Vector结合了“可变数组”的集合和同步每一个操做的实现。这是另一个设计上的缺陷。Vector还有些遗留的方法在枚举和元素获取的方法,这些方法不一样于List接口,若是这些方法在代码中程序员更趋向于想用它。尽管枚举速度更快,可是他们不能检查若是集合在迭代的时候修改了,这样将致使问题。尽管以上诸多缘由,Oracle也从没宣称过要废弃Vector。