Java 集合类

为何使用集合java

数组长度是固定,若是要改变数组的长度须要建立新的数组将旧数组里面的元素拷贝过去,使用起来不方便。数组

java给开发者提供了一些集合类,可以存储任意长度的对象,长度能够随着元素的增长而增长,随着元素的减小而减小,使用起来方便一些。安全

 

数组和集合的区别网络

区别1:数据结构

数组既能够存储基本数据类型,又能够存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值。并发

集合只能存储引用数据类型(对象),若是存储基本数据类型时,会自动装箱变成相应的包装类。性能

区别2:spa

数组长度是固定的,不能自动增加线程

集合的长度的是可变的,能够根据元素的增长而自动增加code

集合基础体系图


java提供了一些集合类,这些集合类分别适用于不一样的场景,下面是经常使用的一些集合基础体系图(图片引自网络)。

Collection类图

Collection是接口,下面的List、Set、Queue也都是接口,而且继承了这个Collection。最下面的ArrayList、LinkedList、Vector、HashSet、TreeSet、PriorityQueue都是他们的实现类。

List:存放的数据是有顺序的,能够存放重复的数据。

LinkedList :基于链表实现,链表内存是散列的,增删快,查找慢;  

ArrayList :基于数组实现,非线程安全,效率高,增删慢,查找快;  

Vector :基于数组实现,效率低,增删慢,查找慢,线程安全

Set:存放的数据是没有顺序的,不能存放重复的数据;

TreeSet:提供有序的Set集合,是天然排序,它继承了AbstractSet抽象类,相对读取慢;

HashSet :底层是由 Hash Map 实现,不容许集合有重复的值,使用该方式时须要重写 equals()和 hashCode()方法; 

LinkedHashSet :继承于 HashSet,同时又基于 LinkedHashMap 来进行实现,底层使用的是 LinkedHashMap,按添加顺序排序;

Queue:是一个队列,里面的数据是先进先出,能够存放重复的数据。

 

Collections是针对集合类的一个帮助类。提供了一系列静态方法实现对各类集合的搜索排序线程彻底化等操做。 
 例如:

Collections.max(Collection coll);  取coll中最大的元素。 
Collections.sort(List list);  对list中元素排序

Map是接口,下面的HashMap、HashTable、AbstractMap也都是接口,而且继承了这个Map。最下面的LinkedHashMap、TreeMap是他们的实现类。

HashMap里面存放的数据是没有顺序的,键值对能够存null键和null值,key 不能重复,值可重复,线程不安全。

LinkedHashMap :继承 了HashMap ,保存了记录的插入顺序; 

HashTable里面存放的元素不保证有序,key 不能重复,值可重复,线程安全

TreeMap:基于红黑树 (red-black tree) 数据结构实现,按 key 排序,默认的排序方式是升序。

 

 

HashMap详情分析

HashMap其实是一个“链表散列”的数据结构,即数组和链表的结合体。

HashMap的底层结构是一个数组,数组中的每一项是一条链表。

HashMap的实例有两个参数影响其性能“初始容量” 和 装填因子。

HashMap实现不一样步,线程不安全,HashTable线程安全。

HashMap中的key-value都是存储在Entry中的。

HashMap能够存null键和null值,不保证元素的顺序恒久不变,经过hashCode()方法和equals方法保证键的惟一性。

hashCode()方法解决哈希冲突主要有三种方法:开放定址法,链表法,再散列法

HashMap是采用 链表法 解决哈希冲突的。

注: 链表法是将相同hash值的对象组成一个链表放在hash值对应的槽位;    

 

Hashtable、HashMap、ConcurrentHashMap的区别

HashMap和HashTable在功能上基本相同,但HashMap是线程不安全的,HashTable是线程安全的;

HashMap的key和value都是能够为null的,当get()方法返回null值时,HashMap中可能存在某个key,只不过该key值对应的value为null,也有多是HashMap中不存在该key,因此不能使用get()==null来判断是否存在某个key值,对HashMap和HashTable,提供了containsKey()方法来判断是否存在某个key。

HashTable是不容许key和value为null的。HashTable中的方法大部分是同步的,所以HashTable是线程安全的。

在JDK1.5之后,出现了ConcurrentHashMap和HashTable功能很像,不容许为null的key或value,但它不是经过给方法加synchronized方法进行并发控制的。在ConcurrentHashMap中使用分段锁技术Segment,将数据分红一段一段的存储,而后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其余段的数据也能被其余线程访问,可以实现真正的并发访问。效率也比HashTable好的多。

 

TreeMap、HashMap、LinkedHashMap的区别

LinkedHashMap保存了数据的插入顺序,底层是经过一个双链表的数据结构来维持这个插入顺序的,key和value均可觉得null。

TreeMap实现了SortMap接口,它保存的记录是根据键值key排序,默认是按key升序排列。也能够指定排序的Comparator。

 

HashMap、LinkedHashMap和TreeMap都是线程不安全的,提供两种遍历Map的方法以下
推荐方式

Map<String, Integer> map = new HashMap<String, Integer>(20); //直接遍历出Entry  for(Map.Entry<String, Integer> entry : map.entrySet()){ System.out.println("key-->"+entry.getKey()+",value-->"+m.get(entry.getValue())); }

这种方式至关于首先经过Set<Map.Entry<String,Integer>> set =  map.entrySet();方式拿到Set集合,而Set集合是能够经过foreach的方式遍历的。

普通方式

Map<String, Integer> map = new HashMap<String, Integer>(20); Iterator<String> keySet = map.keySet().iterator(); //遍历Hash表中的key值集合,经过key获取value  while(keySet .hasNext()){ Object key = keySet .next(); System.out.println("key-->"+key+",value-->"+m.get(key)); }

HashSet内部使用Map保存数据,即将HashSet的数据做为Map的key值保存,这也是HashSet中元素不能重复的缘由。而Map中保存key值的,会去判断当前Map中是否含有该Key对象,内部是先经过key的hashCode,肯定有相同的hashCode以后,再经过equals方法判断是否相同。