Java集合类的底层实现探索

List:

  ArrayList

    首先我们来看看jdk的ArrayList的add方法的源码是如何实现的:     

    public boolean add(E e) {
      ensureCapacityInternal(size + 1); // Increments modCount!!
      elementData[size++] = e;
      return true;
    }

    在AarryList类有如下数组的定义

/**
    * The array buffer into which the elements of the ArrayList are stored. --这是个存储ArrayList元素的数组
    * The capacity of the ArrayList is the length of this array buffer.  ---ArrayList的长度即是数组的长度
    */
    private transient Object[] elementData;

  综上所看,ArrayList底层存储的实现是通过一个数组来实现的

LinkedList

  上源码:

  /**
  * Pointer to first node.
  * Invariant: (first == null && last == null) ||
  * (first.prev == null && first.item != null)
  */
  transient Node<E> first;

  /**
  * Pointer to last node.
  * Invariant: (first == null && last == null) ||
  * (last.next == null && last.item != null)
  */
  transient Node<E> last;

  /**
  * Links e as last element.
  */
  void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
      first = newNode;
    else
      l.next = newNode;
    size++;
    modCount++;
   }

//在ArrayList内部是有这么一个作为"节点"的内部类的

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
      this.item = element;
      this.next = next;
      this.prev = prev;
    }
  }

个人理解:至此可以猜测到LinkedList底层实现是链表;这里代码只是列举了往集合末尾添加元素的情况,具体看linkLast(E e)这个方法

linkLast方法内会根据参数e生成Node,再根据tail具体情况,修改生成node的pre/next指向,存储形式也就是链表啦

  Map:

      map的底层实现是  数组+链表

           描述一下map存储key-value的过程:

             key和value两个对象put到map的时候,会被封装成Entry<K,V>实体对象;put过程会根据K值生成一个hash码值(int类型,不同的key可能会生成相同的hash码)

                   这个hash码会被当成数组的索引/下标(index),数组的每个下标对应一个hash码,而一个hash码对应一个链表(链表存储着具有相同hash码的对象)

                  比如: 现在要  map.put("aa","123");  "aa"对应的hash码是121

                                         map.put("bb","123"); "bb"对应的hash码也是121  执行put操作的时候程序会先到数组找到下标为121(也就是hash的数值)的链表,再通过链表存储put进来的对象

         具体代码:

    

    /**
    * Associates the specified value with the specified key in this map.
    * If the map previously contained a mapping for the key, the old
    * value is replaced.
    *
    * @param key key with which the specified value is to be associated
    * @param value value to be associated with the specified key
    * @return the previous value associated with <tt>key</tt>, or
    * <tt>null</tt> if there was no mapping for <tt>key</tt>.
    * (A <tt>null</tt> return can also indicate that the map
    * previously associated <tt>null</tt> with <tt>key</tt>.)
    */
    public V put(K key, V value) {
      if (key == null)
        return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);  //找出数组对应的下标
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {  //找到数组内对应下标的链表对象
          Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  //原先key已经存在时,覆盖操作
          V oldValue = e.value;
          e.value = value;
          e.recordAccess(this);
          return oldValue;
        }
      }

      modCount++;
      addEntry(hash, key, value, i);//原先不存在key对应的Entry则在链表后添加
      return null;
     }

Set

         set的特点是无序,不重复

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    public boolean add(E e) {
      return map.put(e, PRESENT)==null;
    }

以上是HashSet源码,可以看出HashSet底层是通过Map来实现的,不重复实现:e的hash值相同时,Map会采取覆盖的形式,这样就不会有重复了

Map的无序也就自然导致了HashSet的无序了(hash值求法?HashCode与equals)

"打完收工"....

时间: 2024-07-31 14:34:11

Java集合类的底层实现探索的相关文章

Java集合类: Set、List、Map、Queue使用

