2021-10-18 Java学习(集合)

HashMap的底层实现原理?

以jdk7为例进行说明。

HashMap map=new HashMap()
在实例化之后,底层创建了长度是16的一维数组Entry[] table

…执行过多次put

map.put(key1,value1):
首先,调用hashCode()计算key1哈希值,此哈希值经过某种算法计算后,得到在Entry数组中的存放位置。
如果此位置上的数据为空,此时的key1-value1添加成功。如果此位置上的数据不为空,意味着此位置上存在一个或多个数据(以链表形式存在),比较key1和已经存在的一个或多个数据的哈希值:
如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。
如果key1的哈希值和已经存在的某一个数据的哈希值相同(hash碰撞),继续比较:调用key1所在类的equals方法,如果true,实用value1替换value2
false 则添加成功

不断添加的过程中会遇到扩容问题:默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。

jdk8的不同:

  1. new HashMap() 底层没有创建一个长度16的数组
  2. jdk8底层的数组是Node[],不是Entry[]
  3. 首次调用put()方法时,底层创建长度为16的数组
  4. jdk7的底层结构只有:数组+链表。jdk8中的底层结构:数组+链表+红黑树
    党数组的某一个索引位置上的元素以链表形式存在的数据个数>8,且当前的数组长度大于64时,此时此索引位置上的所有数据改为使用红黑树存储

HashMap的存储结构(jdk1.8前)

hashmap数组扩容后最消耗性能的点: 原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize

什么时候扩容?
当hashmap中的元素个数超过数组大小loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75
默认情况下,数组大小为16,那么当hashmap中元素个数超过16
0.75=12(代码中的threshold值,也叫做临界值)的时候,就把数组的大小扩展为2*16=32,扩大一倍,然后重新计算每个元素在数组中的位置,而这时一个飞航消耗性能的操作。所以如果我们已经阈值hashmap中元素的个数,那么预设元素的个数能够有效地提高hashmap的性能。

HashMap的存储结构 JDK1.8

内部存储结构变成了 数组+链表+树的结合。当实例化一个hashmap时,系统会创建一个长度为initialCapacity的Node数组,这个长度在哈希表中被称为容量(Capacity),在这个数组中可以存放元素的位置我们称之为“桶”(bucket),每个bucket都有自己的索引,系统可以根据索引快速查找bucket中的元素。

一个桶中:Node链/TreeNode对象。新元素作为链表last(尾插?),树的叶子。

扩容和树形化:
当hashmap中的其中一个链的对象个数达到8个,此时如果capacity没有达到64,那么hashmap会先扩容解决。如果已经达到64,那么这个链会变成树,结点类型由Node类型变为TreeNode类型。
如果当映射关系被移除后,下次resize方法时判断树的结点个数小于6个,也会把树再转为链表。

Properties

操作配置文件

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest {

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

    public static void main(String[] args) {
        FileInputStream fis=null;
        try {
            Properties pros=new Properties();
            fis=new FileInputStream("jdbc.properties");
            pros.load(fis);//加载流对应文件

            String name=pros.getProperty("name");
            String password=pros.getProperty("password");
            System.out.println("name="+name+",password="+password);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis!=null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值