Java学习day15:Object类、set集合(知识点+例题详解)

声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)


往期回顾 

Java学习day14:权限修饰符,集合(知识点+例题详解)-CSDN博客

Java学习day13:泛型(一篇文章搞懂)-CSDN博客

Java学习day12:static关键字,字符串声明,字符串常量池-CSDN博客

 Java学习day15:Object类、set集合

一、Object类

Object类是Java中所有类的基类,学习Object类实际上就是在学习他下面的方法。

Object类有构造方法Object(),所以是可以直接实例化的。

1.1三个方法

1.1.1 public String toString()

返回的是对象的字符串表示形式

该toString类方法Object返回一个由其中的对象是一个实例,该符号字符的类的名称的字符串`@` ”和对象的哈希码(内存地址)的无符号的十六进制表示。

念起来很绕口,这句话的意思是“当你在一个对象上调用toString方法时,它会返回一个字符串,返回的字符串通常以@开始,后面跟着对象的类名。除了类名之外,还会包含对象的哈希码的无符号十六进制表示。


例如,如果有一个字符串对象,它的toString方法可能会返回类似于"java.lang.String@15db9742"的字符串。这里的"java.lang.String@15db9742"表示这个字符串对象是属于java.lang.String类,而后面的15db9742是该对象的哈希码的无符号十六进制表示。”


换句话说,这个方法返回一个等于下列值的字符串:
getClass().getName() + '@' + Integer.toHexString(hashCode()) 
说白了就是返回类名+@+对象16进制的内存地址

 示例:

 package org.example;

import java.util.*;

class  Person{
     String name;
     int age;

}

public class Main {

    public static void main(String[] args) {

        Object obj=new Object();

        Person person=new Person();

        System.out.println(person);

    }

控制台输出:
org.example.Person@7ef20235 

 toString()这个方法是打印对象时自动调用的,正常情况下会给出类名+@+对象16进制的内存地址为了结果让人容易阅读,建议所有的子类都覆盖并重写此方法。

示例:

class Person {
    String name;
    int age;
    //person类是Object类子类不? 是!!!


    //
    @Override
    public String toString() {
        System.out.println("123");
        return
                "name=\"" + name + '\"' +
                ", age=" + age
                ;
    }
}
public class Demo1 {
    public static void main(String[] args) {
        Object obj = new Object();
        Person person = new Person();
        System.out.println(person);

    }
}

结果是name=" " ,age=  ; 

不知道大家是否看得懂重写的toString方法?如果看不懂多看几遍 ,其实就是个转义字符。

1.1.2 boolean eaqual(Object obj)

指示一些其他对象是否等于此。

public boolean equals(Object obj) {
     return (this == obj);
 }

Object 类下面的方法比较是两个对象的地址。不看内容的

可能有人会问:为啥String类下面的equals方法比较的是内容呢?String类继承了Object的equals方法时重写了Object类下面的。为啥重写?当父类的需求,满足不了子类的需求的时候要重写父类的方法

 因为实际开发中比较内容的时候很多,如果要比较两个对象的内容是否一样? 如果两个对象的内容一样返回一个true。反之返回false,看一下重写的方法是怎么写的。

import java.util.Objects;

class Student {
    String name;
    int age;

    public Student(String name, int age) {

        this.name = name;
        this.age = age;
    }
    //重写equlas,要求去比较内容,如果内容一样的额话,返回true


    //stu1.equals(stu2)
    //stu2赋值给了 o  向上转型 Object o =new Student();
    @Override
    public boolean equals(Object o) {
        if (this == o) {//比较是地址
            return true;
        }
        //如果地址不一样的话,再去比较内容,如果内容一样也返回true
        if (o instanceof Student) {
            //才去比较值 name  age
            Student stu = (Student)o;//向下转型
            //stu1.equals(stu2)  stu就是stu2  this 是stu1
            return stu.age == this.age && stu.name.equals(this.name);

        }
        return false;
    }

}
public class Demo2 {
    public static void main(String[] args) {
        Student stu1 = new Student("老邢", 89);
        Student stu2 = new Student("老邢", 89);
        //stu1是Object类子类,用的是object 类面的equals方法
        //Object类下面的equals方法比较是 地址  this==obj
        //System.out.println(stu1.equals(stu2));//false
        //现在我的需求是当两个对象的内容一致的时候返回的额是true
        //内容不一样的时候,返回是false
        //就意味着Object类的equals方法已经满足不了Student类的需求了
        //咋解决? 重写equals方法
        System.out.println(stu1.equals(stu2));//true
    }
}

代码注释很详细,大家多看多写,一定要自己写。 

这是自己重写的equals方法,可以看到逻辑上是先比较地址,地址一样的情况下直接就返回true,地址不一样再比较内容,用了一个instanceof,先保证比较的两个对象是一个类的有着相同的成员属性可以比较,再向下转型比较内容。 

而在实际开发中是不会主动去重写的,因为可以直接idea生成,看看idea自动生成的。快捷键alt+insert

import java.util.Objects;

class Student1 {
    String name;
    int age;

