Java Hashtable перезаписывает существующий ключ новым ключом во время 'put' - PullRequest
5 голосов
/ 30 ноября 2011

Я пытаюсь добавить записи в хеш-таблицу в Java, используя Eclipse. Во время операции put только один ключ перезаписывается новым ключом и значением. Счет хеш-таблицы поддерживается должным образом, но одна из пар (ключ, значение) потеряна.

Вот мой пример кода:

ArrayList<Double> list;
Hashtable<Val,ArrayList<Double>> numbers = new Hashtable<Val,ArrayList<Double>>();

while((line = brMyHashval.readLine()) != null)
{
    if(!(line.isEmpty()))
    {               
        String[] temp;
        temp = line.split(" ");      
        eDouble = Double.parseDouble(temp[2].toString());

        Val key = new Val(Double.parseDouble(temp[0].toString()) ,Double.parseDouble(temp[1].toString()) );

        if(!(numbers.containsKey(key)))
        {
            list = new ArrayList<Double>();
            numbers.put(key, list);

        }
        else
        {
            list = numbers.get(key);
        }
        list.add(eDouble); 
     }
}

Я использовал встроенный метод 'hashcode' и 'equals' в eclipse для сравнения объектов класса.

Входной текстовый файл:

1.0 2.0 9.0
3.0 4.0 9.0
5.0 6.0 9.0
1.0 2.0 8.0
5.0 6.0 8.0
1.0 2.0 7.0
**7.0 8.0 7.0** // After this point a new hash entry gets added for key(7,8), But key (1,2) get deleted from the hashtable, though count gets increased to 4.
3.0 4.0 7.0
5.0 6.0 10.0
1.0 2.0 10.0
1.0 3.0 10.0
1.0 4.0 10.0

Почему ключ удаляется в этот конкретный момент .?

[править] хэш-код и равно: я использовал eclipse для автоматического импорта этих методов // (x, y) есть (a, b)

  class Val

{
    double x;
    double y;

Val(double X, double Y)
{
    x = X;
    y = Y;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(x);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    temp = Double.doubleToLongBits(y);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Val other = (Val) obj;
    if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
        return false;
    if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
        return false;
    return true;
}

}

Ответы [ 4 ]

6 голосов
/ 30 ноября 2011

Проблема в том, что вы используете отладчик для проверки содержимого HashMap.

Я предполагаю, что оба ключа (1,2) и (7,8) сохранены в том же слоте HashTable, который использовался для сохранения ключей. По мере добавления (7,8), (1,2) перемещается в «спину» (7,8) - вы должны проверить запись next (7,8).

enter image description here

добавьте следующее в конец вашего кода, чтобы увидеть, что действительно находится в HashMap:

    for (Val key : numbers.keySet()) {
        System.out.printf("%.1f %.1f: %s%n", key.x, key.y, numbers.get(key));
    }
2 голосов
/ 30 ноября 2011

Sumindra выше означает, что если вы хотите использовать пользовательский класс в качестве ключа на карте, вы должны иметь методы equals () и hashCode (), записанные в соответствии с указаниями Выполните следующие действия (например:

public boolean equals(K other) {
    return a == other.a && b == other.b;
}

public int hashCode() {
    return new Double(a).hashCode() ^ new Double(b).hashCode();
}

это гарантирует, что:

  • два K объекта retuyrn равны, если они имеют одинаковые члены
  • два K объекта имеют одинаковый hashCode, если они имеют одинаковые члены

Что является обязательным требованием для ключевых объектов карты.

1 голос
/ 30 ноября 2011

Я не могу воспроизвести вашу проблему, это ТОЧНЫЙ код, который я запускаю (не упрощенный, как другие ответы, чтобы сделать его как можно ближе к вашему первоначальному вопросу).

public class HashProblem {

    public static class Val {
        private double x;
        private double y;

        public Val(double x, double y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            long temp;
            temp = Double.doubleToLongBits(x);
            result = prime * result + (int) (temp ^ (temp >>> 32));
            temp = Double.doubleToLongBits(y);
            result = prime * result + (int) (temp ^ (temp >>> 32));
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Val other = (Val) obj;
            if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
                return false;
            if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
                return false;
            return true;
        }
    }

    public static void main(String... args) throws Exception {
        ArrayList<Double> list;
        String line;
        BufferedReader brMyHashval = new BufferedReader(new InputStreamReader(new FileInputStream("HashProblem.txt")));
        Hashtable<Val, ArrayList<Double>> numbers = new Hashtable<Val, ArrayList<Double>>();

        while ((line = brMyHashval.readLine()) != null) {
            if (!(line.isEmpty())) {
                String[] temp;
                temp = line.split(" ");
                Double eDouble = Double.parseDouble(temp[2].toString());

                Val key = new Val(Double.parseDouble(temp[0].toString()), Double.parseDouble(temp[1].toString()));

                if (!(numbers.containsKey(key))) {
                    list = new ArrayList<Double>();
                    numbers.put(key, list);
                    System.err.println("Created " + key.x + " " + key.y);
                } else {
                    list = numbers.get(key);
                }
                list.add(eDouble);
                System.err.println("Inserted into " + key.x + " " + key.y + " value " + eDouble + " size " + list.size() + " " + list);
            }
        }
    }

ВыводЯ получаю из журнала:

Created 1.0 2.0
Inserted into 1.0 2.0 value 9.0 size 1 [9.0] 
Created 3.0 4.0
Inserted into 3.0 4.0 value 9.0 size 1 [9.0]
Created 5.0 6.0
Inserted into 5.0 6.0 value 9.0 size 1 [9.0]
Inserted into 1.0 2.0 value 8.0 size 2 [9.0, 8.0]
Inserted into 5.0 6.0 value 8.0 size 2 [9.0, 8.0]
Inserted into 1.0 2.0 value 7.0 size 3 [9.0, 8.0, 7.0]
Created 7.0 8.0
Inserted into 7.0 8.0 value 7.0 size 1 [7.0]
Inserted into 3.0 4.0 value 7.0 size 2 [9.0, 7.0]
Inserted into 5.0 6.0 value 10.0 size 3 [9.0, 8.0, 10.0]
Inserted into 1.0 2.0 value 10.0 size 4 [9.0, 8.0, 7.0, 10.0]
Created 1.0 3.0
Inserted into 1.0 3.0 value 10.0 size 1 [10.0]
Created 1.0 4.0
Inserted into 1.0 4.0 value 10.0 size 1 [10.0]

Разве это не то, что вы ожидаете?

В других ответах есть хорошие замечания об упрощении вашего хэш-кода и равных.Кроме того, вам не нужно делать toString () для объекта, который уже является строкой.

1 голос
/ 30 ноября 2011

Убедитесь, что хеш и их эквиваленты соответствуют их требованиям.

Для каждого экземпляра должен быть уникальный хеш, и значение equals должно быть истинным, если они равны. Ложные положительные значения означают, что ложные положительные значения отображаются на один и тот же ключ. Смотрите эту ссылку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...