JavaSE基础———Set接口中的常用类HashSet、LinkedHashSet和TreeSet

1. HashSet 集合

   (1)HashSet 的概述

     HashSet 的底层数据结构是哈希表(哈希表是一个元素为链表的数组)。HashSet 不是线程安全的,集合元素可以是null。当向HashSet 中存入一个元素时,HashSet 会调用该对象的HashCode()方法来得到该对象的HashCode值,然后根据HashCode值决定该对象在HashSet 中的存储位置。

   (2)HashSet判断两个元素相等的标准:

     两个对象的HashCode值相等,并且两个对象的equals方法的返回值也相等。

代码演示:


import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }

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

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

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
import java.util.HashSet;

public class Test {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<>();
        set.add(new Person("张三",21));
        set.add(new Person("张三",22));
        set.add(new Person("张三",21));
        System.out.println(set);
    }
}

执行结果:
在这里插入图片描述
重写了HashCode和equals方法后才能保证对象元素的唯一性。

2. LinkedHashSet 集合

   (1)概述

      LinkedHashSet 是底层数据是链表和哈希表。链表保证了数据的有序性,哈希表保证了数据的唯一性。

   (2)特点:LinkedHashSet的存储顺序和取出的顺序是一样的,它是线程不安全的集合,运行速度快。

3. TreeSet 集合

   (1)概述

      TreeSet 集合继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
      TreeSet基于TreeMap实现的。TreeSet中含有一个”NavigableMap类型的成员变量”m,而m实际上是”TreeMap的实例”。 底层的数据结构是红黑树(平衡二叉树)。

   (2)特点

     存入的元素唯一并且可以对元素排序。
     排序方式有两种:自然排序和比较器排序。
     如果要使用自然排序,那么对其中元素就要求实现Comparable 接口。

代码演示:

package com.westos.demo;

import java.util.Objects;

public class Person implements Comparable<Person>{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public int compareTo(Person p) {
        int num  = this.age-p.age;
        int num2 = num==0?this.name.compareTo(p.name):num;
        return num2;
    }
}

package com.westos.demo;

import java.util.TreeSet;

public class Test1 {
    public static void main(String[] args) {
        TreeSet<Person> set = new TreeSet<>();
        set.add(new Person("张三",25));
        set.add(new Person("李四",21));
        set.add(new Person("王五",23));
        set.add(new Person("王五",28));
       for (Person person : set) {
            System.out.println(person);
        }
    }
}

不写排序的异常:
在这里插入图片描述
执行结果:
在这里插入图片描述
4. HashCode和equals方法的面试题

   ● 问题: 如果两个对象的哈希值相同 p1.hashCode()==p2.hashCode() , 两个对象的equals一定返回true吗 p1.equals(p2) 一定是true吗?

   正确答案:不一定

   ● 如果两个对象的equals方法返回的结果为true,两个对象的哈希值一定相同吗?

   正确答案:一定

在 Java 应用程序执行期间,
1.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
2.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。

两个对象不同(对象属性值不同) equals返回false=====>两个对象调用hashCode()方法哈希值相同

两个对象调用hashCode()方法哈希值不同=====>equals返回true

所以说两个对象哈希值无论相同还是不同,equals都可能返回true

发布了58 篇原创文章 · 获赞 7 · 访问量 2299

猜你喜欢

转载自blog.csdn.net/weixin_42492089/article/details/102991955