    public Student1(String name, int age) {

        this.name = name;
        this.age = age;
    }
    //重写equlas,要求去比较内容,如果内容一样的额话,返回true


    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()){
            return false;
        }
        Student1 student1 = (Student1) o;
        return age == student1.age && Objects.equals(name, student1.name);
    }


}
public class Demo3 {
    public static void main(String[] args) {
        Student1 stu1 = new Student1("老邢", 89);
        Student1 stu2 = new Student1("老邢", 89);
        //stu1是Object类子类,用的是object 类面的equals方法
        //Object类下面的equals方法比较是 地址  this==obj
        //System.out.println(stu1.equals(stu2));//false
        //现在我的需求是当两个对象的内容一致的时候返回的额是true
        //内容不一样的时候,返回是false
        //就意味着Object类的equals方法已经满足不了Student1类的需求了
        //咋解决? 重写equals方法
        System.out.println(stu1.equals(stu2));//true
    }
}

大家可以对比一下,看看自己重写的和idea快捷键生成的区别所在。

1.1.3 int hashCode();

看这个方法之前先了解一个知识点:哈希码值

哈希码值:在Object类下面,将内存地址(十六进制的值)转为十进制的值,此时这个十进制的值就叫hash码。也就是hashcode方法的返回值,hash码。

对于Object类来说,对象不同,内存地址必然不可能相同,对应的hash值也就不可能相同

虽然但是,我们来看看下面这段代码

class Cat {}
public class Demo4 {
    public static void main(String[] args) {
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();
        System.out.println(cat1.hashCode());
        System.out.println(cat2.hashCode());
        String str = new String("a");
        String str1 = new String("b");
        String str2 = new String("a");
        System.out.println(str.hashCode());//97
        System.out.println(str1.hashCode());//98
        System.out.println(str2.hashCode());//97
    }

}

        //现在很尴尬的一个点,Object类的hash值是内存地址十进制的转换
        //只要你内存地址不一样,hash值一定不一样
        //但是你看看str和str2 ,内存地址不一样,但是
        //hash值是一样的?

        咋回事?因为在String类中重写了hashCode方法 

而基本上我们自定义类的时候,也都需要重写hashCode方法。

 注意事项

1.只要在执行Java应用程序时多次在同一个对象上调用该方法, `hashCode`方法必须始终返回相同的整数,前提是修改了对象中`equals`比较中的信息。 该整数不需要从一个应用程序的执行到相同应用程序的另一个执行保持一致。
2.如果根据`equals(Object)`方法,两个对象相等,则在两个对象中的每个对象上调用`hashCode`方法必须产生相同的整数结果。
3.不要求如果两个对象根据[`equals(java.lang.Object)`]方法不相等,那么在两个对象中的每个对象上调用`hashCode`方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能。

最需要重视的,就是第二条。如果equals方法判断了两个对象相等,结果为true,那么hashcode方法必须产生相同的整数结果。

所以大家会发现,一般我们在idea中快捷生成equals方法的重写的时候,idea会同步重写hashcode方法,就是因为这一条规则的存在。

(再次提醒:注意,无论何时重写equals方法,通常需要重写`hashCode`方法,以便维护`hashCode`方法的通用合同,该方法规定相等的对象必须具有相等的哈希码)

 同时我们也要意识到,我们是可以自己重写hashcode方法的,只要保证满足这个规则,就可以自己随意重写。

示例:

import java.util.Objects;

class Dog {
    int id;
    String name;

