哈希码
- 哈希值、哈希码:
hashCode()
方法返回的是一个整数值,称为哈希码 ( HashCode ),存在的主要意义是在散列表 ( Hash Table ) 等数据结构中帮助快速定位对象- 其他存在意义:
- 快速查找,散列集合 ( 散列表 ( 例如
HashMap
、HashSet
) 等集合使用哈希码来实现元素的快速检索 - 通过哈希码,可以将元素存储在合适的桶(Bucket)中,以提高查找性能 )
- 避免重复
- 哈希分布均匀性
- 自定义数据结构的实现 ( 哈希码的概念也可以用于自定义数据结构的实现,例如自定义的哈希表、缓存或索引结构,以便快速查找和访问对象 )
- 快速查找,散列集合 ( 散列表 ( 例如
- 哈希码是一个 32 位整数 ( 在 Java 中,通常是 int 类型 ),但也可以是 64 位整数 ( long 类型 )
- 哈希运算后是否需要取模取决于具体的应用场景和哈希函数的输出范围
- 在某些情况下,哈希函数的输出已经在所需范围内,不需要再进行取模操作
- 在其他情况下,取模运算可能是必要的,以确保哈希码落在合适的范围内
- 其他存在意义:
哈希表
- 哈希表 ( Hash Table ) 可以看作是一个数组,通常是一个动态数组 ( 或称为桶数组 ),每个桶 ( Bucket ) 都可以存储一个键值对 ( Key-Value Pair )。哈希表的主要思想是将键 ( Key ) 通过哈希函数 ( 即计算哈希值 ) 映射到数组的特定位置 ( 桶 ),以便快速查找和访问对应的值 ( Value )
- 散列表通常也被称为哈希表
- 数组中的每个位置通常称为一个桶,每个桶可以存储一个键值对
哈希冲突
- 当要存储一个键值对时,哈希表首先计算键的哈希码,然后根据哈希码计算出桶的索引位置。如果两个不同的键具有相同的哈希码,并且它们被映射到了相同的桶中,那么就会发生哈希冲突 ( 其解决方法: )
- 开放定址法:遇到冲突了就找个新的空闲的
- 线性探测法:加一后再取模运算 ( 单独方向的 )
- 平行探测法:特定的运算方法进行前后寻找 ( 前后两向的 )
- 再哈希法:构造多个不同的哈希函数,冲突了就用其他的函数方法
- 链地址法:哈希地址相同的都记录在同一链表中
- 建立公共溢出区:哈希表分为基本表和溢出表,冲突都放在溢出表中
- 开放定址法:遇到冲突了就找个新的空闲的
重写方法
- 重写
equals
方法的一个常见原因之一是为了在计算对象的哈希码时改变要考虑的内容。在默认情况下,hashCode
方法通常是基于对象的引用地址计算的,但如果你希望基于对象的内容来计算哈希码,就需要重写equals
和hashCode
方法- 当你重写
equals
方法以比较对象的内容时,通常需要确保hashCode
方法也被相应地重写,以便哈希表等数据结构能够正确地处理对象 hashCode
方法的主要目标是生成一个整数值,该值应该在相等的对象上产生相同的哈希码。因此,如果你改变了equals
方法中用于比较的对象内容,那么也应该相应地更改hashCode
方法,以便它考虑到这些内容的变化,以便生成相应的新的计算方式得来的哈希码
- 当你重写
桶
- 在 Java 中的
HashMap
中,桶是用于存储键值对的数据结构。每个桶实际上是一个链表或红黑树,用于解决哈希冲突,即当多个键映射到相同的哈希码时,它们可以存储在同一个桶中- 具体来说,每个桶包含一个链表或红黑树,用于存储键值对。这些键值对的键具有相同的哈希码,但它们不一定相等,因此需要在同一个桶中进行进一步的比较 ( 用 equals 方法比较键是实际内容 ) 来找到特定的键值对
- 在早期版本的
HashMap
中,使用链表来存储同一哈希码的键值对。当发生冲突时,新的键值对被简单地添加到链表的末尾。这种实现的性能在大多数情况下是良好的,但在某些情况下可能导致性能下降,特别是当链表变得很长时 - 为了解决链表变长问题,从 Java 8 开始,
HashMap
实现引入了树化 ( treeify ) 机制,将链表转化为红黑树,以提高查找性能。这意味着当一个桶中的键值对数量超过一定阈值时,链表会被转化为红黑树 - 通过桶,
HashMap
可以有效地存储和检索键值对,并提供 O(1) 时间复杂度的平均性能
静态变量与实例常量
- 总之,实例变量必须创建对象后才可以通过这个对象来使用,
静态变量则可以直接使⽤类名来引用 - 注意:实例变量的生命周期通常随着对象的生命周期而存在。只有在对象被销毁时,与之关联的实例变量才会被销毁
- 注意:垃圾回收主要负责回收不再被引用的对象,而不是变量本身,并且当没有引用指向某个对象时,它才可能被垃圾回收
- 注意:静态变量通常存储在方法区,方法区也被称为静态区或永久代,现如今的元空间所取代,在程序启动时被初始化,一直存在到程序结束运行
- 注意:元空间是 Java 虚拟机 ( JVM ) 中的一块内存区域,用于存储类的元数据信息,包括类的字节码、常量池、方法信息、静态变量、静态常量等 ( 元空间的内容存储在计算机的内存中 )
- 具体存储情况还是看 jvm 版本
字符串存储
-
在 java 8 后,常量池就是存在元空间里了,常量池又主要分为:类常量池和运行时常量池
-
类常量:存储类相关的常量信息,包括类名、父类名、接口名,类常量池中的信息用于描述类的结构和层次关系
-
运行时常量池:用于支持类的运行时操作的一部分常量池,包含运行时生成的字符串常量、字面量常量等,字符串常量池是运行时常量池的一部分,用于存储字符串字面量
- 还有其他常量类型,这些常量一起构成了 Java 字节码的基础,支持类加载、方法调用等操作
-
字面量和成员变量
- 字面量是代码中的常数值,而成员变量是类的属性,用于存储对象的状态信息。字面量是数据的具体值,而成员变量是存储数据的容器。成员变量可以在类中的方法中使用,并根据对象的状态而变化。
红黑树
- 待整理