目录 1. Java集合类基本概念 2. Java集合类架构层次关系 3. Java集合类的应用场景代码 1. Java集合类基本概念 在编程中,常常需要集中存放多个数据.从传统意义上讲,数组是我们的一个很好的选择,前提是我们事先已经明确知道我们将要保存的对象的数量.一旦在数组初始化时指定了这个数组长度,这个数组长度就是不可变的,如果我们需要保存一个可以动态增长的数据(在编译时无法确定具体的数量),java的集合类就是一个很好的设计方案了. 集合类主要负责保存.盛装其他数据,因此集合类也被称为容

[Java] 集合类(List、Set、Map的基本使用)

数组是一种很常见的数据结构,开始接触编程的时候多数程序都和数组相关.刚开始接触Java时也是一直使用数组写一些程序,后来越来越觉得... 数组是一种很常见的数据结构,开始接触编程的时候多数程序都和数组相关.刚开始接触Java时也是一直使用数组写一些程序,后来越来越觉得数组这东西没法满足需求了,这时一位"前辈"对我说了一句:不会用集合类就等于没学过Java.然后才知道有集合类. 想想已经是3.4年前的事了,时间如白驹过隙啊. 什么时候数组会显得力不从心,没法满足需求,需要集合类呢? 不知

Java集合类: Set、List、Map、Queue使用场景梳理

Java集合类: Set.List.Map.Queue使用场景梳理 本文主要关注Java编程中涉及到的各种集合类,以及它们的使用场景 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E6%8E%92%E5%BA%8F%E5%8F%8Ajava%E9%9B%86%E5%90%88%E7%B1%BB%E8%AF%A6%E8%A7%A3%28collection%E3%80%81list%E3%80%81map%E3%

一张图让你看清Java集合类(Java集合类的总结)

如今关于Java集合类的文章非常多,可是我近期看到一个非常有意思图片,基本上把Java集合的整体框架都给展现出来了.非常直观. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWFtenAyMDA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" align="middle" > 假设发现图片看不清楚.点此处看大图 在这里,

基础知识《六》---Java集合类: Set、List、Map、Queue使用场景梳理

本文转载自LittleHann 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E6%8E%92%E5%BA%8F%E5%8F%8Ajava%E9%9B%86%E5%90%88%E7%B1%BB%E8%AF%A6%E8%A7%A3%28collection%E3%80%81list%E3%80%81map%E3%80%81set%29.rar http://blog.sina.com.cn/s/blog_a345

Java集合类的总结

现在关于Java集合类的文章很多,但是我最近看到一个很有意思图片,基本上把Java集合的总体框架都给展现出来了,很直观. 如果发现图片看不清楚,点此处看大图 在这里,集合类分为了Map和Collection两个大的类别. 处于图片左上角的那一块灰色里面的四个类(Dictionary.HashTable.Vector.Stack)都是线程安全的,但是它们都是JDK的老的遗留类,现在基本都不怎么使用了,都有了对应的取代类.其中Map是用来代替图片中左上角的那个Dictionary抽象类(Map的官方

java集合类源码剖析

java集合类源码剖析 hashmap 底层实现 HashMap.Entry数组,数组+拉链 static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; } Entry对象代表了HashMap中的一个元素(键值对) hashCode相同(碰撞)的元素将分配到Entry数组的同一个桶中 同一个桶中的Entry对象由nex

Java集合类--温习笔记

最近去面试,发现自己好多基础知识都一知半解,明明自己脑子里明白,明白这个知识点的原理,但就是说不出来,也不知道是自己表达能力的问题,还是其实自己对这些知识并没有掌握,趁每天空闲时间,好好再补下基础(闹心,话说有些知识刚学的时候不理解,但是能行记住,用过后理解了,反而记不住了).(都是看的网上资料,写的乱,仅作为个人笔记使用) Java集合类提供了一套设计良好的支持对一组对象进行操作的接口和类.Java集合类里面最基本的接口有:1.Collection:代表一组对象,每一个对象都是它的子元素.2.

Java常见面试题(二)JAVA集合类

JAVA集合类图: 1. hashmap原理,与hashtable区别 Java中的HashMap是以键值对(key-value)的形式存储元素的.HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素.当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上.如果key已经存在了,value会被更新成新值.HashMap的一些重要的特性是它的容量(capacity),负载因子(load