1、集合树状图

Collection:最基本的集合接口

  ----List:有序集合,集合中的元素可以重复,访问集合中的元素可以根据元素的索引来访问

    ----ArrayList:异步

    ----LinkedList:实现了List和Queue的双接口

    ----Vector:同步

      ----Stack:后进先出,同步

  ----Queue:先入先出(FIFO)数据结构的集合

    ----LinkedList:实现了List和Queue的双接口

  ----Set:无序集合,集合中的元素不可以重复,最多有一个null元素

    ----EnumSet:枚举类型专用,单一枚举类型,无null元素,异步

    ----SortedSet:继承了Set接口,并添加了comparator()自定义排序方法等方法,可以重写该方法进行客户化排序

      ----TreeSet:实现了SortedSet接口(其中JDK类库中有些类如String,Float,Integer,Double等已经实现了Comparable接口作为TreeSet的自然排序方式)。(Tips:Set内部源码仍以Map为基础,是value为空对象的Key集合)

    ----HashSet:异步,最多有一个null元素

      ----LinkedHashSet:继承HashSet,调用了 LinkedHashMap中记录插入元素顺序的recordAccess()方法。

MAP:保存Key-value对形式的元素,访问时只能根据每项元素的key来访问其value

  ----HashMap:异步,允许null,即null value和null key

    ----WeakHashMap:对key实行“弱引用”,如果一个key不再被外部所引用,该key可以被GC回收

  ----Hashtable:同步,不允许null

  ----SortedMap:继承了Map接口,并添加了comparator()自定义排序方法等方法,可以重写该方法进行客户化排序

      ----TreeMap:实现了SortedMap接口(其中JDK类库中有些类如String,Float,Integer,Double等已经实现了Comparable接口作为TreeMap的自然排序方式)

2、集合统计信息

对于Set、List和Map三种集合,最常用的实现类分别是HashSet、ArrayList和HashMap三个实现类;

Vector、HashTable、Properties和Stack是同步类,所以它们是线程安全的,可以在多线程环境下使用;

ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问;

3、集合遍历

Iterator(迭代器) :hasNext()  next()  remove()

当前遍历的集合元素被更改的时候,会抛出ConcurrentModificationException,避免报错CopyOnWriteArrayList;(Enumeration不会,不安全)

for(for循环):

一:for(Iterator iterator = list.iterator();iterator.hasNext();)

