JAVA数据结构(六)_集合类_Map

List重复的定义是equels

二叉树是大小

 1 MAP

1.1 特点

        1.Map接口是Map集合体系的顶级接口

        2.Map储存的数据是K-V数据,(K-v数据具有自我描述性)

        3.Map的有些子实现K是有序的,有些K是无序的(Hash无序tree有序)

        4.Map不允许存储重复的元素(注意:重复的定义)是key

        5.Map的有些子实现允许存储null,有些不允许(    )

注:有序,null,重复等都是指key,我们不关心value

 API

        V put(k,v):添加

        void putAll():添加所有

        v remove(key):根据key删除这个键值对

        v get(objec):根据key获取value

        boolean containsValue()

        boolean containsKey()

视图方法

        Set<k> keySet():返回K的集合

        Collection<V>  values():返回value集合

        set<Map.Entry<K,V>>,entrySet()>:返回键值对集合

2 HashMap

结构:数组+链表+红黑树

key经过计算得到位置,然后比对key的值,一样就替换,不一样就链上

2.1特点

        1.HashMap是Map接口的一个具体子实现

        2.HashMap它的结构是数组+链表+红黑树

        3.数组默认的初始化容量16,扩容机制扩为原来的二倍,默认加载因子:0.75

        4.存储的数据是无序的(通过key计算出的数组下标是不确定的)

        5.允许存储null键与null值

        6.不允许存储重复的key值

        7.线程不安全

8.加载因子是控制该HashMap扩容的阈值,

        存储元素数量>加载因子*数组长度

        eg:数组长度16,加载因子:0.75,只能存储12个元素(指的是12个entry数量而不是12个下标位置)

9.如果我们给定HashMap一个初始 长度,--构造器赋值(与deque不同先减一了,所以是得到是大于等于给定值的最小的2次幂)

 如图:每次初始化都是n的右移,也就是给定值的最小二次幂;

10.key-value数据是如何存储的?

        把key取出,根据k计算hash值:

        根据hash值(这里做一个新旧值的异或操作)与数组长度取模,得到下标

        如果下标位置没用存储任何元素,那么就将kv数据创建一个节点(hash,K,V,next)进行存储

               如果经过计算的下标位置没又任何元素,那么就new一个节点

                如果这个位置已经存储了元素,先判断(先hash再equals)key是否重复

                如果这时候是一样的key就替换值如果不一样:

                 1.此时是链表:(并且不满足树化操作)此时一个一个对象比较,1.8之后是尾插用next指向

                2.此时是红黑树,肮脏红黑树的compareTo方法插入(红黑树插入5种情况)

                3.链表大于8达到9后会进行树化操作(此时也应该满足数组长度大于64,否则会先扩增数组,扩增数组之后数组长度的变化会导致hash值计算得出的最后角标为x与x+旧length)

11.hash值的计算

        Hash = (h=key.hashCode())^(h>>>16)

        移动16位的原因:我们希望这个hash算法能够尽可能的充分散列,因此,让hashcode的高位也参与到运算之中,下标的位置将取决于低位+高位+数组长度;

12.HashMap中key值重复的依据与条件是:

哈希值没重写的时候看地址值,重写看key值

 13.如果新储存的KV储存已经存在或者重复,那么新的V回覆盖旧的V,旧的value值会作为返回值返回;

经过计算得到(Key-->hash(先异或)-->再取模(位与)得到下标),此时到一个下标上,就回计算

key的hash值是否一样,在hash一样的基础上,key是否相等,相equals;

 

 这个哈希值首先进行右移16位再与旧值进行异或操作,保留高位与地位的信息,减少碰撞

key的哈希值与length长度-1的值做与运算(和对长度取模是一样的),找到角标(位运算取模速度更快)

14.如果一份kv值依据存储在hashmap中,尽量不通过引用修改这个kv值,因为有可能再也访问不到了。(因为角标是根据k计算得出的)

在重写hashcore的之后zs1与zs2 equals了,就变成相同元素

,只会存储一个;zs1的key,与zs2的值(第二次添加覆盖了zs1);

不推荐这种做法,

因为此时通过key(aaa与18)值计算出的位置,在经过equals之后不会等于原来(zs,18)的值,就删不掉了,而就算通过zs18找到这个位置,在equals过后也会发现不匹配 无法删除

注:上图是否重新散列,因为数组长度变化了,进行取模(也就是位与操作的时候得到的高位值可能会变化,如果是1就会到x+lenth的位置上去)

添加过程: 哈希值移动16位(>>>16)异或旧值,之后取模数组长度(这也是为什么扩容为两倍的原因,以为取模是用位运算的方式得到的,这样算出的更快)得到下标;

