Avatar billede junl Nybegynder
20. maj 2006 - 01:26 Der er 11 kommentarer og
1 løsning

Hashtable problemer (igen)

Nu har jeg nok brug for arne_v's hjælp igen.

Jeg gemmer objekter i en hashtable. Hvert objekt indeholder et 3*3 array, der repræsenterer et kryds og bolle bræt. Til hvert objekt hører der en key (som bruges i forbindelse med hashtabellen). Key'ens hashcode udregnes ved at repræsentere brættet som en streng f.eks. "000111033" hvor 0 er et tomt felt, 1 er en bolle og 3 er et kryds - det er så denne strengs hashcode der bliver key'ens hashcode. Jeg ved ikke om det er den korrekte måde at gøre det på - men problemet er:

Jeg tester om et givet objekt findes i hashtabellen og får returneret true. Herefter henter jeg objektet ud og så tester jeg om key'en på det objekt jeg spurgte på og det objekt jeg har hentet er ens (det burde de vel være) - nogle gange er de ikke ens!

Jeg har debugget mig igennem og for mig ser det ud som om, at hashtabellen gemmer objekter (med forskellige keys) på samme plads - hvilket jo er fint nok. Men med get() burde jeg vel få præcis det objekt jeg spørger efter - der burde vel traverseres over de objekter der ligger på samme plads i hashtabellen og returneres det korrekt.

Men jeg gør noget forkert - for jeg får ofte det forkerte af de objekter der ligger på samme plads (de har jo forskellige keys).

Nogen ideér til hvad jeg gør forkert?
Avatar billede arne_v Ekspert
20. maj 2006 - 02:58 #1
er din equals implementeret rigtig ?
Avatar billede junl Nybegynder
20. maj 2006 - 09:31 #2
Det er den sandsynligvis ikke - her er mit key objekt:

public class Key  implements Serializable{
  private String code;

  public Key(String h) {
    code = h;
  }

  public boolean equals(Object key) {
    if (this.getCode().equals(((Key) key).getCode())){
      return true;
    }
    else
      return false;
  }

  public int hashCode() {
    int hash = code.hashCode();
    return hash;
  }

  public String getCode(){
    return code;
  }
}

Så jeg bruger faktisk Strings equals.
Avatar billede junl Nybegynder
20. maj 2006 - 11:47 #3
Det er i denne stump kode, at det går galt:

Key tmpKey = tmpBoard.getKey();
          if (scoreDB.exists(tmpKey) == true) {
            tmpBoard = scoreDB.getBoard(tmpKey);
            if(!tmpKey.equals(tmpBoard.getKey()))
              System.out.println("Asked for key: " + tmpKey.getCode() + " but got key: " + tmpBoard.getKey().getCode());
Avatar billede arne_v Ekspert
20. maj 2006 - 14:59 #4
hvordan ser exists og getBoard ud ?
Avatar billede junl Nybegynder
20. maj 2006 - 15:49 #5
De ser sådan her ud:

public void addBoard(Board board) {
  db.put(board.getKey(), board);
}

public boolean exists(Key key) {
  return db.containsKey(key);
}
Avatar billede junl Nybegynder
20. maj 2006 - 16:03 #6
Altså - jeg har fundet problemet (sådan da). Det er helt korrekt at jeg får tilføjet et board til hashtabellen hvor key'en ikke passer til udseendet, men jeg kan ikke se hvordan det kan ske. Når jeg adder til hashtabellen, kalder jeg getKey i board'et:
  public Key getKey() {
    Key key = new Key();
    key.setCode(createCode());
    return key;
  }

getKey laver et nyt key objekt og sætter koden i keyen (ny implementering):

public class Key  implements Serializable{
  private String code;

  public Key() {
  }

  public boolean equals(Object key) {
    if (this.getCode().equals(((Key) key).getCode()) && this.hashCode() == key.hashCode()){
      return true;
    }
    else
      return false;
  }

  public int hashCode() {
    int hash = code.hashCode();
    return hash;
  }
 
  public void setCode(String c){
    code = c;
    hashCode();
  }
 
  public String getCode(){
    return code;
  }
}

Dvs. bør key objektet ikke altid være opdatereret, med den nyeste kode - når jeg kalder metoden getKey i board objektet, når jeg tilføjer til hashtabellen?
Avatar billede arne_v Ekspert
21. maj 2006 - 04:41 #7
(irrelevant for problemet: du behøver ikke teste på hashCode i equals)
Avatar billede arne_v Ekspert
21. maj 2006 - 04:44 #8
der foregår et eller andet spooky

du genbruger ikke Board eller Key objekter ufrivilligt ?

man gemmer jo kun en reference i Hashtable ikke en kopi af objektet
Avatar billede junl Nybegynder
21. maj 2006 - 12:16 #9
Jeg havde indsat testen på hashcoden i mit desperate forsøg på at finde fejlen :-)
Her er et screenshot af en fejlmapping: http://www.masu.dk/Screenshot.png

Jeg tager kopier af de objekter jeg gemmer i hashtabellen - kan det være problemet? Kopi metoden ser sådan her ud:

  public Board copy() {   
    byte[][] posCopy = new byte[3][3];
    for (int x = 0; x < 3; x++) {
      for (int y = 0; y < 3; y++) {
        posCopy[x][y] = pos[x][y];
      }
    }
    Board b = new Board(posCopy);
    b.setScore(score);
    b.setWin(win);
    return b;
  }

win og score er henholdsvis en double og en int.
Avatar billede junl Nybegynder
21. maj 2006 - 20:16 #10
Jo - der var et enkelt lille møgsted, hvor jeg fik spillet videre på et board, efter at det var tilføjet til hashtabellen. Øv - men det er rettet nu.
Avatar billede junl Nybegynder
21. maj 2006 - 20:22 #11
Nå men så er der point til dig igen arne. Bare lig et svar.
Avatar billede arne_v Ekspert
21. maj 2006 - 22:15 #12
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester