java treeset和hashset如何判断元素是不是相同

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java treeset和hashset如何判断元素是不是相同相关的知识,希望对你有一定的参考价值。

在使用treeset和hashset重复添加元素时,发现二者在比较自定义对象元素上不一样,如下例
假设record对象包含两个信息,一个为int age,一个为String name

Set<record> t0= new TreeSet<record>();
t0.add(new record(1,"lAn"));
t0.add(new record(1,"lAn"));
t0.add(new record(1,"lAn"));
System.out.println(t0);
treeset的输出为[1 lAn]

将相同元素添加到hashset中
Set<record> t1= new HashSet<record>();
t1.add(new record(1,"lAn"));
t1.add(new record(1,"lAn"));
t1.add(new record(1,"lAn"));
System.out.println(t0);
输出为[1 lAn,1 lAn,1 lAn]

为什么会有这种情况呢? hashset和treeset是怎么比较元素相等的?

我想看下你得record类,问题可能出在你得record类里面,你是不是重写了hashcode方法?


刚才看了一下,问题出在你得record类应该,你没有生成一个hashcode()方法,所以你得hashcode方法继承自object类

object类的hashcode算法hashcode算出来的结果就是该对象在内存中的地址的十进制表示,你每次都是new出来的record,所以他们的内存地址一定是不一样,那么这就说明他们的hashcode不一样,而hashset对于相同对象的比较是使用hashcode的,他们的hashcode不同,那么自然被hashset认为是不一样的对象了,所以有了你的结果,建议record类里面写一个hashcode方法,可以利用Eclipse或MyEclipse的生成的那个hashcode算法


然后说说treeset

boss来了,等下给你补上


好了,boss走了,吓死我了

对于你的treeset,他是用compareTo方法判断是否相同,treeset要求你必须给record类实现comparable接口,你应该写了,但是这个接口有个方法compareTo你实现的时候可能是用了默认的吧,默认的compareTo方法只有一句,就是return 0;所以对于任何两个对象来说他们compareTo都是相同的,那么treeset就会认为这些record都是一样的,没区别,所以就只有一条

,建议可以利用下Eclipse或MyEclipse的equals算法生成,然后在compareTo方法里调用equals方法比较


综上所述

hashset用hashcode方法来实现比较是否相同

而treeset用comparable接口的compareTo方法比较


有问题可以追问,

打了这么多字给分吧~~

希望能帮助你


我人还是太好了,附带着还是把record的代码发给你吧,免得你迷糊


public class record implements Comparable
    private int age;
    private String name;
    
    public record(int age,String name)
        // TODO Auto-generated constructor stub
        this.age=age;
        this.name=name;
    

    @Override
    public int compareTo(Object o) 
        // TODO Auto-generated method stub
        
        if(equals(o))
            return 0;
        else 
            return -1;
        
    

    @Override
    public String toString() 
        return "record [age=" + age + ", name=" + name + "]";
    

    @Override
    public int hashCode() 
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    

    @Override
    public boolean equals(Object obj) 
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        record other = (record) obj;
        if (age != other.age)
            return false;
        if (name == null) 
            if (other.name != null)
                return false;
         else if (!name.equals(other.name))
            return false;
        return true;
    
    

参考技术A HashSet 底层数据结构是哈希表,判断两个HashSet对象是否相等,先调用hashCode(),如果hashCode()相等,再调用equals(),equals()也相等,两个对象才相等。
TreeSet底层数据结构是二叉树,一个对象想存入TreeSet中有两种方式:
实现Comparable接口:此时判断相等只依据重写的compareTo中 是否return 0 这一条件,return 0相等,否则不相等;
创建一个Comparator比较器:此时判断是否相等,根据重写Comparator接口中的compare()方法是否return 0判断,return 0相等。
参考技术B

    他们分别用的treemap 和 hashmap。都是用compare方法比较对象的

    你的record类有实现comparable接口重写equals方法?如果没有重写的话。就是应该输出3个,因为你是传进去了3个record对象。

    如果有的话,看看你是怎么实现的

java学习之treeset

Set:无序,不可以重复元素

  |--HashSet:数据结构是哈希表,线程是非同步的。

          保证元素唯一性的原理:判断元素的hashcode值是否相同

            如果相同,还会继续判断元素的equals方法,是否为true

 

  |--TreeSet:可以对Set集合中的元素进行排序

 

注意:排序时,当主要条件相同时,一定要判断一下次要条件(否则会被认为是同一个对象而不被加入)

 1 import java.util.Iterator;
 2 import java.util.TreeSet;
 3 
 4 /**
 5  * 需求:
 6  * 往treeset集合中存储自定义对象学生  
 7  * 想按照学生的年龄进行排序
 8  */
 9 public class PackageDemo {
10 
11     public static void main(String[] args) {
12         TreeSet ts=new TreeSet();
13         ts.add(new Student("皮卡丘1",20));
14         ts.add(new Student("皮卡丘",20));
15         ts.add(new Student("皮卡",19));
16         ts.add(new Student("雷卡",21));
17         ts.add(new Student("雷卡",21));
18         
19         Iterator it=ts.iterator();
20         
21         while(it.hasNext()) {
22             Student student=(Student)it.next();
23             System.out.println(student.getName()+"...."+student.getAge());
24         }
25         
26     }
27 
28 }
29 class Student implements Comparable{//该接口强制让学生具有比较性
30     private String name;
31     private int age;
32     public Student(String name,int age) {
33         this.name=name;
34         this.age=age;
35     }
36     public String getName() {
37         return name;
38     }
39     public int getAge() {
40         return age;
41     }
42     @Override
43     public int compareTo(Object o) {
44         if(null == o) {
45             throw new RuntimeException("传进一个空对象");
46         }
47         if(!(o instanceof Student)) {
48             throw new RuntimeException("传进来的不是学生类");
49         }
50         Student student=(Student)o;
51         if(this.age>student.age) {
52             return 1; 
53         }else if(this.age==student.age) {
54             return this.name.compareTo(student.name);//注意:排序时,当主要条件相同时,一定要判断一下次要条件(否则会被认为是同一个对象而不被加入)
55         }
56         return -1;
57     }
58     
59     
60 }

 

以上是关于java treeset和hashset如何判断元素是不是相同的主要内容,如果未能解决你的问题,请参考以下文章

Java集合 -- HashSet 与TreeSet和LinkedHashSet的区别

java:Set对象TreeSet有序子类,HashSet无序子类,重复对象二

hashset和treeset区别

HashSet和TreeSet的区别

java数据结构之HashSet和TreeSet

HashSet,TreeSet和LinkedHashSet的区别