郑州网站建设品牌好,广州建筑东莞分公司,90设计网站官网首页,农业公司注册流程及费用73、介绍下 HashMap 的底层数据结构
我们现在用的都是 JDK 1.8#xff0c;底层是由“数组链表红黑树”组成#xff0c;如下图#xff0c;而在 JDK 1.8 之前是由“数组链表”组成。 1.Hash
Hash叫做”散列表“#xff0c;就是把任意长度的输入#xff0c;通过散列算法底层是由“数组链表红黑树”组成如下图而在 JDK 1.8 之前是由“数组链表”组成。 1.Hash
Hash叫做”散列表“就是把任意长度的输入通过散列算法变成固定长度输出该输出结果是散列值。 其实这种转换是一种压缩映射散列表的空间通常小于输入的空间不同的输入可能会散列成相同的输出所以不能从散列表来唯一的确定输入值。这就出现了Hash冲突。 74、为什么要改成“数组链表红黑树”
主要是为了提升在 hash 冲突严重时链表过长的查找性能使用链表的查找性能是 O(n)而使用红黑树是 O(logn)。
75、那在什么时候用链表什么时候用红黑树
对于插入默认情况下是使用链表节点。当同一个索引位置的节点在新增后超过8个阈值8如果此时数组长度大于等于 64则会触发链表节点转红黑树节点treeifyBin而如果数组长度小于64则不会触发链表转红黑树而是会进行扩容因为此时的数据量还比较小。
对于移除当同一个索引位置的节点在移除后达到 6 个并且该索引位置的节点为红黑树节点会触发红黑树节点转链表节点untreeify。 78、HashMap 的扩容resize流程是怎么样的 77、HashMap 的插入流程是怎么样的 79、除了 HashMap还用过哪些 Map在使用时怎么选择 90、Java 内存结构运行时数据区 程序计数器线程私有。一块较小的内存空间可以看作当前线程所执行的字节码的行号指示器。如果线程正在执行的是一个Java方法这个计数器记录的是正在执行的虚拟机字节码指令的地址如果正在执行的是Native方法这个计数器值则为空。
Java虚拟机栈线程私有。它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
本地方法栈线程私有。本地方法栈与虚拟机栈所发挥的作用是非常相似的它们之间的区别不过是虚拟机栈为虚拟机执行Java方法也就是字节码服务而本地方法栈则为虚拟机使用到的Native方法服务。
Java堆线程共享。对大多数应用来说Java堆是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例几乎所有的对象实例都在这里分配内存。
方法区与Java堆一样是各个线程共享的内存区域它用于存储已被虚拟机加载的类信息构造方法、接口定义、常量、静态变量、即时编译器编译后的代码字节码等数据。方法区是JVM规范中定义的一个概念具体放在哪里不同的实现可以放在不同的地方。
运行时常量池运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外还有一项信息是常量池用于存放编译期生成的各种字面量和符号引用这部分内容将在类加载后进入方法区的运行时常量池中存放。
String str new String(hello); 上面的语句中变量 str 放在栈上用 new 创建出来的字符串对象放在堆上而hello这个字面量是放在堆中。
93、类加载的过程 类加载的过程包括加载、验证、准备、解析、初始化其中验证、准备、解析统称为连接。
加载通过一个类的全限定名来获取定义此类的二进制字节流在内存中生成一个代表这个类的java.lang.Class对象。
验证确保Class文件的字节流中包含的信息符合当前虚拟机的要求并且不会危害虚拟机自身的安全。
准备为静态变量分配内存并设置静态变量初始值这里所说的初始值“通常情况”下是数据类型的零值。
解析将常量池内的符号引用替换为直接引用。
初始化到了初始化阶段才真正开始执行类中定义的 Java 初始化程序代码。主要是静态变量赋值动作和静态语句块static{}中的语句。 String,StringBuffer,StringBuilder区别 问题提出 StringBuffer的源代码中将其定义为final类型为什么StringBuffer的值仍可改变 public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, ComparableStringBuffer, CharSequence 问题解决 **
final修饰的成员变量为基本数据类型时赋值后无法改变。 当final修饰的为引用变量时在赋值后其指向地址无法改变但对象内容可以改变。** 在使用 StringBuffer 类时每次都会对 StringBuffer 对象本身进行操作而不是生成新的对象所以如果需要对字符串进行修改推荐使用 StringBuffer。
StringBuilder 类在 Java 5 中被提出它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的不能同步访问。
由于 StringBuilder 相较于 StringBuffer 有速度优势所以多数情况下建议使用 StringBuilder 类。