Java Collection Framework概述
文章出自:听云博客
Collection概述
Java collection是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。
Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator、Arrays和Collections)。
Java collection 结构图
通过上图我们可以看出
Collection是一个interface
Collection有List和Set两大分支。
List<E>是一个队列,根据下标索引,第一个元素的下标是0,List的实现类有LinkedList, ArrayList, Vector, Stack。List是有序的队列,List中可以有重复的值。
Set<E>是一个集合,SET中的值是唯一的,我们经常会遇到List去重的问题,把List转为SET就可以快速实现 Set的实现类有HastSet和TreeSet。HashSet。其中TreeSet是有序的。
Ma<K,V>是一个interface,即key-value键值对。Map中的每一个元素包含“一个key”和“key对应的value”。
AbstractMap是个抽象类,它实现了Map接口中的大部分API。而HashMap,TreeMap,WeakHashMap都是继承于AbstractMap。
Iterator。它是遍历集合的工具,我们经常使用Iterator迭代器来遍历集合。Collection的实现类都要实现iterator()函数,返回一个Iterator对象。
抽象类AbstractCollection、AbstractList、AbstractSet、AbstractMap是抽象类,他们都实现了各自的大部分方法,我们直接继承Abstract类就可以省去重复编码相同的方法 。PS当时来面试的时候被问到这个问题竟然一下没想起来。
List简介
1、List 是一个接口,它继承于Collection的接口。它代表着有序的队列。
2、AbstractList 是一个抽象类,它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。
3、AbstractSequentialList 是一个抽象类,它继承于AbstractList。AbstractSequentialList 实现了“链表中,根据index索引值操作链表的全部函数”。
4、ArrayList, LinkedList, Vector, Stack是List的4个实现类。
ArrayList 是一个数组队列。它由数组实现,实现了RandomAccess, Cloneable, java.io.Serializable接口,所以可以随便访问,克隆,序列化,随机访问效率高,随机插入、随机删除效率低。
LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率低。
Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。
Stack 是栈,继承于Vector。栈的特点是:先进后出(First In Last Out)。
List和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。
List的使用
1、如果涉及到“栈”、“队列”、“链表”等操作,应该考虑用List,具体的选择哪个List,根据下面的标准来取舍。
2、对于需要快速插入,删除元素,应该使用LinkedList。
3、对于需要快速随机访问元素,应该使用ArrayList。
4、对于“单线程环境” 或者 “多线程环境,但List仅仅只会被单个线程操作”,此时应该使用非同步的类(如ArrayList)。
5、对于“多线程环境,且List可能同时被多个线程操作”,此时,应该使用同步的类(如Vector)。
Fail-Fast
fail-fast 机制是java集合(Collection)中的一种错误机制。当一个线程遍历某集合时,这个集合的值被其它线程改变,该线程就会抛出ConcurrentModificationException异常。
fail-fast示例。
- package Test;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- public class FastFailEX {
- private static List<Integer> list = new ArrayList<Integer>();
- public static void main(String[] args) {
- //使用两个线程操作list
- new ThreadA().start();
- new ThreadB().start();
- }
- private static void print() {
- System.out.println("");
- Integer value = null;
- Iterator<Integer> iter = list.iterator();
- while(iter.hasNext()) {
- value = (Integer)iter.next();
- System.out.print(value+", ");
- }
- }
- //向list添加元素
- private static class ThreadA extends Thread {
- public void run() {
- for(int i=0;i<10;i++){
- list.add(i);
- print();
- }
- }
- }
- //向list添加元素
- private static class ThreadB extends Thread {
- public void run() {
- for(int i=10;i<20;i++){
- list.add(i);
- print();
- }
- }
- }
- }
运行结果:
结果说明:
当某一个线程遍历list的过程中,list的内容被另外一个线程所改变了;就会抛出ConcurrentModificationException异常,产生fail-fast事件。
ConcurrentModificationException是在操作Iterator时抛出的异常。我们先看看Iterator的源码。在AbstractList.java中
通过以上代码段我们看到两点
1、执行next()时,要先判断iterator返回的对象中的modCount”和“当前的modCount”是否相等
2、如果不相等,则抛回异常
接下来我们要知道在什么情况下 modCount!= expectedModCount
我们来看ArrayList.java中的代码
我们现在知道,只要修改集合中的元素个数时,都会改变modCount的值。
添加时在决定是否扩空list前修改modCount,删除元素时直接修改
至此,我们就完全了解了fail-fast是如何产生的。
即,当多个线程对同一个集合进行操作的时候,某线程访问集合的过程中,该集合的内容被其他线程所改变(即其它线程通过add、remove、clear等方法,改变了modCount的值);这时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。
解决fail-fast
使用CopyOnWriteArrayList 就不会产生fail-fast
上源码
从中,我们可以看出:
CopyOnWriteArrayList是自己实现了Iterator 为COWIterator。
ArrayList的Iterator调用next()时,会调用checkForComodification()比较expectedModCount和modCount的大小;CopyOnWriteArrayList的Iterator实现类中,没有checkForComodification(),所以不会抛出ConcurrentModificationException异常。
Map简介
Map是什么:public interface Map<K,V> { }
Map 是一个键值对(key-value)映射接口。Map映射中不能包含重复的键;每个键最多只能映射到一个值。
Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。
Map 映射顺序。有些实现类,可以明确保证其顺序,如 TreeMap;另一些映射实现则不保证顺序,如 HashMap 类。
Map 的实现类应该提供2个“标准的”构造方法:第一个,void(无参数)构造方法,用于创建空映射;第二个,带有单个 Map 类型参数的构造方法,用于创建一个与其参数具有相同键-值映射关系的新映射。实际上,后一个构造方法允许用户复制任意映射,生成所需类的一个等价映射。尽管无法强制执行此建议(因为接口不能包含构造方法),但是 JDK 中所有通用的映射实现都遵从它。
Map体系
1、Map 是映射接口,Map中存储的内容是键值对(key-value)。
2、AbstractMap 是继承于Map的抽象类,它实现了Map中的大部分API。其它Map的实现类可以通过继承AbstractMap来减少重复编码。
3、SortedMap 是继承于Map的接口。SortedMap中的内容是排序的键值对,排序的方法是通过比较器(Comparator)。
4、NavigableMap 是继承于SortedMap的接口。相比于SortedMap,NavigableMap有一系列的导航方法;如"获取大于/等于某对象的键值对"、“获取小于/等于某对象的键值对”等等。
5、TreeMap 继承于AbstractMap,且实现了NavigableMap接口;因此,TreeMap中的内容是“有序的键值对”, 它是通过红黑树实现的。它一般用于单线程中存储有序的映射。
6、HashMap 继承于AbstractMap,没实现SortedMap或NavigableMap接口;因此,HashMap的内容是无序的键值对。
7、Hashtable继承于Dictionary(Dictionary也是键值对的接口),实现Map接口;因此,Hashtable的内容也是“键值对,是无序的”。 Hashtable是线程安全的。
8、WeakHashMap 继承于AbstractMap。它和HashMap的键类型不同,WeakHashMap的键是“弱键”, 当“弱键”被GC回收时,它对应的键值对也会被从WeakHashMap中删除。JVM提供的弱引用
Set简介
Set 是继承于Collection的接口。它是一个不允许有重复元素的集AbstractSet 是一个抽象类,它继承于AbstractCollection,AbstractCollection实现了Set中的绝大部分函数,为Set的实现类提供了便利。
HastSet 和 TreeSet 是Set的两个实现类。
HashSet中的元素是无序的。
TreeSet中的元素是有序的,不支持快速随机遍历,只能通过迭代器进行遍历。
Iterator和Enumeration
在Java集合中,我们通常都通过 “Iterator(迭代器)” 或 “Enumeration(枚举类)” 去遍历集合
Enumeration是一个接口,它的源码如下
Iterator也是一个接口,它的源码如下:
1、函数接口不同
Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。
Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。
2、Iterator支持fail-fast机制,而Enumeration不支持。
Iterator和Enumeration性能对比
package Test;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Random;
- public class IteratorEnumerationEX {
- public static void main(String[] args) {
- int val;
- Random r = new Random();
- Hashtable<Integer, Integer> table = new Hashtable<Integer, Integer>();
- for (int i=0; i<100000; i++) {
- val = r.nextInt(100);
- table.put(i, val);
- }
- iterateHashtable(table) ;
- enumHashtable(table);
- }
- private static void iterateHashtable(Hashtable<Integer, Integer> table) {
- long startTime = System.currentTimeMillis();
- Iterator<Entry<Integer, Integer>> iter = table.entrySet().iterator();
- while(iter.hasNext()) {
- iter.next();
- }
- long endTime = System.currentTimeMillis();
- countTime("iterate",startTime, endTime);
- }
- private static void enumHashtable(Hashtable<Integer, Integer> table) {
- long startTime = System.currentTimeMillis();
- Enumeration<Integer> enu = table.elements();
- while(enu.hasMoreElements()) {
- enu.nextElement();
- }
- long endTime = System.currentTimeMillis();
- countTime("enum",startTime, endTime);
- }
- private static void countTime(String type,long start, long end) {
- System.out.println(type+":"+(end-start)+"ms");
- }
- }
输出结果
因为Iterator支持fail-fast所以做操作多一些性能也相对慢一些
原文链接:http://blog.tingyun.com/web/article/detail/268
Java Collection Framework概述的更多相关文章
- java collection framework
java collection framework Map
- Java Collection Framework : List
摘要: List 是 Java Collection Framework的重要成员,详细包括List接口及其全部的实现类.由于List接口继承了Collection接口,所以List拥有Collect ...
- Java Collection集合概述及其常用方法
Collection集合概述 Java数组的长度是固定的,为了使程序能够方便地存储和操作数目不固定的一组数据,JDK类库提供了Java集合 与数组不同的是,集合中不能存放基本类型数据,而只能存放对象的 ...
- 集合框架(JCF/Java Collection Framework)
集合的特点:1.数据的类型可以不同2.集合长度可变3.空间不固定集合也是对象,用于检索,存储以及传输对象集合框架的组成Collection接口和Map接口 Collection是Set接口和List接 ...
- 设计: ListView 接口,and the missing read-only interfaces in java collection framework
Java的集合框架以其成功易用的设计征服了很多人(包括我),并且教科书式的诠释了泛型的应用方式. 我也是被 Joshua Bloch 的书引领入门,从中得益良多.我当然不会认为自己在设计上比他懂得更多 ...
- Java Collection Framework 备忘点
最顶端是两个接口,集合和映射—— Collection<T> / Map<K, V> List 列表 保持插入顺序 ArrayList 擅长随机读 LinkedList ...
- Java Collections Framework知识结构目录
The core collection interfaces are the foundation of the Java Collections Framework. The Java Collec ...
- (一)一起学 Java Collections Framework 源码之 概述
. . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述 JDK 中很多类 LZ 已经使用了无数次,但认认真真从源码级研究过其原理的还只占少数,虽然从 ...
- (二)一起学 Java Collections Framework 源码之 AbstractCollection
. . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述(未完成) (二)一起学 Java Collections Framework 源码之 Abs ...
随机推荐
- Javascript动画效果(三)
Javascript动画效果(三) 前面我们已经介绍了速度动画.透明度动画.多物体运动和任意值变化,并且我们在Javascript动画效果(二)中介绍到我们封装了一个简单的插件雏形,接下来我们对前面的 ...
- 关于Entity Framework中的Attached报错的完美解决方案终极版
之前发表过一篇文章题为<关于Entity Framework中的Attached报错的完美解决方案>,那篇文章确实能解决单个实体在进行更新.删除时Attached的报错,注意我这里说的单个 ...
- React Native版本升级的正确姿势
基于React Native(简称:RN)的APP也发布了三个版本了,RN由于两周就会发布一版从最开始项目用的0.29到最近的0.37,做为一个开源项目来说更新真是跟坐火箭般快速,当然对于我们使用的人 ...
- Android客户端消息推送原理简介
首先简单介绍一下Android消息推送的主要三种方式,如果你已经看过类似的文章,请直接忽略三种介绍. 1.使用SMS服务,即服务器端发送短信,然后手机客户端监听短信的广播,然后对数据进行一定的处 ...
- QTableWidget控件总结<二>
QTableWidget是QT程序中常用的显示数据表格的空间,很类似于VC.C#中的DataGrid.说到QTableWidget,就必须讲一下它跟QTabelView的区别了.QTableWidge ...
- HoverTree项目添加了查看留言列表功能
HoverTree项目添加了查看留言列表功能 页面:HoverTreeWeb项目下hvtpanel/usermessage/messagelist.aspx 添加留言页面:addmessage.asx ...
- Windows 7专业版安装VS2005与WinCE6.0开发环境
近期更新了自己的小黑从XP更新到WIN7专业版,我花了两天时间验证了下列软件安装在WIN7 PRO是完全兼容的. 1:2011年最新更新的SourceInsight3.50.0066版本,这个是支持W ...
- NanUI for Winform 使用示例【第二集】——做一个所见即所得的Markdown编辑器
经过了这一个多星期的调整与修复,NanUI for .NET Winform的稳定版已经发布.应广大群友的要求,现已将NanUI的全部代码开源. GitHub: https://github.com/ ...
- PHP程序员7小时学会Kotlin 第二小时
Kotlin中,一切皆对象:PHP则并非一切皆对象,甚至不需要对象的存在即可完成系统功能开发,我们现在可以接触到的旧的系统都可以说明这一点. 基本数据类型 数值型 类型 位长 双精度浮点型Double ...
- Oracle数据库,join多表关联方式、union结果集合并
join on : 多表关联 内连接 :与其他表连接 from 表1 t join 表2 s on t.字段1 =s.字段2 join 表3 n on n.字段3=t.字段1 或 from 表1 ...