    public Dog(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public boolean equals (Object o) {
        if (this ==  o) {
            return  true;
        }
        if (o instanceof Dog) {
            Dog dog = (Dog)o;
            return this.id == dog.id && dog.name.equals(this.name);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return name.hashCode() + id;
    }
}
public class Demo5 {
    public static void main(String[] args) {
        Dog dog1 = new Dog( 3, "a");
        Dog dog2 = new Dog( 3, "a");
        //现在关注的是内容,如果内容一样 调用equals方法的时候
        //必须返回一个true
        System.out.println(dog1.equals(dog2));//true
        System.out.println(dog1.hashCode());
        System.out.println(dog2.hashCode());

    }
}

没有重写hashCode时这个两个对象的hash值一样不一样?是不一样的,因为内存地址不一样的      如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。所以我们重写hashCode方法。

上面这个两个对象的值是一样的,下面我们改进一下

import java.util.Objects;

class Dog {
    int id;
    String name;

    public Dog(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public boolean equals (Object o) {
        if (this ==  o) {
            return  true;
        }
        if (o instanceof Dog) {
            Dog dog = (Dog)o;
            return this.id == dog.id && dog.name.equals(this.name);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return name.hashCode() + id;
    }
}
//同时改进一下,把两个对象的参数改成不一样的
public class Demo5 {
    public static void main(String[] args) {
        Dog dog1 = new Dog( 3, "a");
        Dog dog2 = new Dog( 2, "b");
        //现在关注的是内容,如果内容一样 调用equals方法的时候
        //必须返回一个true
        System.out.println(dog1.equals(dog2));//false
        System.out.println(dog1.hashCode());
        System.out.println(dog2.hashCode());
    }
}

这个时候你会发现,两个对象的内容是不相等的了,内存地址就更不相等了,但是,但是,你会发现,hashcode值是相等的,一个是3+97,一个是2+98,结果都是100 

所以得出结论,如果两个对象的hashcode值一样,对象是不一定一样的,但是如果两个对象相等,那么hash值一定相等。

hash值不一样,对象不一定一样。
对象一样的话,hash值一定一样

最后我们再看一个String类型的

import java.util.Objects;

class Panda {
    int id;
    String name;

    public Panda(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Panda panda = (Panda) o;
        return id == panda.id && Objects.equals(name, panda.name);
    }

    @Override
    public int hashCode() {
        return id;
    }
}
public class Demo6 {
    public static void main(String[] args) {
        String str1 = new String("ab");
        String str2 = new String("a");
        System.out.println(str1.equals(str2));//true
        //31 * 97+ 98
        System.out.println(str1.hashCode());//3105
        System.out.println(str2.hashCode());
        //STring类下面的hashCode重写的Object类下面的

        Integer i1 = new Integer(45);
        Integer i2 = new Integer(45);
        System.out.println(i1 == i2);//false
        System.out.println(i1.equals(i2));//true
        //大胆猜测一下 hash值是啥?
        System.out.println(i1.hashCode());
        System.out.println(i2.hashCode());

        Panda panda1 = new Panda(67, "狗蛋");
        Panda panda2 = new Panda(67, "狗蛋");
        System.out.println(panda2.equals(panda1));
        System.out.println(panda1.hashCode());
        System.out.println(panda2.hashCode());
    }
}

这里的31*97+98,是string重写的hashcode方法里封装的算法,属于是底层实现了,可以不用管 

以上就是hashCode()方法的总结,说实话,我写这段总结的时候自己都是有点懵的,慢慢地在写的过程中才回忆起知识点。写的不完善也有点乱,大家更多地建议看相关视频讲解,还有就是,多敲代码!

二、set集合

2.1set集合特点

Set集合也是用来存储数据的,是collection接口的子接口。

存储数据的特征:   无序的  不可重复的,注意这个不可重复是指hash值不一样(这一点是区别于List接口的,List接口是有序的,可重复的)

2.2两个实现类HashSet和TreeSet

2.2.1 HashSet

依靠hash值进行存储的,如果两个元素hash值一样的话,就不再存储了。

HashSet这个类的方法和Collection接口和Set接口下面一样的,也有自己独有的方法,和ArrayList特别像,我们先通过一段代码来感受。

import java.util.HashSet;
import java.util.Set;

public class Demo1 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        //set集合存储的无序的  不可重复的
        set.add("b");
        set.add("a");
        set.add("d");
        set.add("c");
        set.add("a");
        set.add("ad");
        System.out.println(set);

        Set<Integer> set1 = new HashSet<>();
        set1.add(78);
        set1.add(23);
        set1.add(100);
        set1.add(56);
        System.out.println(set1);
        set1.remove(23);
        //循环
        for (Integer integer : set1) {
            System.out.println(integer);
        }

    }
}

通过这段代码的输出结果能够很明确的感受到无序不可重复性这个特点,同时注意,正是由于其无序性,没法直接用for循环进行遍历,因为没有下标 。

解决办法就是用增强for循环

 for (Integer integer : set1) {
            System.out.println(integer);
        }

2.2.1.1HashSet集合存对象 

存对象的知识点和collection集合和List接口一样的,就是先创建一个类,后面set里存放相应的对象,但是要注意,创建的类为了便于理解,要重写tostring方法

同时要知道,在调用add方法添加对象的时候,底层在调用hashCode方法和equals,如果说两个对象的hash值一样,根据我们之前说的set集合的特性,无序不可重复,那么只会存放一个对象,所以就会看到有时候两个对象的内容值一样但是hash值不一样,所以两个都会存进去,就好像重复了一样。

而真实开发的时候,只关注内容的,如果内容一样,我也让你存不进去。!!!这个时候就需要重写equals方法和hahsCode方法。

在添加的时候,注意是先调用hashCode方法,再调用equals方法,也就是说,会先判断hash值是否一样,如果一样,再比较内容,内容也一样就不存,如果hash值不一样,那就直接存。

hash值不一样,对象不一定一样。
对象一样的话,hash值一定一样

再次重申知识点!

接下来看示例:

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

class Person {
    int id;
    String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return id == person.id && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Person person1 = new Person(1, "zhangsan");
        Person person2 = new Person(1, "李四");
        Person person3 = new Person(1, "李四");
        Person person4 = new Person(1, "李四");
        Set<Person> set = new HashSet<>();
        //在调用add方法的时候 底层在调用hashCode方法和equals
        set.add(person1);
        set.add(person2);
        set.add(person3);
        set.add(person4);
        System.out.println(set);
        //感觉不太合适,发现存的两个对象的内容是一样。真实开发的时候
        //只关注内容的,如果内容一样,我也让你存不进去。!!!

        //总结:以后set集合中如果想存对象的时候,要求对象的内容如果一样的
        //话,不能存到set集合中,咋办?重写equals方法和hahsCode方法


        //hash值不一样,对象不一定一样。
        //对象一样的话,hash值一定一样
    }
}
2.2.2TreeSet

也是实现了Set集合,可以保证数据 唯一性,存储也是无序的。底层是二叉树里的红黑树,对存储数据进行自然排序 。

2.2.2.1底层结构

说结构之前,我们要明确什么是数据结构,数据结构,其实就是存储数据的各种结构,分为线性的和非线性的,线性的比如数组,非线性的比如树、图。说起来不难,但是想要搞懂各类数据结构及其底层原理实现,还是要点水平的。

我们先简单了解一下底层结构——二叉树。

通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。

树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。

树结构存储的数据,每个数据也需要节点来保存。

而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?

二叉树:每个节点的下面最多只能有2个子节点。

说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。

在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。

既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?

二叉树的存储流程:

当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。

如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:

大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。

等于根元素:丢弃。

小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。

总结:二叉树是通过比较大小来保证元素唯一和排序的。

比如:用二叉树对一下数据排序
20  10  31  5  13  23 51 

 

大家可以看看这个博主的,拓展学习。 

什么是二叉树,二叉树及其性质详解 

 

2.2.2.2TreeSet存数据

TreeSet简单的存数据,基本和hashset一样 

package com.qfedu.c_treeSet;

import java.util.Set;
import java.util.TreeSet;

public class Demo1 {
    public static void main(String[] args) {
        //TreeSet在存储的数据的时候 会排序
        Set<Integer> set = new TreeSet<>();
        set.add(89);
        set.add(79);
        set.add(69);
        set.add(109);
        set.add(39);
        System.out.println(set);

        Set<String> set1 = new TreeSet<>();
        set1.add("d");
        set1.add("w");
        set1.add("a");
        set1.add("c");
        System.out.println(set1);
    }
}

 重点是TreeSet集合中存自定义对象

想要在TreeSet集合中添加对象,必须要去实现Comparable这个接口

 抽象方法:

| int | compareTo(T o)将此对象与指定的对象进行比较以进行排序。 |

返回值是int类型,但是形参是泛型
将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。

 所以说,如果想要在TreeSet集合中存自定义对象,具体的操作步骤

1.首先需要创建一个类,这个类去实现Comparable接口
2.其次需要在类里重写compareTo()方法,注意这里面就选取类的一个int属性进行比较就好。返回值为int,形参就直接写成这个类的类型,本来就是比较同一个类的不同对象,就没必要再写泛型
3.在主类里创建多个对象并调用compareTo()进行比较
4.最终treeset会对存入的对象按其compareTo()方法返回的int值从小到大排序,这个排序次数不定,

 如果不重写,那么在存数据的时候就会报类转换异常的错误。

        //  Exception in thread "main" java.lang.ClassCastException:
        //  com.qfedu.c_treeSet.Student cannot be cast to      java.lang.Comparable
        // at java.util.TreeMap.compare(TreeMap.java:1294)
        //因为Student转换不了Comparable
        //而底层在进行排序的时候,实现了Comparable这个接口

示例

import java.util.Set;
import java.util.TreeSet;

class Student implements Comparable<Student>{
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        System.out.println("123");
        int num = this.age - o.age;
        return num;
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Student stu1 = new Student("老邢", 45);
        Student stu2 = new Student("老邢", 35);
        Student stu3 = new Student("saolei", 25);
        Student stu4 = new Student("老万", 87);
        //按照年龄进行排序 存到TreeSet集合中
        Set<Student> set = new TreeSet<>();
        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu4);
        System.out.println(set);


    }
}

我们分析代码,利用断点逐个跟进看代码运行情况

> 得有一个int类数据
>
> 好好思考一个问题:你得给我返回一个int类型的数据
>
> ​  stu1有age变量    stu1的年龄 减去 stu2的年领
>
> 如果年龄返回值是一个负数的话: stu1的年领小与 stu 2
>
> 如果年龄返回值是一个0的话,stu1的年龄和stu2年龄相等
>
> 如果年龄返回值是一个正整数的话: stu1的年领大于 stu 2

stu1   45

stu2   35

stu3   25

compareTo

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]

基本上是非常详细的解释了底层原理,大家多看多想多写。

另外注意:如果是String类型或者Integer之类的,java是已经封装好了的,直接调用compareTo()方法就是,String类型是比较每个字符串的Unicode码。

我们再看几个示例:

1.使用TreeSet存储Employee对象,比较两个属性
int age,  int weight   先按照年龄进行升序排,如果年龄相等的话,按照体重升序排

import java.util.Set;
import java.util.TreeSet;

class Employee implements Comparable<Employee>{
    String name;
    int age;
    int weight;

    public Employee(String name, int age, int weight) {
        this.name = name;
        this.age = age;
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", weight=" + weight +
                '}';
    }

    @Override
    public int compareTo(Employee o) {
        //先按照年两比,如果年龄相等 就比较体重
        int num = this.age - o.age;
        if (num == 0) {
            int num1 = o.weight - this.weight;
            return num1;
        }
        return num;
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Set<Employee> set = new TreeSet<>();
        set.add(new Employee("广坤", 35, 78));
        set.add(new Employee("二贝", 26, 70));
        set.add(new Employee("赵四", 35, 72));
        set.add(new Employee("彩云", 35, 79));
        set.add(new Employee("鸡哥", 32, 59));
        set.add(new Employee("正经博", 32, 59));
        System.out.println(set);
    }
}

 这里面需要着重注意的就是重写的compareto方法,还有就是this和o分别指代,顺序不同决定了最后是从小到大排还是从大到小排

2.TreeSet里面存的是Dog类,
两个属性: String  name, int  age
先按照字符串的字典顺序排,然后字符串相等的话,在按照年龄排

import java.util.Set;
import java.util.TreeSet;