在扩容之后,根据哈希值的高位来决定在原来的位置还是在原来位置+旧的长度;

( 依然>>>16异或之后取模(位与),此时决定位的只有高位的值 )

--

 15,在数据的不断存储过程之中,有可能导致key经过计算之后得到同一个下标而这些key不重复,也就是意味着这些kv都会存储到这个位置,这会导致数组链表的产生,如果链表过长(效率降低的时候)需要转化为红黑树

链表多长转化为红黑树链表长度超过8达到9的时候

(这是因为泊松分布,在8之前链表的效率是优于红黑树的)

1.有重复位置的元素,p不为null,继续往下,先判断如果这个节点是树节点,按照树结构查找,否则按照链表方式查找

链表方式

 

泊松分布,当长度超过8的时候链表的查找效率此时低于红黑树,所以转化为红黑树

16.当链表长度大于8达到9的时候:

此时如果底层数组长度小于64会先扩容而非转化为红黑树(扩容也会重新分布,参考下文扩容的时候高位决定了新的位置)

 17.如果数组扩容,那么一个原本在x位置的元素要重新散列,就两个位置可以选择,x,以及旧长度+x位置,取决于高位(是根据hash值重新算)

18.红黑树转化为链表:

        1.当不断删除的元素(并且删除的是红黑树上的元素->导致红黑树上的节点变少->转回链表

        2.扩容(扩容->一个红河偶数,拆分成两部分->有可能需要转化回链表;)

            删除:判断红黑树的根节点,以及跟节点的左节点,右节点,以及左节点的左节点,如果这四个节点有任意一个是null,那么就会由红黑树转化为链表()

        扩容:当紧邻的高位为0

        

         此时就会还在原来的位置

        扩容的时候红黑树散列无论是新位置还是旧位置,只要散列的节点数是小于等于6的,那么就要留红黑树转化为链表

(在红黑树上用hash值比较大小) 

思考:扩容的时候会重新散列//红黑树的遍历依靠next//删除过程(找到值,替换为左树最大和右树最小)//

为什么是6,如果是7刚转化为链表,此时添加之后又反复转化形态;用6概率相对降低

2.2 总结一个kv添加的过程

以上

树的扩容:散列之后数组长度是2的幂值,只取决于高位的值

2.3构造方法

 Hash算法不是加密算法

加密--->(x)解密  加密是为了解密,而Hash为了散列

MD4、MD5、SHA-1、SHA-2

3.LinkedHashMap

3.1特点

1.LinkedHashMap是HashMap的子类

2.LinkedHashMap它的底层结构复用了HashMap的底层而机构

        它的特点基本上于HashMap一致

3.LinkedHashMap在HashMap基础上额外维护了一个双向链表,以保证迭代顺序

:尾元素双向指向下一个元素

4.HashMap是有序的(HashMap按下标进行遍历,Linked按链表顺序)

同样不允许key重复

3.2

4.TreeMap

        1.TreeMap是map接口的子实现

        2.TreeMap是一个黑红树

        3.TreeMap存储元素大小有序(key)

        4.TreeMap不允许存储重复的key值(红黑树,大小相关compareTo)所以填入的值一定是可以进行比较的;

        5.TreeMap的key不允许是null(null不能比较因为)

        6.TreeMap是线程不安全的

注意:与hashmap一致,如果数据已经存储通过类的点修改属性,可能会导致这个节点找不到无法删除

注意使用的类要实现排序方法

 API(TreeMap)

        boolean containskey//value

        Map.Entry ceilingEntry 返回大于等于给定key的最小的键值对

        Map.Entry floorKey:返回小于等于给定key的KV

        Map.Entry firstEntry:获得最小键值对        K firstKey():获得最小的key

         K firstKey():获得最大的

         Map.Entry higherEntry:大于给定key的

(对所有给定的key值的大于或者严格大于,小于或者严格小于的值的查找,删除)

        map的切割

        headMap(头切到x)       //          subMap        //        tailMap(从x切割到尾部)

5.Hashtable

        5.1.1Hashtable是Map子实现(Map是1.2 Hashtable是1.0出现了))

        2.Hashtable底层是数组+链表(没有红黑树结构)

        3.数组默认初始容量(11)与扩容机制(扩容为原来的2倍加一)

        4.不允许存储null值,null值

(HashMap是可以的并且null值为0,排在第一个,Hashtable是)HashMap在put的时候会调用hash()方法来计算key的hashcode值而Hashtable执行int  hash = key.hashCode()会空指针

         5.计算hash值的方式key.hashcode(直接计算和取模,没有位运算))

        6.线程安全

5.2Properties

(Hashtable的子类)

Xml

Properties

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值