【重难点】【Java基础 02】Arrays.sort() 、创建对象的 5 种方式、hashCode() 的作用、解决哈希冲突的方法
文章目录
一、Arrays.sort()
1.探究
进入 Arrays.sort() 源码
以 int 型为例
public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
Arrays 的排序是使用了 DualPivotQuicksort(双基准快速排序)的一个静态方法
作者把双基准快速排序封装成了一个类,方便其他类直接调用
所以要了解 Arrays.sort() 的原理,就是了解 DualPivotQuicksort 的原理
进到 DualPivotQuicksort 的源码里看,发现里面有很多排序算法,对于不同的情形会通过较为复杂的逻辑进行判断并选择最优的方案
- 优化后的归并排序(Timsort)
- 插入排序,成对插入排序
- 单基准快速排序,双基准快速排序
- 计数排序
大纲,最下面的参考链接里有一个博主进行了源码注释的翻译和解读,太长了我就不贴在这里了
校招面试我认为理解到这里就够了,这只是目前我对自己的要求,贪多嚼不烂。下面链接里有博主对 DualPivotQuicksort 进行了非常详细的解读,看了相信一定会有收获的
二、创建对象的 5 种方式
1.创建方法
1、使用 new 关键字
这是最常见也最简单的创建对象的方式,通过这种方式,我们可以调用一个类的任意构造函数
Employee emp1 = new Employee();
2、使用Class类的newInstance方法
也可以使用 Class 类的 newInstance 方法创建对象,只能调用无参构造
//无参构造
Class<?> aClass = Class.forName("类的完整路径地址");
Person person = (Person)aClass.newInstance();
3、使用Construtor类的newInstance方法
和 Class 类的 newInstance 方法很像,java.lang.reflect.Constructor 类里也有一个 newInstance 方法可以创建对象,可以调用有参构造
//有参构造
Class<?> aClass = Class.forName("类的完整路径地址");
Constructor<?> construtor = aClass.getConstructor(Integer.class,String.class);
Peoson person = (Person)constructor.newInstance(10,"sisyphus");
2 和 3 两种 new Instance 方法就是反射机制,事实上 Class 的 newInstance 方法内部就是调用了 Constructor 的 newInstance 方法
4、使用 clone 方法
当调用一个对象的 clone 方法时,JVM 会创建一个新的对象,将前面对象的内容全部拷贝进去,用此方法不会调用任何构造函数
//使用 clone 方法前我们要先实现 Cloneable 接口,并实现 clone 方法
Person demo2 = (Person)demo1.clone();
5、使用反序列化
当序列化和反序列化一个对象时,JVM 会创建一个单独的对象,用此方法也不会调用任何构造函数
//需要先实现 Serializable 接口
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Person person = (Person)in.readObject();
下面的链接中有完整测试案例
三、hashCode() 的作用
1.分析
hashcode 方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常规协定是:
在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果
以下情况不是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码
如果 hashCode() 返回常量 1 会有什么影响
重点关注一下 ”常量“,也就是说每次使用 hashCode() 这个方法时,返回的都是相同数值
其次,Java中 的 hashCode 方法就是根据对象相关的信息(比如对象的存储地址,对象的字段等)进行计算的。也就是说如果没有重写 hashCode 方法,那么它返回的的可能就是对象的存储地址,但是大多数情况不是直接返回存储地址,这取决于 JVM 的版本,只能说有一定关联,比如说 HotSpot(一种对 JVM 的实现) 就不是
hashCode() 这个方法是比较对象是否相同的一个依据,当 hashCode() 返回的都是相同数值时,所有对象都会出现 hash 冲突
四、解决哈希冲突的方法
1.介绍
1、拉链法
将哈希地址相同的记录链接在同一链表中,比如 Java 中的 HashMap 就是如此解决哈希冲突的
2、开放地址法
重新找哈希表的其他位置存放
3、再哈希法
使用另一个哈希函数计算哈希码值,直到冲突不再发生位置,设计的函数越好越多发生冲突的概率就越小,但是不可能百分百解决
4、建立公共溢出区
将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表
参考链接
建议结合下面的链接理解
DualPivotQuicksort源码解读(附图解)——java学习总结(8)
Java的Arrays.sort()方法到底用的什么排序算法
Java中创建对象的5种方式
第十七章 反射、注解与Spring事务底层原理
解决哈希冲突的三种方法(拉链法、开放地址法、再哈希法)
Hash算法解决冲突的四种方法
HashMap解决冲突的四种方法
开放地址法