class Dog implements Comparable<Dog>{
    String name;
    int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Dog o) {
        //先按照字典的顺序进行排,如果字符串相等再按照年龄升序排
        int num = this.name.compareTo(o.name);
        if (num == 0) {
            //字符串相等的情况,又要比较年领
            int num1 = this.age - o.age;
            return num1;

        }
        return num;
    }
}
public class Demo3 {
    public static void main(String[] args) {
        Set<Dog> set = new TreeSet<>();
        set.add(new Dog("彩云", 5));
        set.add(new Dog("旺财", 2));
        set.add(new Dog("大黄", 6));
        set.add(new Dog("大黄", 3));
        set.add(new Dog("大黄", 4));
        System.out.println(set);
    }
}

这个的变化就是,比较的是string类型,在自己重写的compareto方法里又重新调用了string的compareto方法,但不是递归,要想清楚。


以上,就是今天的所有知识点了。hashCode有点小混乱,需要多理解,set集合应该是比奥清楚的,就是要记的背的东西很多,大家得多花点时间,静下心慢慢看,慢慢理解,不是什么大问题。数据结构的知识点,大家可以下来自行再拓展。

加油吧,预祝大家变得更强!

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/204713.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件系统安全漏洞检测应该怎么做?靠谱的软件安全检测公司推荐

软件系统安全漏洞检测是指通过对软件系统进行全面的、系统化的评估&#xff0c;发现和解决其中可能存在的安全漏洞和隐患。这些安全漏洞可能会被不法分子利用&#xff0c;引发数据泄露、系统瘫痪、信息被篡改等安全问题&#xff0c;给企业造成严重的经济和声誉损失。那么软件系…

jenkins 使用 nexus插件,将代码打包好推送到制品库

Nexus是一个开源的、基于Java的应用程序框架和存储库管理系统&#xff0c;可用于管理软件开发和部署的所有相关构件。 它允许用户创建和维护Maven存储库&#xff0c;使其更易于组织&#xff0c;搜索和共享构建工件和库。 Nexus具有安全性和身份验证、多格式支持、镜像管理和自定…

精彩回顾|迪捷软件先进装备软件技术研讨会之行圆满收官

2023年11月24日&#xff0c;为期3个月的先进装备软件高安全、高可靠、智能化验证技术系列研讨会在成都圆满收官。迪捷软件董事长康烁作为研讨会特邀专家&#xff0c;在西安、上海、成都站进行了演讲分享。 以航空航天、船舶、电力电子、汽车、医疗为代表的先进装备软件发展迅速…

ELK+filebeat+kafka

无需创建logstash的端口&#xff0c;直接创建topic 远程收集mysql和httpd的日志 &#xff08;一&#xff09;安装nginx和mysql服务 1、打开mysql的日志功能 2、创建日志&#xff08;创库、创表、添加数据&#xff09; &#xff08;1&#xff09;mysql服务器上安装http system…

Jenkins持续集成Python项目

一、前言   之前学习了很多自动化测试框架&#xff0c;但是写的脚本都是本地执行&#xff0c;多数用来造数据。最近公司掀起一股自动化测试的风&#xff0c;所以就想研究下如何集成jenkins&#xff0c;本次采用pytest&#xff0c;用的是阿里云服务器centos7。 二、服务器环境…

功能测试常见的测试方法及其使用实例说明

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

软文推广如何自然融入品牌?媒介盒子有妙招

软文推广作为一种柔性推广方式&#xff0c;能将品牌信息融入到用户日常浏览的内容中&#xff0c;让用户不知不觉接触品牌&#xff0c;从而产生好感&#xff0c;这种方式既可以避免广告带来的反感&#xff0c;又可以提高广告的有效性。那么在推广中应该如何自然融入品牌信息呢&a…

一文看懂:库存分析如何做?

在之前的文章中&#xff0c;老李给大家简单介绍了制造业数据分析用到的指标体系和典型分析场景。如果你读过那篇文章&#xff0c;你就会知道制造业主要有两个典型的分析场景&#xff0c;一是库存管理&#xff0c;二是生产管理。虽然老李在之前的文章中提到了这两个场景&#xf…

Cesium.CustomShader颜色值显示错误

官方示例&#xff1a; Cesium Sandcastle 测试过程&#xff1a; 1、修改示例&#xff0c;把customshader中的fragmentShaderText替换为如下代码 void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {//注意&#xff1a;下述颜色的b值是0.1&#x…

IPv6+2.0网络切片技术在电子政务网的应用实践详解

