ArrayList:

1. ArrayList是List接口的大小可变数组的实现,此实现是不同步的。

2. ArrayList内部使用类型为Object[]的数组存储元素。

3. ArrayList默认的数组长度为10, 当需要扩大容量时,扩大后的容量为:newCapacity = (oldCapacity * 3)/2 + 1;

4. ArrayList的clone方法为浅拷贝(shallow copy)

5. ArrayList的remove方法根据参数类型的不同有两种重载:

remove(int index) : 删除指定位置的元素;

remove(Object o)  : 删除第一个遇到的元素,如果没有不做改变

6. ArrayList允许null值、允许重复值、不排序,获取快速,增删麻烦。

HashMap:

HashMap是不同步的。

 HashMap内部使用类型为Entry[]的数组存储元素。Entry是HashMap的一个内部类,定义如下所示。

 每一个Entry对象其实是一个单向链表,之后的解析可以看到,最后存入的元素在最前面。

备注:下面出现的代码都是HashMap.java中的源码,中文描述是作者加的。

 transient Entry[] table;//HashMap内部定义的数据存储变量
     //内部类
     static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        final int hash;
        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }

       *****
       省略
       *****
    }

HashMap中几个概念:

capacity:容量,即Entry[]数组的长度

 loadFactor:负载因子,Entry[]数组中实际数据量/容量的比例达到loadFactor时,HashMap就需要扩大容量了,一般扩大为原来的两倍。

 threshold: 当HashMap中的元素个数超过这个数值时,就将扩大容量。

put方法:

public V put(K key, V value) {
        if (key == null)
        //如果key为null,特殊处理,key为null直接存储在table[0]位置。
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);//此处得到的i即为key对应的HashMap中的存储位置table[i]
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        //从Entry链表的第一个开始如果找到与key执行equals方法为true的Entry,则修改对应Entry的value值为新值,key不做修改
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        //如果没有找到对应的key,则执行增加操作
        addEntry(hash, key, value, i);
        return null;
    } 

void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        if (size++ >= threshold)
            //如果大小超过了threshold,扩大容量为原来的两倍。扩大容量时,所有的key-value需要重新hash。
            resize(2 * table.length);
}

void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }
    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable);//将原来hash表中的数据放入新的hash表中,需要重新hash。
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
}

/**
 * Transfers all entries from current table to newTable.
 */
void transfer(Entry[] newTable) {
    Entry[] src = table;
    int newCapacity = newTable.length;
    for (int j = 0; j < src.length; j++) {
        Entry<K,V> e = src[j];
        if (e != null) {
            src[j] = null;
            //此处使用循环,将原来hash链中的所有的key-value都重新获取hash值,重新放置。
            //因为放置位置是跟hash表的大小有关的,当hash表容量扩大后,之前放在一个地方的key-value对现在可能hash不到同一个地方了。
            do {
                Entry<K,V> next = e.next;//记录此处的下一个地址
                int i = indexFor(e.hash, newCapacity);//重新计算当前的key-value在新hash表中的位置
                e.next = newTable[i];//将之前在同一位置的数据放在e的next位置,没有则为null
                newTable[i] = e;//将e作为hash表i位置的第一个元素
                e = next;//将next赋值给e, 对原来j位置的所有的元素都执行重新hash,重新放置
            } while (e != null);
        }
    }
}

get方法:按照put时的逻辑根据key获取value。不再详述。

keySet与values方法:

这两个方法作用好理解,但需要注意的是,当对keySet()和values()方法获取到的集合执行remove操作的时候就相当于对HashMap集合本身执行remove操作。看源码通过keySet和values获取到的好像是HashMap的迭代器,这里我没有深究。如果谁明白具体原因不吝赐教。

HashSet:

HashSet的内部是用的HashMap实现的,使用Entry将每一个HashSet元素的引用存储在key位置,value位置使用默认的数据填充。

 在此也可以看到,HashMap中的key-value对其实可以看成value是每一个key的附属,只需要找到每一个key的位置,然后把对应的value放入即可。

