声明: 本文有些内容摘自网络.只是自己总结了一下供大家参考.会不断更新
Java集合类
集合类存放于java.util包中
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)
集合类型主要有3种: set(集) list(列表) map(映射)
Java API中所用的集合类,都是实现了Collection接口,他的一个类继承结构如下:
集合与数组
数组
- 数组(可以存储基本数据类型)是用来存储对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用.
- 集合(只能存储对象,对象类型可以不一样)的长度可变 ,可在多数情况下使用.
层次关系
如图所示: 图中, 实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等
Collection
接口是集合类的根接口, Java中没有提供这个接口的直接的实现类. 但是却让其被继承产生了两个接口, 就是Set
和List
. Set中不能包含重复的元素. List是一个有序的集合, 可以包含重复的元素, 提供了按索引访问的方式.
Map
是Java.util包中的另一个接口, 它和Collection接口没有关系, 是相互独立的, 但是都属于集合类的一部分. Map包含了key-value. Map不能包含重复的key, 但是可以包含相同的value.
Iterator
, 这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
hasNext(): 是否还有下一个元素
next(): 返回下一个元素
-
remove(): 删除当前元素
它的一个子接口LinkedIterator在它的基础上又添加了三种方法,分别是add(),previous(),hasPrevious()。也就是说如果是先Iterator接口,那么在遍历集合中元素的时候,只能往后遍历,被遍历后的元素不会在遍历到,通常无序集合实现的都是这个接口,比如HashSet,HashMap;而那些元素有序的集合,实现的一般都是LinkedIterator接口,实现这个接口的集合可以双向遍历,既可以通过next()访问下一个元素,又可以通过previous()访问前一个元素,比如ArrayList。
Collection(集合的最大接口)继承关系
- List 可以存放重复的内容
- Set 不能存放重复的内容,所以的重复内容靠hashCode()和equals()两个方法区分
- Queue 队列接口
- SortedSet 可以对集合中的数据进行排序
几种重要的接口和类简介
1.List ( 有序,可重复 )
List里存放的对象是有序的, 同时也是可以重复的, List关注的是索引, 拥有一系列和索引相关的方法, 查询速度快. 因为往list集合里插入或删除数据时, 会伴随着后面数据的移动, 所以插入删除数据速度慢.
特有方法:凡是可以操作角标的方法都是该体系特有的方法。
- ArrayList 线程不安全,查询速度快
- Vector 线程安全,但速度慢,已被ArrayList替代
- LinkedList 链表结果,增删速度快
2.Set ( 无序,不可重复 )
Set里存放的对象是无序, 不能重复的, 集合中的对象不按特定方式排序, 只是简单地把对象加入集合中.
HashSet
:底层数据结构是哈希表。是线程不安全的。不同步
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成。
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素的hashcode值不同,不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
TreeSet
:有序的存放,线程不安全,可以对Set集合中的元素进行排序。
3.Map ( 键值对,键唯一,值不唯一 )
Map集合中存储的是键值对, 键不能重复, 值可以重复. 根据键得到值, 对map集合遍历时先得到键的set集合, 对set集合进行遍历, 得到相应的值.
对比如下:
[图片上传失败...(image-72f409-1518362184308)]
遍历
在类中提供了以下四种的常见输出方式:
- Iterator: 迭代输出, 是使用最多的输出方式.
- ListIterator: 是Iterator的子接口, 专门用于输出List中的内容
- foreach: JDK1.5之后提供的新功能, 可以输出数组或集合
- for循环:
代码示例如下:
//for的形式:
for (int i = 0; i < arr.size(); i++) {
...
}
//foreach的形式:
for (String s : arr) {
...
}
//iterator的形式:
while (it.hasNext()) {
Object o = it.next();
...
}
ArrayList和LinkedList
ArrayList
和LinkedList
在用法上没有区别, 但是在功能上还是有区别的. LinkedList经常用在增删操作较多而查询操作很少的情况下, ArrayList则相反.
Map集合
实现类: HashMap
,Hashtable
,LinkedHashMap
,TreeMap
HashMap
HashMap是最常用的Map, 它根据键的HashCode值存储数据, 根据键可以直接获取它的值, 具有很快的访问速度, 遍历时, 取得数据的顺序是完全随机的. 因为键对象不可以重复, 所以HashMap最多只允许一条记录的键为Null, 允许多条记录的值为Null, 是非同步的.
Hashtable
Hashtable与HashMap类似, 是HashMap的线程安全版, 它支持线程的同步, 即任一时刻只有一个线程能写Hashtable, 因此也导致了Hashtable在写入时会比较慢, 它继承自Dictionary类, 不同的是它不允许记录的键或者值为null, 同时效率较低.
ConcurrentHashMap
线程安全, 并且锁分离. ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分, 每个段其实就是一个小的hash table, 它们有自己的锁. 只要多个修改操作发生在不同的段上, 它们就可以并发进行
LinkedHashMap
LinkedHashMap保存了记录的插入顺序, 在用Iterator遍历LinkedHashMap时, 先得到的记录肯定是先插入的, 在遍历的时候会比HashMap慢, 有HashMap的全部特性.
TreeMap
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当使用Iterator遍历TreeMap时,得到的记录是排过序的.不允许key值为空,非同步的.
map的遍历
第一种: KeySet()
将Map中所有的键存入到set集合中. 因为set具备迭代器. 所以可以迭代方式取出所有的键, 再根据get方法. 获取每一个键对应的值. keySet(): 迭代后只能通过get()取key.
取到的结果会乱序, 是因为取得数据行主键的时候, 使用了HashMap.keySe()方法, 而这个方法返回的Set结果, 里面的数据是乱序排放的.
典型用法如下:
Map map = new HashMap();
map.put("key1","lisi1");
map.put("key2","lisi2");
map.put("key3","lisi3");
map.put("key4","lisi4");
//先获取map集合的所有键的set集合,keyset()
Iterator it = map.keySet().iterator();
//获取迭代器
while(it.hasNext()){
Object key = it.next();
System.out.println(map.get(key));
}
第二种: entrySet()
Set> entrySet() //返回此映射中包含的映射关系的Set视图
一个关系就是一个键-值对, 就是把(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.put("key4","lisi4");
//将map集合中的映射关系取出,存入到set集合
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry e = (Map.Entry) it.next();
System.out.println("键" + e.getKey() + "的值为" + e.getValue());
}
推荐使用第二种方式, 即entrySet()方法,效率高.
对于keySet其实是遍历了2次,一次是转为iterator, 一次就是从HashMap中取出key所对应的value. 而entrySet只是遍历了第一次, 它把key 和value都放到了entry中, 所以快了. 两种遍历时间相差还是很明显的.
主要实现类区别小结
Vector和ArrayList
Vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的. 如果不考虑线程的安全因素, 一般用ArrayList的效率比较高.
如果集合中的元素的数目大于目前集合数组的长度时,Vector增长率为目前数组长短的100%, 而ArrayList增长率为目前数组长度的50%. 如果在集合中使用数据量比较大的数据,用Vector有一定的优势.
-
如果查找一个指定位置的数据,Vector和ArrayList使用的时间是相同的,如果频繁的访问数据,这个时候使用Vector和ArrayList都可以. 而如果移动一个指定位置会导致后面的元素都发生移动,这个时候就应该考虑到使用LinkList, 因为他移动一个指定位置的数据时其它元素不移动.
ArraList和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引数据快,插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差, LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历, 但是插入数据时只需要记录本项的前后项即可,所以插入数据速度较快.
ArrayList和LinkedList
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.
- 对于随机访问get和set, ArrayList优于LinkedList, 因为LinkedList要移动指针.
- 对于新增和删除操作add和remove, LinkedList比较占优势, 因为ArrayList要移动数据. 这一点要看实际情况的. 若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList.但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList,因为ArrayList每插入一条数据, 要移动插入点之后的所有数据
HashMap与TreeMap
HashMap通过hashCode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)
-
在Map中插入,删除和定位元素,HashMap是最好的选择. 但如果您要是按自然顺序或自定义顺序遍历键, 那么TreeMap会更好. 使用HashMap要求添加的键类明确定义了hashCode()和equals()的实现
两个map中的元素一样,但顺序不一样,导致hashCode()不一样
同样做测试:
在HashMap中,同样的值的map,顺序不同,equals时,false;
而在TreeMap中,同样的值的map,顺序不同,equals时,true, 说明,TreeMap在equals时是整理了顺序的
Hashtable与HashMap
- 同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程不安全的,不是同步的
- HashMap允许存在一个为null的key,多个为null的value
- Hashtable的key和value都不允许为null
集合工具类
Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection有什么区别?
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口,
——List:对元素都有定义索引。有序的。可以重复元素。
——Set:不可以重复元素。无序。 Collections是集合框架中的一个工具类。该类中的方法都是静态的。
提供的方法中有可以对list集合进行排序,二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
- public static void sort(List list) // 根据元素的自然顺序 对指定列表按升序进行排序。
- public static void shuffle(List> list) // 打乱集合中元素的顺序
- max(Collection extends T> coll) // 返回 collection的最大元素
- min(Collection extends T> coll) // 返回collection的最小元素