【问题标题】:HashSet equals, hashCode are overriden, styl have duplicatesHashSet 等于,hashCode 被覆盖,仍然有重复
【发布时间】:2014-02-09 08:43:03
【问题描述】:
 public class DateObj extends Date implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;
    private String fName;
    private String sName;
    private String days;
    private String country;
    private boolean fitIn;


    public DateObj(String id,String fName, String sName, String country, String days) {
        this.id = id;
        this.fName = fName;
        this.sName = sName;
        this.days = days;
        this.country = country;

    }

    @Override
    public boolean equals(Object obj) {

        DateObj dateObj = (DateObj) obj;
        System.out.println("method Call");


        return getfName().equals(dateObj.getfName());
    }

    public String getfName() {
        return fName;
    }

    public void setfName(String fName) {
        this.fName = fName;
    }

    public String getsName() {
        return sName;
    }

    public void setsName(String sName) {
        this.sName = sName;
    }

    public String getDays() {
        return days;
    }

    public void setDays(String days) {
        this.days = days;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String toString(){
        return fName;
    }

@Override
public int hashCode() {
    return fName.hashCode();
}

}

================================================ ============================================

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

public class DataSaveTo {

    private ArrayList<DateObj> listData = new ArrayList<DateObj>();
    File file = new File("data3.csv");
    public static void main(String[] args) {


        DataSaveTo dataExperiment = new DataSaveTo();
        dataExperiment.go();


    }

    public void go() {



        loadData();

        TreeSet<DateObj> data = new TreeSet<DateObj>();
        data.addAll(listData);
    //  ObjComparInt comparId = new ObjComparInt();
    //  ObjectComparable comparObj = new ObjectComparable();
    //  Collections.sort(listData, comparId);
        saveData();
    //  System.out.println(listData);


    }



    public void saveData() {

        try {
            File file = new File("dataNoDupl.csv");
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));
            for(DateObj obj : listData){
                bw.write(obj.getId()+";"+obj.getfName()+";"+obj.getsName()+";"+obj.getCountry()+";"+obj.getDays()+"\n ");
            }
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Exception in save Data method:  "+ e);

        }

    }

    public  void loadData() {
        FileReader fr;
        try {
            fr = new FileReader(file);
            String s = null;
            String[] tokens;
            BufferedReader br = new BufferedReader(fr);
            while((s=br.readLine())!=null){
                tokens = s.split(",");
                createDateObj(tokens);
            }
            br.close();
        } catch (FileNotFoundException e) {
            System.out.println("Exception in LoadData method"+e);
        } catch (IOException e) {
            System.out.println("Exception in LoadData method 2nd catch"+e);
            e.printStackTrace();
        }


    }



    private void createDateObj(String[] tokens) {

        DateObj obj = new DateObj(tokens[4],tokens[0],tokens[2],tokens[3],tokens[1]);
        listData.add(obj);
        System.out.println(obj.hashCode()+"--"+obj.getfName()+"--"+obj.getsName());

    }



    //  Name comparator
    public class ObjectComparable implements Comparator<DateObj>{
        @Override
        public int compare(DateObj obj, DateObj obj1) {
            return obj.getfName().compareTo(obj1.getfName());

        }
    }

        // ID comparator
    public class ObjComparInt implements Comparator<DateObj>{
        @Override   
        public int compare(DateObj ob, DateObj ob1){
            return Integer.parseInt(ob.getId()) - Integer.parseInt(ob1.getId());
            }
        }


    }

我希望 HashSet 调用 equal 方法,因为覆盖了 hashCode。在等于比较之后,我想删除我的集合中的重复项,我传递给了 hashSet。

HashSet<DateObj> data = new HashSet<DateObj>();
    data.addAll(listData);

在控制台中它打印出我,是真的(因为 sys.out 在 equals 方法中)但它没有做任何事情。我有重复的样式。

【问题讨论】:

  • 您的 equals 方法仅使用 fName 字段,而 hashCode 使用 fName 和 sName。不应该重写您的 equals 方法来比较 fName 和 sName 吗??
  • 请阅读 hashcode 和 equals 之间的“契约”。他们必须是等价的!您也可以尝试在 IDE 中重新生成 hashCode 和 equals,然后从那里开始。
  • 编辑您的问题,并添加一些您遇到问题的示例(以及您更新的代码)。另外,请避免使用缩写 - meth != method。
  • 您能否更准确地解释您所期望的结果,以及出了什么问题?

标签: java equals hashcode hashset


【解决方案1】:

具有相同的fName 不会获得相同的哈希值。正如您在生成哈希码时考虑sName 一样。

当您将对象放入您的HashSet 时,会生成哈希码,并且您的哈希码实现会根据您的fNamesName 生成哈希码。另一方面,您在 equal 方法中仅匹配 fName 并打印 true

首先定义您何时想将您的对象视为相同。使用这些标准在equals 方法中进行匹配,并在hashCode 方法中考虑它们。 因为如果两个对象相等,那么它们的哈希码必须相等

【讨论】:

  • 是的,这不是预期的吗?正如您在 equls 方法中所说的那样,考虑具有相同 fName 的对象相同!
  • @user1984327 无论您计划了什么技巧,您的哈希码实现都是错误的。如果您有两个根据 equals 方法相等的对象,则这些对象的哈希码方法必须相同,否则您的哈希码实现被破坏。如果您有例如“Bob Smith”和“Bob Johnson”,它们是相等的,但在您的示例中具有不同的哈希码,这是错误
  • 好吧,恐怕,在这种情况下,您必须编写自己的 HashSet 实现!
  • 好的,对不起,请告诉我我应该在代码中更改什么。我找不到为什么我的风格有重复
【解决方案2】:

hashCode() 的 Java documentation 声明:

如果两个对象根据equals(Object)方法相等,那么 对两个对象中的每一个调用 hashCode 方法必须产生 相同的整数结果。

您的实现违反了此规则,您需要更改 hashCode()equals() 的实现以实现它。

你可能想更新equals()

@Override
public boolean equals(Object obj){
    if (obj == null || !(obj instanceof DateObj)) {
        return false;
    }
    DateObj dateObj = (DateObj) obj;
    return getfName().equals(dateObj.getfName()) && getsName().equals(dateObj.getsName());
}

【讨论】:

  • 实现不需要有意义,它总是可以依赖规范。实际上,快速浏览一下,HashSets 使用 HashMap 将其元素作为键持久化,HashMap.put() 方法需要两个键具有相同的哈希(条件之一)才能认为它们相等。跨度>
猜你喜欢
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 2013-03-15
  • 2013-06-11
  • 1970-01-01
  • 2016-12-19
  • 2011-04-24
  • 1970-01-01
相关资源
最近更新 更多