简单的理解java集合中的HashSet和HashTree几个重写方法

 更新时间:2020年10月13日 14:11:58   作者:m0_51327764  
这篇文章主要介绍了简单的理解java集合中的HashSet和HashTree几个重写方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Java中的set是无序的,但是是不可重复的

HashSet底层是哈希表,通过调用hashcode和equals方法实现去重

当我们HashSet里面存的是字符串时,就能默认去重了,因为String已经重写了hashcode和euqals方法

  public static void main(String[] args) {
    HashSet<String> set = new HashSet();
    set.add("java");
    set.add("c");
    set.add("php");
    set.add("bigdata");
    set.add("java");
    //运行结果,给去重了,而且是无序的
    System.out.println(set);//[java, c, bigdata, php]
  }
}

但是当我们有类的时候,比如Person,Cat,Dog,我们自己写的类,但是我们想按照自己制定的规则去重,就比如Person的姓名和年龄,因为Person类是我们自己建的,如果我们没有重写方法,就会去找Object的hashcode方法,这样new Person()的hashcode就会不同,这样每个都是一个新的,都会输出,即使年龄和姓名一样

public class Demo1 {
  public static void main(String[] args) {
    HashSet<Person> set1 = new HashSet<>();
    set1.add(new Person("aing",50));
    set1.add(new Person("bing",10));
    set1.add(new Person("ding",20));
    set1.add(new Person("ding",20));
    //运行结果是即使名字年龄一样,也会输出两个,我们如果想要按照自己的规则去重,这样我们一定要重写hashcode 和euqals方法
    System.out.println(set1);//[Person{name='bing', age=10}, Person{name='ding', age=20}, Person{name='aing', age=50}, Person{name='ding', age=20}]
  }
}
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 +
        '}';
  }
}

我们重写hashcode方法,当hashcode不一样时,就不会比较equals,直接就是不一样,如果hashcode一样,再比较equals方法

public class Demo1 {
  public static void main(String[] args) {
    HashSet<Person> set1 = new HashSet<>();
    set1.add(new Person("aing",50));
    set1.add(new Person("bing",10));
    set1.add(new Person("ding",20));
    set1.add(new Person("ding",20));
    //根据年龄和姓名比较的
    System.out.println(set1);//[Person{name='ding', age=20}, Person{name='aing', age=50}, Person{name='bing', age=10}]
  }
}
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 +
        '}';
  }
  @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);
  }
  //和属性关联,根据属性的值比较,之所以让age*100;是因为怕有可能出现这个name.hashCode()+age 和 下一个name.hashCode()+age加起来的值恰好相等,所以age*100,可以避免这种情况的发生
  @Override
  public int hashCode() {
    //return Objects.hash(name, age);
    return name.hashCode()+age*100;
  }
}

TreeSet底层是二叉树,而且TreeSet还是有序的,在String中不仅重写了hashcode,还要调用元素的compareTo方法, String类已经实现了Comparable接口,并重写 了compareTo方法,但是如果我们自己写类的话,比如Person来说,如果想要按照自己的规则比,就要重写hashcode方法和实现Comparable接口

public class Demo2 {
  public static void main(String[] args) {
    TreeSet<String> set = new TreeSet();
    set.add("java");
    set.add("c");
    set.add("php");
    set.add("bigdata");
    set.add("java");
    System.out.println(set);//[bigdata, c, java, php]
  }
}

但是要是自己的类
会报错cannot be cast to java.lang.Comparable,因为Person会去找compareTo的方法,但是Person类没有实现它,我们要去实现Comparable

public class Demo2 {
  public static void main(String[] args) {
    TreeSet<Person1> set1 = new TreeSet<>();
    set1.add(new Person1("aing",50));
    set1.add(new Person1("bing",10));
    set1.add(new Person1("ding",20));
    set1.add(new Person1("ding",20));
    System.out.println(set1);
  }
}
class Person1{
  String name;
  int age;

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

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

这样我们就可以实现有序了,根据我们的属性

public class Demo2 {
  public static void main(String[] args) {
    TreeSet<Person1> set1 = new TreeSet<>();
    set1.add(new Person1("aing",50));
    set1.add(new Person1("bing",10));
    set1.add(new Person1("ding",20));
    set1.add(new Person1("ding",20));
    System.out.println(set1);
  }
}
class Person1 implements Comparable{
  String name;
  int age;

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

  @Override
  public int hashCode() {
    return name.hashCode()+age*100;
  }

  @Override
  public String toString() {
    return "Person1{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
  }
  //根据类的属性进行排序
  @Override
  public int compareTo(Object o) {
  Person1 person = (Person1)o;
  int num = name.compareTo(person.name);
  return num==0?age-person.age:num;
}
}

到此这篇关于简单的理解java集合中的HashSet和HashTree几个重写方法的文章就介绍到这了,更多相关java HashSet和HashTree重写内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JAVA 自定义线程池的最大线程数设置方法

    JAVA 自定义线程池的最大线程数设置方法

    这篇文章主要介绍了JAVA 自定义线程池的最大线程数设置方法,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
    2020-06-06
  • Java和c语言随机数Random代码详细

    Java和c语言随机数Random代码详细

    这篇文章主要介绍Java和c语言得随机数Random,随机数的用处在生活中比较少见,但是用处并不少,比如一些小游戏的制作等等。下面我们就一起来学习这篇关于Java和c随机数Random得文章吧
    2021-10-10
  • springboot通用分支处理超级管理员权限逻辑

    springboot通用分支处理超级管理员权限逻辑

    这篇文章主要为大家介绍了springboot通用分支处理超级管理员的权限逻辑,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 一文搞懂Java正则表达式的使用

    一文搞懂Java正则表达式的使用

    正则表达式,又称规则表达式,是一种文本模式。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。本文将通过示例为大家详细说说Java正则表达式的使用,感兴趣的可以了解一下
    2022-08-08
  • JAVA实现图书管理系统项目

    JAVA实现图书管理系统项目

    相信每一个学生学编程的时候,应该都会写一个小项目——图书管理系统。为什么这么说呢?我认为一个学校的氛围很大一部分可以从图书馆的氛围看出来,而图书管理系统这个不大不小的项目,接触的多,也比较熟悉,不会有陌生感,能够练手,又有些难度,所以我的小项目也来了
    2021-10-10
  • Springboot实现动态定时任务流程详解

    Springboot实现动态定时任务流程详解

    通过重写SchedulingConfigurer方法实现对定时任务的操作,单次执行、停止、启动三个主要的基本功能,动态的从数据库中获取配置的定时任务cron信息,通过反射的方式灵活定位到具体的类与方法中
    2022-09-09
  • java JVM方法分派模型静态分派动态分派全面讲解

    java JVM方法分派模型静态分派动态分派全面讲解

    这篇文章主要为大家介绍了java JVM方法分派模型静态分派动态分派全面讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • SpringBoot的启动速度优化

    SpringBoot的启动速度优化

    随着我们项目的不断迭代 Bean 的数量会大大增加,如果都在启动时进行初始化会非常耗时,本文主要介绍了SpringBoot的启动速度优化,感兴趣的可以了解一下
    2023-09-09
  • Java中synchronized的几种使用方法

    Java中synchronized的几种使用方法

    本文主要介绍了Java中synchronized的几种使用方法,synchronized可用于修饰普通方法、静态方法和代码块,下面详细内容介绍,需要的小伙伴可以参考一下
    2022-05-05
  • Java集合的Collection接口和List接口详解

    Java集合的Collection接口和List接口详解

    这篇文章主要为大家详细介绍了Java集合的Collection接口和List接口,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03

最新评论