Object类
1学习类的方法:
1.1toString()什么时候执行此方法
//在输出对象的时候使用toString()方法;
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo1 {
public static void main(String[] args) {
Person person = new Person("张三",21);
System.out.println(person);
}
}
1.2equals()比较的是什么,
//在Object类中比的是内存地址
public boolean equals(Object obj) {
return (this == obj);
}
:在子类中可以重写equals方法,String的equals方法比较的是内容
public boolean equals(Object anObject) {
if (this == anObject) {//先比较地址
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
定义一个重写的equals方法:(需要定义hashCode方法)
class Person1{
String name;
int age;
public Person1() {
}
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
// public boolean equals(Object o) {
// if (this == o) return true;
// if (o == null || getClass() != o.getClass()) return false;
// Person1 person1 = (Person1) o;
// return age == person1.age && Objects.equals(name, person1.name);
// }
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof Person1){
Person1 person1 = (Person1) o;
return age == person1.age && Objects.equals(name, person1.name);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class Demo2 {
public static void main(String[] args) {
Person1 person1 = new Person1();
Person1 person11 = new Person1();
System.out.println(person1.equals(person11));
}
}
1.3HashCode()
哈希值的产生:
hashCode的总合同是:
只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数,前提是修改了对象中equals比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。
如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
不要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。
String:如果内存地址不一样那么哈希值一定不一样。
在String类中重写了HashCode方法。
注意;重写equals方法必须重写hashcode方法。
:两个对象的哈希值一样,对象不一定一样。但如果对象相等,那么哈希值一定相等(Object定义合同)。
public class Demo4 {
public static void main(String[] args) {
String str = "aaa";
String str1 = new String("aaa");
String str2 = new String("bbb");
System.out.println(str.hashCode());//96321
System.out.println(str1.hashCode());//96321
System.out.println(str2.hashCode());//97314
}
}
2.Set集合(无序,不可重复的)
使用:
set的引用指向子类对象。
hashSet:
依靠哈希值进行存储,如果两个元素hash值一样的话,就不再存储。
treeSet:
底层是二叉树。存储时需要进行一次排序。
2.1hashSet:
底层实现是什么:
HashSet 的实现是依赖于 HashMap 的,HashSet 的值都是存储在 HashMap 中的。
在 HashSet 的构造法中会初始化一个 HashMap 对象,HashSet 不允许值重复。
因此,HashSet 的值是作为 HashMap 的 key 存储在 HashMap 中的,当存储的值已经存在时返回
false。
:存入对象时,内容相同存入hashSet时不会被覆盖。
要想存储的对象值相同时不会被存进去的话,重写equals方法后再重写hashCode方法之后才可以。
//hashSet集合存对象
class Cat{
String name;
int age;
public Cat() {
}
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo6 {
public static void main(String[] args) {
Set<Cat> set = new HashSet<>();
Cat cat = new Cat("小白",3);
Cat cat1 = new Cat("小白",3);
Cat cat2 = new Cat("小白",3);
set.add(cat);
set.add(cat1);
set.add(cat2);
System.out.println(set);
}
}//控制台打印的是
//[Cat{name='小白', age=3}, Cat{name='小白', age=3}, Cat{name='小白', age=3}]
若想满足Set集合相同的数据存不进去就需要重写equals和HashCode方法
//在Cat实体类中重写equals和HashCode方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cat cat = (Cat) o;
return age == cat.age && Objects.equals(name, cat.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//之后输出的set结果是:[Cat{name='小白', age=3}]
2.2TreeSet
也是实现了Set集合,可以保证数据 唯一性,存储也是无序的
TreeSet存对象的话实体类需要实现Comparable接口
int | compareTo(T o) |
---|---|
将此对象与指定对象进行比较以进行排序。 |
将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。
stu1.comparetTo(stu2)
得有一个int类数据
好好思考一个问题:你得给我返回一个int类型的数据
stu1有age变量 stu1的年龄 减去 stu2的年领
如果年龄返回值是一个负数的话: stu1的年领小与 stu 2
如果年龄返回值是一个0的话,stu1的年龄和stu2年龄相等
如果年龄返回值是一个正整数的话: stu1的年领大于 stu 2
stu1 45,stu2 35,stu3 25
set.add(stu1); 第一次调用compareTo
stu1和stu1在比较 45-45 =0 只保留 stu1
set.add(stu2)的时候
又调用compareTo() 第二次调用compareTo
o:stu1
this: stu2 35 - 45 = -10 负数 stu2 比stu1小 咋排 [stu2, stu1]
set.add(stu3)的时候 第三次调用compareTo
this: stu3
o: stu1
[stu3, stu1]
第四次调用compareTo
this:stu3
o:stu2 [stu3 stu2]
[stu3 stu2 stu1]
2.3面试问题
1、HashSet 和 TreeSet 有什么区别?
HashSet 是由一个 hash 表来实现的,因此,它的元素是无序的。add(),remove(),contains()
方法的时间复杂度是 O(1)。TreeSet 是由一个树形的结构来实现的,它里面的元素是有序的。因
此,add(),remove(),contains()方法的时间复杂度是 O(logn)。
2.为什么重写 equals 时必须重写 hashCode 方法?
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码 的作用是确定该对象在哈希表中的索引位置。如果两个对象相等,则 hashcode 一定也是相同的 如果两个对象相等,对两个对象分别调用 equals 方法都返回 true 如果两个对象有相同的 hashcode 值,它们也不一定是相等的因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆 盖。hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据).