文章出自:听云博客

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概述的更多相关文章

  1. java collection framework

    java collection framework Map

  2. Java Collection Framework : List

    摘要: List 是 Java Collection Framework的重要成员,详细包括List接口及其全部的实现类.由于List接口继承了Collection接口,所以List拥有Collect ...

  3. Java Collection集合概述及其常用方法

    Collection集合概述 Java数组的长度是固定的,为了使程序能够方便地存储和操作数目不固定的一组数据,JDK类库提供了Java集合 与数组不同的是,集合中不能存放基本类型数据,而只能存放对象的 ...

  4. 集合框架(JCF/Java Collection Framework)

    集合的特点:1.数据的类型可以不同2.集合长度可变3.空间不固定集合也是对象,用于检索,存储以及传输对象集合框架的组成Collection接口和Map接口 Collection是Set接口和List接 ...

  5. 设计: ListView 接口,and the missing read-only interfaces in java collection framework

    Java的集合框架以其成功易用的设计征服了很多人(包括我),并且教科书式的诠释了泛型的应用方式. 我也是被 Joshua Bloch 的书引领入门,从中得益良多.我当然不会认为自己在设计上比他懂得更多 ...

  6. Java Collection Framework 备忘点

    最顶端是两个接口,集合和映射——  Collection<T>  /  Map<K, V> List 列表 保持插入顺序 ArrayList 擅长随机读 LinkedList ...

  7. Java Collections Framework知识结构目录

    The core collection interfaces are the foundation of the Java Collections Framework. The Java Collec ...

  8. (一)一起学 Java Collections Framework 源码之 概述

    . . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述 JDK 中很多类 LZ 已经使用了无数次,但认认真真从源码级研究过其原理的还只占少数,虽然从 ...

  9. (二)一起学 Java Collections Framework 源码之 AbstractCollection

    . . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述(未完成) (二)一起学 Java Collections Framework 源码之 Abs ...

随机推荐

  1. 基于HTML5技术的电力3D监控应用(一)

    最近参与了国网计量中心的四线一库自动化检定系统的项目开发,团队封闭开发了大半年终于快到尾声了,整个项目过程实在非常累,我的mentor杨杨老师是这样描述的:累的不想说话了.我估计是我太渴望新知识,整天 ...

  2. 使用PhoneGap搭建一个山寨京东APP

    为什么要写一个App 首先解释下写出来的这个App,其实无任何功能,只是用HTML和CSS模仿JD移动端界面写的一个适配移动端的Web界面.本篇主要内容是介绍如何使用PhoneGap把开发出来的mob ...

  3. 使用Uploadify(UploadiFive)多文件上传控件遇到的坑

    最近项目中需要实现多文件上传功能,于是结合需求最终选择了Uploadify这一款控件来实现.相比其他控件,Uploadify具有简洁的界面,功能API基本可以解决大多数需求,又是基于jquery的,配 ...

  4. CentOS matplotlib 安装

    sudo yum install freetype-devel sudo yum install libpng-devel sudo pip install matplotlib

  5. [译]学习IPython进行交互式计算和数据可视化(二)

    第一章:开始使用IPython 在本章中,我们首先进行一遍IPython的安装过程,在大概浏览一下IPython提供的功能.IPython提供了一个高度优化的Python控制台和Notebook.除此 ...

  6. Rebalance Customer Balances Utility的使用

    用户不管是打开A/R Posted Transactions Detail还是A/R Posted Transactions Summary 窗口,均显示如下一个警示: 打开Currency Code ...

  7. ExtJs动态生成treepanel的Json格式

    在节点中加上"checked"属性,会自动生成checkbox. 获取选中节点 var nodeArray = ""; var nodesObj = mytre ...

  8. c# datetime 格式化

    //c datetime 格式化 DateTime dt = DateTime.Now; Label1.Text = dt.ToString();//2005-11-5 13:21:25 Label2 ...

  9. 【Java每日一题】20161013

    package Oct2016; public class Ques1013{ public static void main(String[] args){ new Obj(); } } class ...

  10. SQL简单语句总结习题

    创建一个表记员工个人信息: --创建一个表 create table plspl_company_info( empno ) not null, ename ) not null, job ), ma ...