IPv6是面向5G、云网/算网融合的智能IP技术&#xff0c;具有包含可编程路径、快速业务发放、自动化运维、质量可视化、SLA保障和应用感知等特点。IPv6将万物互联提升到了万物智联&#xff0c;赋能百行百业高质量数字化转型。 图示&#xff1a;“IPv6”技术创新体系发展的三个阶段…

机器学习模型验证——以数据为中心的方法

构建机器学习模型时&#xff0c;人们往往将激情和精力集中于收集数据和训练模型&#xff0c;对测试模型和验证结果往往缺少应有的关注。正确的验证技术有助于估计无偏见的广义模型的性能&#xff0c;并更好地理解模型训练的效果。您需要确保机器学习模型经过准确的训练&#xf…

骨传导与入耳式耳机哪种音质好?骨传导与入耳式耳机有什么区别?

由于骨传导耳机和入耳式耳机的传声原理不同&#xff0c;入耳式耳机的音质要更好一些&#xff01; 想要了解骨传导耳机和入耳式耳机哪种音质好&#xff0c;首先就要了解骨传导耳机和入耳式耳机的传声原理有什么区别&#xff1f; 一、骨传导耳机和入耳式耳机有什么区别 1、传声…

智慧垃圾分拣站:科技改变城市环境,创造更美好的未来

随着城市化进程的不断加快&#xff0c;垃圾处理问题日益凸显。为了更好地解决垃圾分类问题&#xff0c;越来越多的城市开始推广智慧垃圾分拣站&#xff0c;利用创新科技实现高效垃圾分类处理。 山海鲸使用三维建模技术&#xff0c;建立了一个智慧垃圾分拣站数字孪生模型&#x…

PHP在线日语学习平台

有需要请加文章底部Q哦 可远程调试 PHP在线日语学习平台 一 介绍 此日语学习平台基于原生PHP开发&#xff0c;数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 3 查看课程…

自己的邮箱名称出现在别人的此电脑的网络位置中

在公司别的同事告诉我&#xff0c;我的邮箱名字出现在他们的【此电脑】-【网络位置中】 如图&#xff1a; 当时吓我一跳&#xff0c;因为我总喜欢搞一些渗透的东西&#xff0c;我以为把自己暴漏了&#xff0c;然后疯狂的在网上找原因。 于是就搜到一位安暖的博主&#xff1a; …

发生这种情况 经常导致投资者的痛苦

在这个市场中&#xff0c;什么事会让人痛苦呢&#xff1f;有的投资者马上回答&#xff0c;因为亏损。说实话&#xff0c;如果经过刻意的练习&#xff0c;我们在一定程度上能克服亏损给人带来的痛感。但是有另一种情况也容易为投资者带来痛苦&#xff0c;下面我们就来讨论一下。…

单片机学习12——电容

电容的作用&#xff1a; 1&#xff09;降压作用&#xff1a; 容抗&#xff1a; Xc 1/2fc 串联分压原理。2100Ω的容量&#xff0c;50Hz的频率&#xff0c;可以得到1.5uF。断电之后&#xff0c;需要串联一个1MΩ的电阻放电。 那是不是可以使用2100欧姆的电阻来代替电容呢&am…

Java高级技术(反射的作用与应用场景)

一&#xff0c;放射 二&#xff0c;案例 &#xff08;1&#xff09;&#xff0c;题目 &#xff08;2&#xff09;&#xff0c;反射类 &#xff08;3&#xff09;&#xff0c;测试类

民安智库(第三方公众满意度调查):专业助力咖啡店客户满意度调查

近期&#xff0c;一家知名的咖啡店品牌面临着市场竞争加剧和服务质量提升的挑战。为了更好地了解客户需求和提升客户满意度&#xff0c;该咖啡店决定委托民安智库&#xff08;第三方满意度测评&#xff09;开展一次全面的客户满意度调查。 本次调查旨在了解客户对咖啡店服务的…

【10张图带你搞清楚生成树协议】

STP协议分类 BPDU&#xff0c;网桥协议数据单元 STP路径开销&#xff0c;以链路带宽为准&#xff0c;两个标准&#xff0c;现在主要以NEW为准 在网络刚开始运行的阶段&#xff0c;所有交换机都会从所有端口发送BPDU&#xff0c;大家都认为自己是root&#xff0c;随着B…