Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Hashtable overwrites existing key with new key during 'put'

Tags:

java

hashtable

I am trying to add entries to an hashtable in Java using Eclipse. During the put operation, only one of the key gets overwriten by a new key and value. The count of the hashtable is maintained properly but one of the (key,value) pair is lost.

Here is my sample code:

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); 
     }
}

I have used to inbuilt 'hashcode' and 'equals' method in eclipse for comparing class objects.

Input Text File:

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

Why does the key get deleted at that specific instant.?

[edit] hashcode and equals: I used eclipse to automatically import these methods // (x,y) is (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;
}

}

like image 444
SyncMaster Avatar asked Dec 28 '22 10:12

SyncMaster


2 Answers

The problem is that you are using the debugger to check the contents of the HashMap.

I assume that both the keys (1,2) and (7,8) are saved in the same slot of the HashTable used to save the keys. As (7,8) get added, (1,2) is moved to the "back" of (7,8) - you must check the next entry of the (7,8) entry.

enter image description here

add the following to the end of your code to see what is really in the HashMap:

    for (Val key : numbers.keySet()) {
        System.out.printf("%.1f %.1f: %s%n", key.x, key.y, numbers.get(key));
    }
like image 52
user85421 Avatar answered Feb 19 '23 20:02

user85421


Sumindra above means that is you want to use a custom class as a key in a Map, you must have the equals() and hashCode() methods written as specified. Do following (for instance:

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

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

this guarantees that:

  • two K objects retuyrn equal if they have the same members
  • two K objects have the same hashCode if they have the same members

Which is a requirement for Map key objects.

like image 28
Hannes R. Avatar answered Feb 19 '23 21:02

Hannes R.