HashCode
hashcode
/*哈希值:是一个十进制的整数,由系统随机给出(就是一个对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是实际地址)
- 在object类中有一个方法,可以获得对象的哈希值
- int hashcode()返回该对象的哈希值
- hashcode方法的源码
- public native int hashcode();
- native:代表该方法调用的是本地操作系统的方法*/
新建一个对象类Person
代码:
public class Person extends Object {
}
测试类:
代码:
public class Demo01HashCode {
public static void main(String[] args) {
Person p1=new Person();
int h1=p1.hashCode();
Person p2=new Person();
int h2=p2.hashCode();
System.out.println(h1);//1163157884,重写hashcode,放回值为一;
System.out.println(h2);//1956725890,重写hashcode,放回值为一;
System.out.println(p1);//cn.itcast.API.HashCode.Person@4554617c
System.out.println(p2);//cn.itcast.API.HashCode.Person@74a14482
System.out.println(p1==p2);//false
/*String类的哈希值
* String类重写object类的hashCode方法*/
String s1=new String("abc");
String s2=new String("abc");
System.out.println(s1.hashCode());//96354
System.out.println(s2.hashCode());//96354
System.out.println("重地".hashCode());//1179395,巧合!
System.out.println("通话".hashCode());//1179395
System.out.println("你是谁:".hashCode());//631668296,一般情况!
System.out.println("为了谁:".hashCode());//617023717
HashSet<String> strings = new HashSet<>();
//set存取hashcode相同的元素
strings.add("abc");
strings.add(s1);//地址值相同,且equals相同,不存储
strings.add(s2);//地址值相同,且equals相同,不存储
strings.add("重地");//地址值相同,但equals不相同,存储
strings.add("通话");//地址值相同,但equals不相同,存储
System.out.println(strings);//[重地, 通话, abc]
}
显示效果:
1163157884
1956725890
cn.itcast.API.HashCode.Person@4554617c
cn.itcast.API.HashCode.Person@74a14482
false
96354
96354
1179395
1179395
631668296
617023717
[重地, 通话, abc]
person类中的HashCode方法重写
代码:
public class Person extends Object {
@Override
public int hashCode()
{
return 1;
}
}
测试类重写测试显示效果
1
1
cn.itcast.API.HashCode.Person@1
cn.itcast.API.HashCode.Person@1
false
96354
96354
1179395
1179395
631668296
617023717
[重地, 通话, abc]
重写HashCode后为什么P1和P2的返回值都是相同的p1 == p2还是false,因为p1 == p2比较的是两个实际地址值,而哈希值只是逻辑地址值,是模拟出来的地址
String s1=new String("abc");
String s2=new String("abc");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s1==s2);//false
list存储数据先看两个字符串的哈希值是否相同再看是否Equals(值是否相同)再进行是否存入!
关于重地和通话哈希值相同为啥能够进入到set中,我们知道set不可以存储相同元素的,哈希值相同,我们还要看元素值equals是否相等,满足这两个条件才存储进set中
LinkedHashSet
哈希表和链表实现了Set接口,具有可预测的迭代次序。 这种实现不同于HashSet,它维持于所有条目的运行双向链表
代码:
public class LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set=new HashSet<>();
set.add("www");
set.add("baidu");
set.add("www");
set.add("com");
System.out.println(set);
java.util.LinkedHashSet<String> linked=new java.util.LinkedHashSet<>();
linked.add("www");
linked.add("baidu");
linked.add("com");
linked.add("baidu");
System.out.println(linked);//按照原来的顺序,也不接受重复数据!
}
}
显示效果:
[com, www, baidu]
[www, baidu, com]
set存储对象时的应用
定义一个Student类存放对象的属性值
代码(已经重写了Equals和HashCode方法!,为了简便的观看重写了Tostring方法):
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试类
代码:
public class StudentDemoTest {
public static void main(String[] args) {
HashSet<Student> set=new HashSet<>();
Student stu1=new Student("钱学森",22);
Student stu2=new Student("钱学森",22);
Student stu3=new Student("钱伟长",22);
Student stu4=new Student("钱三强",22);
System.out.println(stu1.hashCode());
System.out.println(stu2.hashCode());//hashCode不一样,重写之后一样了!
System.out.println(stu1==stu2);//false,地址值不一样
System.out.println(stu1.equals(stu2));//false重写之后true
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set);
}
}
注意点
存储对象时,必须重写hashcode方法和equals方法!
重写tostring方法(非必须!将地址值的默认改掉!)
显示效果
1157313598
1157313598
false
true
[Student{name=‘钱三强’, age=22}, Student{name=‘钱伟长’, age=22}, Student{name=‘钱学森’, age=22}]