2013-05-23 5 views
0

Я пытаюсь сохранить набор возможных вариантов и исключить дубликаты, поэтому я храню выбор, который я сделал в 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 
     } 
    } 

} 

} 
+1

Похоже, что использование [Point] (http://docs.oracle.com/javase/7/docs/api/java/awt/Point.html) может удовлетворить ваши потребности. – Dukeling

+0

Не понимаю.Почему вы не можете просто создать новый класс с парой 'int'? –

+0

Я не знал, что существует, но в этом случае да, я могу пойти с этим. Благодарю. Тем не менее, мне все еще хотелось бы ответить на этот вопрос – Daniel

ответ

2

В Java, hashCode() и equals(Object) идут вместе. Если вы переопределите один, вы должны переопределить другой. Когда Java ищет объект в HashSet, он сначала вычисляет hashCode, чтобы определить, в каком ведре может быть найден объект. Затем он использует equals(Object), чтобы узнать, имеет ли объект этот объект. Кроме того, изменение объекта, находящегося в HashSet, приведет к проблемам, так как оно может оказаться в неправильном ведре и больше не будет найдено.

Вы можете написать свой собственный неизменный класс, Position, который содержит конструктор, A position и depth переменных, добытчик, equals(Object) и hashCode(). Члены массивов Integer[] имеют смысл, поэтому вы должны, вероятно, указать их явно.

1

Проблема в том, что equals() для Array проверяет, являются ли массивы одного и того же экземпляра. В вашем случае они, вероятно, нет. См. Хороший вопрос и ответы here.

Ваш HashSet вызовет equals() для всех элементов в наборе, поэтому он вернет false, если все массивы не совпадают.

Возможно, изменение массива на List будет работать, поскольку оно проверяет, что все содержащиеся элементы равны друг другу. Для Integer s это, конечно, работает.

Я бы, однако, реализовал свой класс. Если у вас нет таких ограничений, вы должны это сделать.

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.

Смежные вопросы