探讨java中的集合


集合所属的类在java.util包下

集合可分为两种collection单列存储,map双列集合

一、collection(单列集合)

list:存储有序的、数据可重复

ArrayList、LinkedList、Vector三种实现类
ArraryList:LIst的主要实现类,线程不安全、效率高底层使用Object[ ]存储,在JDK7中初始创建时长度为10,在JDK8开始创建时先初始化为DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};;第一次创建时才是长度为10,扩容是1.5倍

初始化在这里插入图片描述

创建在这里插入图片描述
扩容
在这里插入图片描述

LinkedList:底层用双向链表存储,插入、删除效率高
Vctor:线程安全、效率低,底层同用Object[ ]存储,每次扩容为原来的2倍(现在很少采用)
  • set:存储无序的、不可重复的数据,没有额外定义的新方法,只用collection中的方法

  • HashSet:存储无序的,不可重复的数据,作为set的主要实现类,线程不安全,可以存储null值,JDK7底层数组+链表实现,数组初始长度为16,同一位置链表插入使用头插法,JDK8使用数组+链表+红黑树实现,添加时指定长度为16;同一位置链表使用尾插法

    • 向HashSet添加元素a,首先调用元素a所在的类的HashCode方法,计算a的哈希值,此哈希值接着通过某种计算方法,计算出HashSet底层数组的存放位置(即索引位置),判断此位置上是否有元素,如果没有元素,直接放入,如果有元素进行比较,先用哈希值比较, 如果哈希值不同放入后面(采用JDK8尾插说法),如果哈希值相同,在调用equals()方法比较,返回true添加失败,返回false,可以放入,在此位置中已经有元素的时候用链表串起来放在数组的一个位置
    • 基于以上的只是,我们可以知道在向set中添加数据时,所在的类一定要重写HashCode(),equals()方法,重写这两个方法尽可能保持一致性,相等的对象必须具有相等的散列码
    • 重写技巧,对象中用作比较的属性,都应用来计算hashcode值(快捷键生成)
  • LinkedHashSet:作为HashSet的子类,遍历内部数据时,可以按照添加的顺序遍历(双向链表,再添加时维护了两个引用,记录此数据的前一个和后一个)

  • TreeSet:(放入类型相同的数据)可以按照添加的对象的指定属性,进行排序(自然排序是实现Comparable接口,定制排序实现comparator接口用重写compare()方法定制排序方式即规定用什么排序,但是内部还是调用compareTo(放入参数)比较)

注意:

1.无序性不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数组的哈希值存储

2.不可重复性:保证添加的元素按照equals(),判断时不是返回true,即同一个元素只能添加一个

3.对于频繁遍历操作LinkedHashSet效率高于HashSet


二、Map双列集合

map:双列集合,存储用<key,value>的键值对数据。

HashMap:Map主要实现类,线程不安全,效率高,可存储null值得key和value

LinkedHashMap:保证遍历map元素时,可以按添加顺序遍历(添加了一堆指针维护)(对于频繁遍历操作,此类效率高于HashMap)在JDK7以前底层是数组+链表实现,JDK8采用数组+链表+红黑树存储

TreeMap:保证按照key-value对进行排序,是先排序遍历,底层采用红黑树

HashTable:作为古老实现类,线程安全,,效率低,不能存储null得key和value

Properties:常用来处理配置文件,key和value都是String类型

Map的结构

  • Map的key:无序的、不可重复的,使用set存key(所在类重写equals()、hashcode()方法)
  • Map的value:无序的、可重复的,使用collection存储value
  • 一个键值对:key-value构成了一个Entry对象
  • Map的entry:无序的、不可重复的,使用set存储

经典面试题

HashMap底层实现原理

先以JDK7为例说明

  • HashMap map = new HashMap();在实例化以后,底层创建了一个长度为16的一维数组Entry[ ] table
  • map.put(key,value):先调用key所在类的hashcode()计算key的哈希值,此哈希值经过某种算法运算后,得到在Entry中的存放位置
    • 如果此为位置上数据为空,(key,value)添加成功;
    • 如果此位置的数据不为空,意味着这个位置已经存在了一个/多个数据(链表形式),比较key和已经存在的一个或多个数据的哈希值,
      • 如果key与已存在的所有数据都不同,则添加成功
      • 如果key的哈希值与某个Entry相同,继续比较,调用key所在的equals()方法
        • 如果为false,添加成功
        • 如果true,使用value替代之前Entry中的value

添加过程中,涉及到扩容,默认以2倍扩容复制到原有数组

JDK8相较于JDK7的不同方面

  • new HashMap():底层没有创建长度为16的数组,
  • JDK8底层数组是Node[ ],而不是Entry[ ],
  • 首次调用put(),方法,底层创建一个长度为16的数组
  • JDK7 底层结构:数组+链表,JDK8底层:数组+链表+红黑树,当数组的某个索引位置上的元素以链表的形式存在的的数据个数>8并且当前数组的长度>64时,此时索引位置上的所有数据改用红黑树存储

HashMap和Hashtable的异同

  • 相同点,都作为Map的实现类,双列存储<key,value> 都要求key唯一
  • 不同点 HashMap线程不安全,效率高,可以存储null值作为key和value, Hashtable线程安全,效率低,不能存储null值作为key或value

总结

抓住主要的,对于集合这一块可以进行对比记忆,多看看底层源码,加深记忆,不知道为什么这目录只生成这么多,还改了一下还是不行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值