二:Iterator iterator = list.iterator();   while(iterator.hasNext()){

三:for (Object object : list) {(从JDK1.5开始出现的语法,相当于 while(iterator.hasNext(),所以这里的for循环内部还是迭代器方式遍历)

四: for (int i = 0 ;i<list.size();i++) {

4、原理

一、Hashtable、HashMap、HashSet的实现原理:

底层数据结构是哈希表;

首先判断hashCode()值是否相同

是:继续执行equals(),看其返回值

  是true:说明元素重复,不添加

  是false:就直接添加到集合

否:就直接添加到集合

最终:自动生成hashCode()和equals()即可;

二、线程安全:Hashtable和ConcurrentHashMap

Hashtable:synchronized是针对整张Hash表的,即每次锁住整张表让线程独占;

ConcurrentHashMap:锁分离,使用了多个锁来控制对hash表的不同部分(段Segment);但size()和containsValue()等方法依然是跨段对整个表进行加锁(按顺序锁定所有段);ConcurrentHashMap的迭代器为弱一致性,即在遍历并遇到修改时会复制数据进行遍历,遍历结束再将迭代器指针指向新数据。

各种集合的原理详解---jdk源码

Arraylist    LinkList  HashMap  HashSet

1.ArrayList

  private transient Object[] elementData;
private int size;
 public ArrayList(int paramInt)
{
if (paramInt < 0)
throw new IllegalArgumentException("Illegal Capacity: " + paramInt);
this.elementData = new Object[paramInt];
} public ArrayList()
{
this(10);
}

ArrayList构造方法,支持预定长度,使用类中的全局变量Object类型的数组,进行数据的保存。

2.LinkList

 private transient Entry<E> header;
private transient int size;
   public LinkedList()
{
this.header = new Entry(null, null, null);
this.size = 0; this.header.next = (this.header.previous = this.header);
} public LinkedList(Collection<? extends E> paramCollection)
{
addAll(paramCollection);
}

LinkList  构造方法,支持预设值一个集合,方法addAll为for循环创建并增加集合数据。

 private static class Entry<E>
{
E element;
Entry<E> next;
Entry<E> previous; Entry(E paramE, Entry<E> paramEntry1, Entry<E> paramEntry2)
{
this.element = paramE;
this.next = paramEntry1;
this.previous = paramEntry2;
}
}

LinkList  中的Entry 为静态内部私有类,包括前后指针和数据。

3.HashMap 存储/读取数据原理:

//定义
//private transient Set<Map.Entry<K, V>> entrySet; public HashMap(int paramInt)
{
this(paramInt, 0.75F);
} public HashMap()
{
this.entrySet = null; this.loadFactor = 0.75F;
this.threshold = 12;
this.table = new Entry[16];
init();
} public HashMap(Map<? extends K, ? extends V> paramMap)
{
this(Math.max((int)(paramMap.size() / 0.75F) + 1, 16), 0.75F); putAllForCreate(paramMap);
}

HashMap在无参数下,初始化entry为16(2的指数),仅保存12个元素;以16为基础翻倍扩容,存储数据以12为基础翻倍增加;

 public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable {
private static final int MINIMUM_CAPACITY = 4;
...
transient HashMapEntry<K, V>[] table;
...
private static final Entry[] EMPTY_TABLE
= new HashMapEntry[MINIMUM_CAPACITY >>> 1];
...
@Override public V put(K key, V value) {
if (key == null) {
return putValueForNullKey(value);
} int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
preModify(e);
V oldValue = e.value;
e.value = value;
return oldValue;
}
} // No entry for (non-null) key is present; create one
modCount++;
if (size++ > threshold) {
tab = doubleCapacity();
index = hash & (tab.length - 1);
}
addNewEntry(key, value, hash, index);
return null;
}
...
public V get(Object key) {
if (key == null) {
HashMapEntry<K, V> e = entryForNullKey;
return e == null ? null : e.value;
} int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
e != null; e = e.next) {
K eKey = e.key;
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
return e.value;
}
}
return null;
}
...
}

分析下put方法的实现:

  • if (key == null) {

return putValueForNullKey(value);

}

首先判断是否为null,如果为null则特殊处理;

  • 2、int hash = Collections.secondaryHash(key);

获取Key的二级hash值,其中Collections.secondaryHash方法的实现就是把Key的hashcode值做一定改变;

  • int index = hash & (tab.length - 1);

通过刚才计算的hash值来获取该key应该存放在数组的下标位置,也就是获取该数据应该存储在table数组的哪个位置;

  • for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {

if (e.hash == hash && key.equals(e.key)) {

preModify(e);

V oldValue = e.value;

e.value = value;

return oldValue;

}

}

如果已经有该key存在了,则覆盖这个key的值value。

注意这里的判断:因为只有两个对象的hashcode值相等并且两个对象用equals判断返回true时,才去覆盖原有的值;

  • if (size++ > threshold) {

tab = doubleCapacity();

index = hash & (tab.length - 1);

}

addNewEntry(key, value, hash, index);

如果该key不存在,或者发生碰撞的对象不是一个对象时,则需要把它存储下来。首先如果存储数量已经大于数组大小,则把数组双倍扩大。然后再把键值对保存到数组中。

注意这里保存的时候,如果数组存储位置原本就存在键值对,那么则把新的键值对对象保存到旧的键值对 对象next变量中,构成链表。

  • hashMap是table和entry的组合,他的扩容机制,保证table与entry比例均衡,对table的查询与entry的修改的优点进行均衡采用。

4.HashSet

  private transient HashMap<E, Object> map;
private static final Object PRESENT = new Object();
public HashSet()
{
this.map = new HashMap();
}
  public boolean add(E paramE)
{
return (this.map.put(paramE, PRESENT) == null);
}

由源码可见,HashSet用的就是HashMap实现的,其类中定义一个final状态的Object对象,作为每个数据元素的value,HashSet仅仅使用HashMap的key进行数据的保存,其remove等方法均调用HashMap的方法实现。

