2011-11-30 18 views
5

Tôi đang cố thêm các mục nhập vào một hàm có thể bắt đầu bằng Java bằng Eclipse. Trong quá trình đặt, chỉ một khóa được ghi đè bằng một khóa và giá trị mới. Số đếm của hashtable được duy trì đúng cách nhưng một trong các cặp (khóa, giá trị) bị mất.Java Hashtable ghi đè khóa hiện có bằng khóa mới trong khi 'đặt'

Đây là mẫu mã của tôi:

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

Tôi đã sử dụng để inbuilt 'hashcode' và 'bằng' phương pháp trong nhật thực để so sánh các đối tượng lớp.

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 

Tại sao phím được xóa ở đó ngay lập tức cụ thể.?

[sửa] hashCode và equals: Tôi sử dụng Eclipse để tự động nhập những phương pháp // (x, y) là (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; 
} 

}

+2

gì hashCode của bạn và bằng làm gì? – Thilo

+0

Lớp "Val" là gì? Nó giống như "K"? – dmeister

+0

Vâng. lấy làm tiếc. Lớp Val là lớp K – SyncMaster

Trả lời

6

Vấn đề là bạn đang sử dụng trình gỡ lỗi để kiểm tra nội dung của HashMap.

Tôi giả định rằng cả hai phím (1,2) và (7,8) được lưu trong cùng một khe của HashTable được sử dụng để lưu khóa.Khi (7,8) được thêm vào, (1,2) được chuyển đến "mặt sau" (7,8) - bạn phải kiểm tra mục nhập next của mục nhập (7,8).

enter image description here

thêm dòng sau vào cuối của mã của bạn để xem những gì thực sự là trong HashMap:

for (Val key : numbers.keySet()) { 
     System.out.printf("%.1f %.1f: %s%n", key.x, key.y, numbers.get(key)); 
    } 
+1

Tốt bắt rằng sử dụng một trình gỡ lỗi để kiểm tra một HashMap có thể không trực quan. –

1

Hãy chắc chắn rằng băm và bằng nhau là đáp ứng yêu cầu của họ.

Có một mã băm duy nhất cho mỗi trường hợp và bằng sẽ là true nếu chúng chỉ bằng nhau. Sai tích cực có nghĩa là các giá trị dương tính giả ánh xạ tới cùng một khóa. See this link.

2

Sumindra ở trên có nghĩa là bạn muốn sử dụng lớp tùy chỉnh làm khóa trong Bản đồ, bạn phải có phương thức equals() và hashCode() được viết như được chỉ định. Làm sau đây (ví dụ:

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

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

này đảm bảo rằng:

  • hai K đối tượng retuyrn bằng nhau nếu chúng có cùng các thành viên
  • hai K đối tượng có hashCode tương tự nếu họ có các thành viên cùng

Đó là một yêu cầu cho đồ vật chủ chốt.

+0

Ngay cả với mã bạn đã đề cập, cùng một vấn đề xảy ra. tức là hai đối tượng K trở lại bằng nhau cho các thành viên khác nhau. Tôi có nên viết phương pháp khác đi không? Tôi không thể tìm thấy bất kỳ lý do gì tại sao nó mang lại giá trị giống nhau cho các thành viên khác nhau ngay cả khi sử dụng^ – SyncMaster

+1

@SyncMaster hãy cẩn thận rằng hai đối tượng có thể trả lại cùng một 'hashCode' và vẫn khác nhau! Ví dụ: Chuỗi có thể có nhiều bit hơn mã băm, sẽ không thể có các mã duy nhất tuyệt vời cho mọi Chuỗi. Trong trường hợp của bạn, hai đôi có nhiều bit hơn dài (kiểu trả về hashCode) –

+0

@CarlosHeuberger: Vì vậy, cách tốt hơn để xử lý các trường hợp như vậy là viết mã băm thích hợp của riêng tôi? – SyncMaster

1

Tôi không thể tái tạo vấn đề của bạn, đây là mã EXACT tôi đang chạy (không được đơn giản hóa như các câu trả lời khác để làm cho câu trả lời gần nhất có thể với câu hỏi ban đầu của bạn).

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

Kết quả tôi nhận được từ khai thác gỗ là

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] 

Đó không phải là những gì bạn mong muốn?

Các câu trả lời khác có điểm tốt về việc đơn giản hóa hashCode và bằng. Ngoài ra, bạn không cần phải làm toString() trên đối tượng đã là chuỗi.

Các vấn đề liên quan