简体   繁体   English

树集的行为不同,但对于自定义对象,哈希集不会

[英]Tree Set behaves differently but hash set doesn't in case of custom object

In below created code have Employee class with attributes Id and Name,Created 3 objects of Employee class e1,e2,e3 with respective name attribute a,b,a. 在下面创建的代码中,创建了具有ID和Name属性的Employee类,创建了3个Employee类e1,e2,e3对象,它们分别具有名称属性a,b,a。 when I add these object in hash set the size shows 3 but on same while in Tree Set it show size 2 even i am not overriding the hash code and equals method. 当我将这些对象添加到哈希集中时,大小显示为3,但在树集中同时显示为2,即使我没有覆盖哈希码和equals方法。

    Emplyoee class.............................


        package collection.core.concept;

        public class Employee implements Comparable<Employee>{

            private int id;
            private String name;

            public int getId() {
                return id;
            }
            public void setId(int id) {
                this.id = id;
            }
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }

           @Override
           public int compareTo(Employee o) {
            if(this.name.equal(o.getName()){
               return 0;
            }else{
              return 1;
              }
           }
            @Override
            public String toString(){
            return name;

            }
    }

    main class...............................................
    public class CustomTreeSetSorting {
        public static void main(String[] args) {

            Employee e1 = new Employee();
            e1.setId(1);
            e1.setName("alok");
            Employee e2 = new Employee();
            e2.setId(2);
            e2.setName("vaibhav");
            Employee e3 = new Employee();
            e3.setId(3);
            e3.setName("alok");


            Set<Employee> Employee1 = new TreeSet<Employee>();

            Employee1.add(e1);
            Employee1.add(e2);
            Employee1.add(e3);
            System.out.println(Employee1.size());

        }
    }

In general sets you cannot have repetitions. 一般而言,您不能重复。 Hence the size is two. 因此,大小为两个。

Since 以来

 @Override
    public boolean equals(Object obj) {
        Employee emp = (Employee) obj;  
           if (name.equals(emp. getName())) {  
               return true;  
           }
           return false;  
}

It checks only name even though the id is different it treats them as same objects. 即使id不同,它也只检查名称,它将它们视为相同的对象。

Change it to 更改为

    @Override
    public boolean equals(Object obj) {
       if(obj instanceof this) {
           Employee emp = (Employee) obj;  
           if (name.equals(emp. getName()) && id == emp.getId()) {  
               return true;  
           }
           return false;  
       }
       return false;
    }

Also the code is wrong for 另外代码是错误的

@Override
public int compareTo(Employee o) {
    if(this.name==o.name){
        return 0;
    }else{
        return 1;
    }
}

Change it to 更改为

@Override
public int compareTo(Employee o) {
    return name.compareTo(o.getName());
}

You cannot compare strings with == use .equals method. 您不能使用==使用.equals方法比较字符串。

Whenever you are add something to TreeSet then compareTo method of class Employee is getting invoked and in compareTo method you are stating that if 2 names are equal then both objects are the same. 每当您向TreeSet添加一些内容时,便会调用Employee类的compareTo方法,并在compareTo方法中声明如果2个名称相等,则两个对象都相同。 Thats why TreeSet is adding only 2 objects alok and vaibhav . 这就是为什么TreeSet仅添加2个对象alokvaibhav Moreover, currently you are comparing string wrongly , in order to compare Strings use compareTo on String objects that compare objects based on natural ordering ie lexicographically 此外,当前您错误地比较了字符串,为了比较字符串,请对基于自然顺序(即按字典顺序比较对象)的String对象使用compareTo

How could we get different results according to the set that is used? 我们如何根据所使用的设置获得不同的结果? It's quite simple : the HashSet uses both equals and hashCode to check object equality. 这很简单:HashSet同时使用equals和hashCode来检查对象是否相等。 You've got 3 different ids, that's why you get 3 objects in your hashset. 您有3个不同的ID,这就是为什么在哈希集中获得3个对象的原因。

On the other hand, the TreeSet will use your compareTo method (or a provided Comparator) to compare items and check equality. 另一方面,TreeSet将使用您的compareTo方法(或提供的Comparator)比较项目并检查相等性。 If you compareTo method uses names only to give its result, and knowing you have only 2 unique names, then the TreeSet will only have 2 elements (probably the last one will be discarded) 如果compareTo方法仅使用名称来给出其结果,并且知道您只有2个唯一的名称,则TreeSet将仅具有2个元素(可能最后一个元素将被丢弃)

Personally if I was going to base my comparison on a single string for insertion into the tree I would use what is already given to us: 就个人而言,如果我将比较基于插入到树中的单个字符串,我将使用已经提供给我们的内容:

public int compareTo(Employee o) {
    return this.name.compareTo(o.getName());
}

Not sure why this isn't the first choice? 不确定为什么这不是首选? Am I missing something? 我想念什么吗?

Given that, you probably need more than just the String, otherwise why have id's? 鉴于此,您可能不仅仅需要String,否则为什么要使用id? I can't fathom two employee objects being the same if they have different id's (ie if they have more than one ID, I would create an array of id's as names are not unique.) 如果两个员工对象具有不同的ID,则我无法理解它们是否相同(即,如果它们具有多个ID,由于名称不是唯一的,我将创建一个ID数组)。

Both HashSet and Treeset doesn't allow duplicates. HashSetTreeset都不允许重复。

The behavior is explained by understanding How do you define a Duplicate! 通过了解How do you define a Duplicate!来解释该行为How do you define a Duplicate!


HashSet 哈希集

In case of HashSet , the hashcodes for two objects are different even for same names, hence they are not considered duplicates.Unless you override hashCode and equals all the objects are considered distinct/unique 在的情况下, HashSet ,两个对象的哈希码是即使是同一名称的不同,因此它们没有考虑duplicates.Unless你重写hashCodeequals所有的对象都认为是不同的/独特


TreeSet: TreeSet:

You are providing the definition of "Duplicate" by overriding compareTo . 您将通过覆盖compareTo提供“ Duplicate”的定义。 ie If the names are same then the Objects are same 即,如果名称相同,则对象相同

To allow duplicates in your TreeSet , Change your compareTo to 要允许TreeSet有重复项,请将compareTo更改为

@Override
  public int compareTo(Employee o) {
    if (this.name.equals(o.getName())) {
      return -1; //return 0 says that two objects are same 
    } else {
      return 1;  
    }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM