JDK之数据结构---集合

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK之数据结构---集合相关的知识,希望对你有一定的参考价值。

参考技术A 集合的分类
ArrayList与LinkedList区别
HashSet、TreeSet、LinkedHashSet的区别
HashMap、TreeMap、LinkedHashMap区别
HashMap、HashTable的区别
HashSet、HashMap区别
HashMap是怎么样的存储格式,怎么样扩容,怎么处理冲突
集合安全问题
1.数组与集合的区别:
数组是静态的,固定大小的,相对集合来说轻量级。而集合是可以动态扩展容量。

2.集合的分类
java中的集合框架有两个基本接口

Collection框架:List接口(ArrayList、LinkedList)、Set接口(HashSet、TreeSet、LinkedHashSet)、Queue接口(ArrayDeque一种用循环数组实现的双端队列)

Map框架(键值对存储):(HashMap、TreeMap、LinkedHashMap)

3.ArrayList与LinkedList区别
ArrayList是可改变大小的数组,动态增长的索引序列,存储空间是连续分布的,数组中任意元素的访问的时间复杂度为O(1),访问快速,但是增加删除需要移动大量元素,速度慢。

而LinkedList,高效插入和删除的有序序列,存储空间动态分配,访问链表的元素,需要从第一个到访问的那个元素,速度相对较慢,而对于增加和删除元素,只需修改元素的指针就行,相对较快。

4.HashSet、TreeSet、LinkedHashSet的区别
HashSet:是一种没有重复元素的无序集合。

TreeSet:是一种有序集合。

LinkedHashSet:使用链表维护元素的次序,通过元素的插入顺序保存的有序集合。

备注:当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。

如果两个对象通过equals方法比较返回true时,其hashCode也是相同的。反之如果hashCode相同,equals不一定相同。

5.HashMap、TreeMap、LinkedHashMap区别
HashMap:一种存储键值关联的无序散列映射表。

TreeMap:一种有序存储键值的映射表。

LinkedHashMap:一种记住键值插入次序的映射表。

6.HashMap、HashTable的区别
HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。而HashTable支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢。

HashMap最多只允许一条记录的键为Null,允许多条记录的值为 Null。而HashTable它不允许记录的键或者值为空。

7.HashSet、HashMap区别
HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key。

HashSet实现了Set接口,HashMap实现了Map接口

HashSet仅存储对象key,HashMap是对键值对的映射

HashSet实添加元素是add,HashMap添加元素用put

8.HashMap是怎么样的存储格式,怎么样扩容,怎么处理冲突?
a.键值对存储,由散列函数hashCode()为实例对象产生一个散列码hashcode,将散列码与桶的总数取余,得到索引存储在散列表hashtable中,在散列表内部,用桶来保存键值对,用链表或数组实现。

b.扩容:负载因子0.75 如果表中超过75%的位置已经填入元素,那么这个表就会用双倍的桶数进行再散列。

c.冲突处理:hashmap的冲突处理是拉链法

d.其他解决冲突处理的方法:

开放地址法:查找数组中的空位

线性探测法:查找冲突位置的下一个位置

拉链法:使用链表解决,将冲突的key放到原来的数据节点后面

9.集合安全:
a.线程安全类(Vector、HashTable)在核心方法上加了synchronized

ArrayList不支持线程同步,而Vector增加同步机制,线程安全。

HashMap不支持线程的同步,而HashTable相比较增加同步机制,线程安全。

b.Collections类:(1.5后新加)

可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,synchronizedList等方法

提供了多个静态方法,包装集合,将指定集合包装成线程同步的集合。

c.并发集合(ConcurrentHashMap):

通过复杂的策略,不仅保证了多线程的安全,也提高了并发的效率。

最核心的就是锁分段技术,不直接对整个hashmap的表锁定,由多个segment组成。

集合之LinkedList(含JDK1.8源码分析)

LinkedList的数据结构

LinkedList的增删改查

增:add

  说明:add函数用于向LinkedList中添加一个元素,并且添加到链表尾部。具体添加到尾部的逻辑是由linkLast函数完成的。

举例:

public class Test {
    public static void main(String[] args) {
        List<String> list = new LinkedList<>();
        list.add("zhangsan");
        list.add("lisi");
        list.add("wangwu");
     
list.add("zhangsan");
     System.out.println(list);
  }
}

结果:

[zhangsan, lisi, wangwu, zhangsan]

add源码分析:

/**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #addLast}.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

LinkLast方法如下:

/**
     * Links e as last element.
     */
    void linkLast(E e) {
        //将last节点保存
        final Node<E> l = last;
        //构造新节点
        final Node<E> newNode = new Node<>(l, e, null);
        //将新构造的节点赋值给last节点,便于下次添加元素时使用
        last = newNode;
        //判断保存的last节点是否为null
        if (l == null)
            //为null,首次添加,first节点与last节点一样,都是新节点
            first = newNode;
        else
            //不为null,说明list中已有元素,将newNode赋值给未添加元素e之前,list中已经存在的last节点的next属性
            l.next = newNode;
        //size加1
        size++;
        //结构性修改加1
        modCount++;
    }

图示说明添加元素后链表状态的改变:

list.add("zhangsan");

技术图片

技术图片

list.add("lisi");

技术图片

list.add("wangwu");

技术图片

由此可见,双向链表的含义即:由上一个节点的next属性可以得到下一个节点,下一个节点的prev属性可以得到上一个节点。上下两个节点之间互相指向关联。





以上是关于JDK之数据结构---集合的主要内容,如果未能解决你的问题,请参考以下文章

集合之LinkedHashSet(含JDK1.8源码分析)

集合之TreeSet(含JDK1.8源码分析)

集合之LinkedList(含JDK1.8源码分析)

集合之HashSet(含JDK1.8源码分析)

大话JDK之数据结构和算法

集合框架JDK1.8源码分析之HashMap 转载