java几种数据结构原理

1、ArrayList

//初始化一个空数组
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
    //添加元素
    public boolean add(E e) {
    	//设置容量
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //当前数组大小+1,并设置值
        elementData[size++] = e;
        return true;
    }
    
    
    private void ensureCapacityInternal(int minCapacity) {
    	//判断数组为空设置初始化大小为 DEFAULT_CAPACITY = 10;
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //
        ensureExplicitCapacity(minCapacity);
    }
    
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
        	//真正的设置容量的方法
            grow(minCapacity);
    }
    
    private void grow(int minCapacity) {
        //判断当前数组容量,如果不够则按一定的规则设置新的长度
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //拷贝老的数组到新数组
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

可见底层实现就是数组,通过改变数组长度来实现可变数组 

2、LinkedList

//链表添加元素
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
    //链尾添加元素
    void linkLast(E e) {
    	//链表最后一个元素
        final Node<E> l = last;
        //新建一个链表元素,设置上一个元素为l,下一个元素是null
        final Node<E> newNode = new Node<>(l, e, null);
        //设置链表的最后一个元素为新建的元素
        last = newNode;
        //如果上一个元素为空则当前元素为第一个元素
        if (l == null)
            first = newNode;
        //否则设置上一个节点的下一个元素是当前元素
        else
            l.next = newNode;
        //链表大小加1
        size++;
        modCount++;
    }
    
    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;
        }
    }

底层实现就是一个双向链表结构

3、HashMap 

    public V put(K key, V value) {
    	//hash(key) 计算key的hash值
        return putVal(hash(key), key, value, false, true);
    }
    
    //根据hashCode方法计算
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    
    
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
            boolean evict) {
     //定义单向链表结构数组
	 Node<K,V>[] tab; Node<K,V> p; int n, i;
	 //如果单向链表=null则调用resize方法
	 if ((tab = table) == null || (n = tab.length) == 0)
		 //重置链表数组
	     n = (tab = resize()).length;
	 //如果在链表结构的数组上不存在当前hash值对应的值,则直接创建新的链表节点存放在(n - 1) & hash的位置
	 if ((p = tab[i = (n - 1) & hash]) == null)
	     tab[i] = newNode(hash, key, value, null);
	 //如果hash值对应的数组位置有值作如下处理
	 else {
	     Node<K,V> e; K k;
	     //判断hash值相等并且(地址相等或者equals方法相等),hash值相等并且equals比较也想等
	     if (p.hash == hash &&
	         ((k = p.key) == key || (key != null && key.equals(k))))
	         e = p;
	     else if (p instanceof TreeNode)
	         e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
	     else {
	    	 //遍历单向链表
	         for (int binCount = 0; ; ++binCount) {
	        	 //获取链表下一个元素 如果到链表末尾
	             if ((e = p.next) == null) {
	            	 //则创建新的元素追加到链表末尾
	                 p.next = newNode(hash, key, value, null);
	                 //如果binCount操作tree结构的阈值>=8-1则初始化树
	                 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
	                     treeifyBin(tab, hash);
	                 break;
	             }
	             //链表当前元素hash值和equals值相等,则直接跳出循环
	             if (e.hash == hash &&
	                 ((k = e.key) == key || (key != null && key.equals(k))))
	                 break;
	             p = e;
	         }
	     }
	     //如果在链表找到hash值和equals值相等则重新设置当前元素值
	     if (e != null) { // existing mapping for key
	         V oldValue = e.value;
	         if (!onlyIfAbsent || oldValue == null)
	             e.value = value;
	         afterNodeAccess(e);
	         return oldValue;
	     }
	 }
	 ++modCount;
	 if (++size > threshold)
	     resize();
	 afterNodeInsertion(evict);
	 return null;
	}

 底层实现是一个可变数组,每一个数组存储是一个链表结构数据,通过hash值来决定元素存放位置

4、HashSet

 public boolean add(E e) {
		 	//map的结构HashMap<E,Object>,PRESENT = new Object()
	        return map.put(e, PRESENT)==null;
	 }

 可见HashSet的实现就是Value= new Object()的HashMap

5、HashTable

	//有synchronized关键字说明是线程安全的
	public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        //通过hash值查找元素
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        //如果找到元素并遍历查找当前位置链表结构下是否存在hash值相等并且equals也想等,
        //如果找到则设置新值后返回旧值
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }
        //添加新元素
        addEntry(hash, key, value, index);
        return null;
    }
	
    private void addEntry(int hash, K key, V value, int index) {
        modCount++;

        Entry<?,?> tab[] = table;
        if (count >= threshold) {
            //重置数组,并且拷贝旧的数组到新数组
            rehash();

            tab = table;
            hash = key.hashCode();
            index = (hash & 0x7FFFFFFF) % tab.length;
        }

        
        @SuppressWarnings("unchecked")
        Entry<K,V> e = (Entry<K,V>) tab[index];
        // 创建新键值对之后在链表头添加当前元素(设置当前元素的下个节点为当前位置元素),并设置到当前位置
        tab[index] = new Entry<>(hash, key, value, e);
        count++;
    }

  

posted @ 2019-07-06 20:46  myTang  阅读(348)  评论(0)    收藏  举报