JAVA总结--集合的更多相关文章

  1. 【Java】集合_学习笔记

    一.集合 1.集合类也称容器类,主要负责保存.盛装其他数据. 2.集合可以保存数量不确定的数据,保存具有映射关系的数据(也称关联数组). 3.Java5后提供一些多线程安全的集合类,放在java.ut ...

  2. java的集合框架最全详解

    java的集合框架最全详解(图) 前言:数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作 ...

  3. 谈谈Java的集合组件

    让我们一起谈谈Java的集合组件 我们在使用Java的时候,都会遇到并使用到Java的集合.在这里通过自己的理解和网上的资源对Java的集合方面的使用做一个简单的讲解和总结. Java主要分为3个集合 ...

  4. java.util 集合框架集合

    java的集合框架为程序提供了一种处理对象组的标准方式.设计了一系列标准泛型接口: ⑴Collection ()接口,扩展了Iterable接口,位于集合层次结构的顶部,因此所有的集合都实现Colle ...

  5. Java基础——集合框架

    Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...

  6. Java学习-集合(转)

    在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...

  7. java的集合框架之一

    java是一套很成熟的东西,很多商用的东西都喜欢用它,用的人多,稳定.不过一般也不怎么说起它,因为太常见了,私下里说,写java应用层得就像农民工,每一处都是搭积木,根据设计师的东西如何优雅地搭好积木 ...

  8. 浅谈Java的集合框架

    浅谈Java的集合框架 一.    初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...

  9. Java之集合初探(一)

    一.集合概述.区别 集合是一种容器,数组也是一种容器 在Java编程中,装各种各样的对象(引用类型)的叫做容器. 为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的 ...

  10. Java面向对象 集合(下)

      Java面向对象 集合(下) 知识概要:               (1)Map集合的体系结构 (2)Map集合的方法 (3)HashMap TreeMap (4)集合框架中的常用工具类 ( ...

随机推荐

  1. GUI学习之二十八—QMessageBox

    今天来学习下QMessageBox. QMessageBox主要用来通知用户或者请求用户提问和接收应答一个模态对话框. 一.对话框的构成 图标是有标准图标的,可以直接调用. 我们声明的消息框,初始状态 ...

  2. 应用程序不了找到mysql中的表,客户端可以正常打开表

    原因是mysql中区分大小写的参数:lower-case-table-names=1  默认是区分大小写的,程序中代码可能是大小写混合的,其中访问数据库的sql是大小写混合的.所以找不到数据库中的表 ...

  3. 如何用git将本地代码上传github

    其实去年就用github了,但是毕竟也只是在上面搜索一些工作的难点和自我学习,自己都没有贡献过代码,觉得确实很low,知道今天自己用了2周左右的时间开发了 微信小程序,有了自己的贡献代码,所以想上传到 ...

  4. mysql Update语句 语法

    mysql Update语句 语法 作用:用于修改表中的数据.广州大理石机械构件 语法:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值 mysql Update语句 示例 ...

  5. Java——容器(Interator)

    [Interator接口]   <1> 所有实现了Collection接口的容器类都有一个interator方法用以返回一个实现了Interaor接口的对象. <2> Inte ...

  6. 原来程序是这样从NandFlash拷贝并跳转到SDRAM的

    重新看了一下FL2440的BootLoader,终于把程序是怎样从Nandflash拷贝并跳转到SDRAM的过程弄清楚了,在这边做一下笔记.先上张图: 1. 当S3C2440被配置成从Nand Fla ...

  7. FLASH位宽为8、16、32时,CPU与外设之间地址线的连接方法

    转 http://blog.csdn.net/linweig/article/details/5556819 flash连接CPU时,根据不同的数据宽度,比如16位的NOR FLASH (A0-A19 ...

  8. windows 删除文件或文件夹

    删除文件夹 rd 文件夹名 (只能删除空文件夹) 删除整个文件夹及子文件所有 rd /s 文件夹名(删除该文件及子文件) 删除文件 del 文件名(删除该文件)

  9. 在github pages网站下用jekyll制作博客教程

    https://www.jekyll.com.cn/ https://github.com/onevcat/vno-jekyll https://help.github.com/articles/us ...

  10. angular 发送ajax

    在使用angular发送ajax的时候get和post一样的,就是method改一下. ajax的js: <script> var app = angular.module('emialV ...