java学习--day17 (Set集合、toString&equals方法)

文章目录

      • 1.Object类
      • 2.Set集合
        • 2.1hashSet类
        • 2.2HashSet集合存对象
        • 2.3TreeSet集合
        • 2.4TreeSet集合中存的是对象

回顾

1.Collection的方法
2.对集合遍历
	1.for循环
	2.增强for循环
	3.迭代器
3.List接口下面的方法
4.ArrayList和LinkedList的区别
5.集合中存对象的
1.Collection 接口下面的方法
	add()
	addAll()
	remove(Object obj);
	removeAll();
	clear();
	size();
	contains();
	toArray();
	conatinsAll();
	isEmpty();
2.List接口的方法
	add(int index, E e);
	addAll(int index, Collection);
	remove(int index);
	set(int index, E e);
	get(int index);
	indexOf(E e);
	lastIndexOf(E e);
	subList(int fromIndex, int toIndex);
	
3.static关键字的使用
	static 修饰成员变量
	static修饰成员方法
	static修饰代码块
4.throw和throws的区别
	throw 抛出一个异常对象
	throws 在方法的声明处使用,告知调用者此方法有异常
5.接口和抽象类的区别
	接口声明interface
	抽象类abstract 
	
6.ArrayList和LinkedList的区别

1.Object类

Object类是Java中所有类的基类

学习Object类就是在学习他的方法

构造方法:

可以直接实例化

Object()

只需要学习三个方法

String toString()返回对象的字符串表示形式
public String toString()

返回对象的字符串表示形式。 一般来说, toString方法返回一个“textually代表”这个对象的字符串。 结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法。

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

getClass().getName() + '@' + Integer.toHexString(hashCode()) 
  • 结果

    对象的字符串表示形式。

package com.qfedu.a_object;
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);

    }
}

boolean equals(Object obj)指示一些其他对象是否等于此。

boolean eaqual(Object obj);

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

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

为啥String类下面的equals方法比较的是内容呢?String类继承了Object

equals方法重写了Object类下面的。为啥重写?

当父类的需求,满足不了子类的需求的时候要重写父类的方法

需求:比较两个对象的内容是否一样? 如果两个对象的内容一样返回一个true。反之返回false

package com.qfedu.a_object;

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
    }
}

package com.qfedu.a_object;

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
    }
}

int hashCode();

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

返回对象的哈希码值。 支持这种方法是为了散列表,如HashMap提供的那样 。

hashCode的注意事项是:

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

尽可能多的合理实用,由类别Object定义的hashCode方法确实为不同对象返回不同的整数。 (hash码的值通常通过将对象的内部地址转换为整数来实现,但Java的编程语言不需要此实现技术。)

package com.qfedu.a_object;

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");
        //现在真他娘的尴尬,Object类的hash值是内存地址十进制的转换
        //只要你内U存地址不一样,hash值一定不一样
        //但是你看看str和str2 ,内存地址不一样,但是
        //hash值是一样的?咋回事?在String类中重写了hashCode
        //方法
        System.out.println(str.hashCode());//97
        System.out.println(str1.hashCode());//98
        System.out.println(str2.hashCode());//97



    }

}

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

package com.qfedu.a_object;

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));//true
        //此时这个两个对象的hash值一样不一样?因为内存地址不一样的
        System.out.println(dog1.hashCode());
        System.out.println(dog2.hashCode());
        //现在hashCode不一样咋办? 重写hashCode即可
//如果根据equals(Object)方法两个对象相等,
// 则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
        //如果两个对象的hash值一样,对象是不一定一样的。但是如果两个对象相等
        //那么hash值一定相等
    }
}

package com.qfedu.a_object;

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());
    }
}

2.Set集合

Set集合也是用来存储数据的

Set也是一个接口

父接口是Collection

存储数据的特征: 无序的 不可重复的

Set接口有两个实现类:

​ HashSet:

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

​ TreeSet:

​ 底层是二叉树,对存储数据进行自然排序

2.1hashSet类

HashSet这个类的方法和Collection接口和Set接口下面一样的

也有自己独有的方法,和ArrayList特别象

package com.qfedu.b_hashSet;

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);
        }

    }
}

2.2HashSet集合存对象
package com.qfedu.b_hashSet;

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只能一定一样
        // 每次执行add()方法就会调用一次hashcode方法进行比较对象的哈希	码是否相同
		// 当hash码相同时,再调用equals方法进行内容比较
		// 哈希码相同,内容不一定相同。内容相同,哈希吗一定相同。
    }
}

2.3TreeSet集合

也是实现了Set集合,可以保证数据 唯一性,存储也是无序的

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);
    }
}

2.4TreeSet集合中存的是对象

如果想要在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

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]


package com.qfedu.c_treeSet;

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);

        //  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
        //y因为底层在进行排序的时候,实现了Comparable这个接口
        //为啥泛型String没有报错  Integer也没有报错
    }
}

你可能感兴趣的:(Java基础,java)