ArrayList、HashMap、HashSet源码总结的更多相关文章

  1. HashSet源码学习,基于HashMap实现

    HashSet源码学习 一).Set集合的主要使用类 1). HashSet 基于对HashMap的封装 2). LinkedHashSet 基于对LinkedHashSet的封装 3). TreeS ...

  2. 【Java集合】HashSet源码解析以及HashSet与HashMap的区别

    HashSet 前言 HashSet是一个不可重复且元素无序的集合.内部使用HashMap实现. 我们可以从HashSet源码的类注释中获取到如下信息: 底层基于HashMap实现,所以迭代过程中不能 ...

  3. Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  4. java基础解析系列(十)---ArrayList和LinkedList源码及使用分析

    java基础解析系列(十)---ArrayList和LinkedList源码及使用分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder jav ...

  5. HashSet源码分析

    在java集合中有一种集合Set(集),他有两个实现类,分别是HashSet,TreeSet.下面仔细分析HashSet源码. 看了HashSet的源码就会发现HashSet的底层实现是利用HashM ...

  6. HashSet源码

    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java. ...

  7. 死磕Java之聊聊HashSet源码(基于JDK1.8)

    HashSet的UML图 HashSet的成员变量及其含义 public class HashSet<E> extends AbstractSet<E> implements ...

  8. HashSet源码分析:JDK源码系列

    1.简介 继续分析源码,上一篇文章把HashMap的分析完毕.本文开始分析HashSet简单的介绍一下. HashSet是一个无重复元素集合,内部使用HashMap实现,所以HashMap的特征耶继承 ...

  9. Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例

    概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解Arra ...

  10. 【转】Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例

    原文网址:http://www.cnblogs.com/skywang12345/p/3308556.html 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具 ...

随机推荐

  1. 出错信息:Incorrect string value: '\xE4\xBD\xA0\xE5\xA5\xBD' for column 'username'

    出错信息: java.sql.SQLException: Incorrect string value: '\xE4\xBD\xA0\xE5\xA5\xBD' for column 'username ...

  2. [SDOI 2013]森林

    Description 题库链接 给你 \(n\) 个节点,初始 \(m\) 条边, \(t\) 组操作.让你支持: 询问树上路径点权 \(K\) 小: 支持加边操作. 强制在线,所有状态保证是一个树 ...

  3. [Luogu 3902]Increasing

    Description Input Output Sample Input 3 1 3 2 Sample Output 1 HINT 题解 由于题目要求我们求严格递增的数列,即: $$A[i]> ...

  4. [Vijos 2024]无向图最短路径

    Description 无向图最短路径问题,是图论中最经典也是最基础的问题之一.本题我们考虑一个有 $n$ 个结点的无向图 $G$.$G$ 是简单完全图,也就是说 $G$ 中没有自环,也没有重边,但任 ...

  5. [HAOI2006]数字序列

    题目描述 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. 输入输出格式 输入格式: 第一行包含一个数 ...

  6. [USACO13DEC]假期计划(黄金)Vacation Planning (gold)

    题目翻译不好,这里给出一份 题目背景 Awson是某国际学校信竞组的一只大佬.由于他太大佬了,于是干脆放弃了考前最后的集训,开车(他可是老司机)去度假.离开学校前,他打开地图,打算做些规划. 题目描述 ...

  7. 成也DP,败也DP(AFO?)

    不知道想说什么.. 从来没写过博客,markdown什么的也不会,凑合着看一下吧. 初中的时候开始搞OI,学了两个月后普及组爆零就退赛了. 初三直升的时候说每个人都要选竞赛,抱着混一混的心态选了信息, ...

  8. Codeforces Round #460 D. Karen and Cards

    Description Karen just got home from the supermarket, and is getting ready to go to sleep. After tak ...

  9. hdu 5514 Frogs(容斥)

    Frogs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  10. [USACO 5.1.3]乐曲主题

    Description 我们用N(1 <= N <=5000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,每个数表示钢琴上的一个键.很不幸这种表示旋律的方法忽略了音符的 ...