在没有自定义类的情况下覆盖equals

时间:2013-05-23 13:28:05

标签: java equals contains hashset override

我正在尝试存储一组可能的选择并消除重复,因此我将我在HashSet中所做的选择存储起来。每个步骤我有两个数据,两者的组合不能是唯一的,以便它被认为是重复的(例如[2,0],[0,2],[2,2]都是新的步骤,但后来[2,2]将是重复的)。

我认为我需要覆盖equals才能正确判断该步骤是否已经在HashSet但我没有使用自定义类,只是Integers的数组,所以我发现的大部分内容都不适用(据我所知)。 This seems like it may be useful,建议继承HashSet的可能性,但如果可能,我想避免这种情况。我希望我已经注释掉的equals方法可以工作,但它从未调用过。我是否还需要覆盖hashCode()?我知道它们是齐头并进的。我只需要去写自己的课程,还是有其他方法可以做我想做的事情?

import java.util.HashSet;

public class EP2 {

 public static long count = 0;
 public static HashSet<Integer []> visits = new HashSet<Integer []>();

 //@Override
 //public boolean equals(Object j){     
 // return true;
 //}

 public static void main(String[] args) {

    int position = 0;
    int depth = 0;

    walk(position, depth);
    System.out.println(count);
 }

 public static void walk(int position, int depth){

    count++;

    Integer[] specs = new Integer[2];
    specs[0] = position;
    specs[1] = depth;
    visits.add(specs);


    Integer[] specL = new Integer[]{position - 1, depth+1};
    Integer[] specR = new Integer[]{position + 1, depth+1};


            //doesn't avoid [0,2] duplicates
    if(depth < 2){
        if(!visits.contains(specL)){
            walk(position - 1, depth+1); //walk left
        }
        if(!visits.contains(specR)){
            walk(position + 1, depth+1); //walk right
        }
    }

 }  

}

3 个答案:

答案 0 :(得分:2)

在Java中,hashCode()equals(Object)一起使用。如果覆盖一个,则应覆盖另一个。当Java在HashSet中查找对象时,它首先计算hashCode以确定可以找到该对象的桶。然后它使用equals(Object)来查看该集合是否具有该对象。此外,更改HashSet中的对象会导致问题,因为它可能最终会出现在错误的存储桶中,并且永远不会再被发现。

您可能希望编写自己的不可变类Position,其中包含构造函数,positiondepth变量,getter,equals(Object)和{{1 }}。 hashCode()数组的成员具有意义,因此您应该明确说明这些。

答案 1 :(得分:1)

问题是equals() Array检查数组是否是同一个实例。在你的情况下,他们可能不是。查看一个很好的问题和答案here

您的HashSet将为集合中的所有元素调用equals(),因此除非所有数组都是同一个实例,否则它将返回false

将数组更改为List可能会有效,因为它会检查所有包含的元素是否彼此相等。对于Integer,这当然有效。

但是,我会实现自己的课程。如果您没有任何此类限制,则应该这样做。

答案 2 :(得分:1)

如果您只是想检查重复项,请编写一个自定义方法来检查一个集合是否包含int[]

 public static boolean contains(HashSet<Integer []> set, int[] step) {
     Iterator<Integer []> it = set.iterator();
     boolean flag = false;
     while(it.hasNext()) {
         Integer[] inner = it.next();
         if (step.length == inner.length) {
             for (int i = 0; i < inner.length; i++) {
                 if (inner[i].equals(step[i]))
                     flag = true;
                 else 
                     flag = false;
             }
             if (flag)
                 return true;
         }
     }
     return false;
 }

你应该遵循你的规则。例如,如果您知道数组的大小总是为2,那么您可能不需要进行检查,并且可以快速检查每个数组的相同索引处的每个值。

您可以在想要向Set添加内容时调用此方法。