Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[Java] containsKey van HashMap geeft incorrect resultaat

Pagina: 1
Acties:

  • Gummbahla
  • Registratie: Februari 2003
  • Laatst online: 05-11 10:50
Ik ben bezig met een stukje software dat MP3's scanned en vervolgens een HashMap oplevert met als key een instantie van mijn klasse Album, als value een HashSet met de bestandslocaties van MP3's die bij het betreffende album behoren.
Nu wil ik natuurlijk dat alle bestanden van hetzelfde album ook onder dezelfde key in de HashMap komen. Ik check dus voordat ik een bestandslocatie toevoeg aan mn HashMap of er al een ander bestand van hetzelfde album in de HashMap voorkomt:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//...
HashMap collection = new HashMap<Album,HashSet<String>>();

for(Mp3File f : files){
    HashSet h = null;

    String artist = f.getArtist();
    String albumname = f.getAlbumname();
    Album a = new Album(artist,albumname);

    if(collection.containsKey(a)){
        h = collection.get(a);
    }else{
        h = new HashSet();
    }
    h.add(filename);
    collection.put(h);
}


Omdat HashMap bij containsKey gebruik maakt van de hashcode() methode van Album, override ik deze:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Album{

private String artist;
private String album;

public Album(String artist,String album){
    this.artist = artist;
    this.album = album;
}

public String toString(){
    return "Album:"+this.album+",Artist:"+this.artist;
}

public boolean equals(Album a){
    return this.toString().equals(a.toString());
}

public int hashCode(){
    return this.toString().hashCode();
}

}


Controle tijdens het debuggen bevestigd dat bestanden die bij hetzelfde album horen, dezelfde hashcode opleveren wanneer HashMap.containsKey() wordt aangeroepen. Toch is het resultaat altijd false, waardoor ik een vrij nutteloze HashMap krijg met een groot aantal dubbele keys.

Voorbeeldje bij 6 MP3's uit twee verschillende albums ('Idealism' en 'Moshi Moshi'):

Verwacht resultaat voor 'collection':
code:
1
2
3
4
{
"Album:Idealism,Artist:Digitalism"=[file1,file2,file3,file4]
"Album:Moshi Moshi,Artist:Digitalism"=[file5,file6]
}


Daadwerkelijk resultaat
code:
1
2
3
4
5
6
7
8
{
"Album:Idealism,Artist:Digitalism"=[file1]
"Album:Idealism,Artist:Digitalism"=[file2]
"Album:Idealism,Artist:Digitalism"=[file3]
"Album:Idealism,Artist:Digitalism"=[file4]
"Album:Moshi Moshi,Artist:Digitalism"=[file5]
"Album:Moshi Moshi,Artist:Digitalism"=[file6]
}


Iemand enig idee hoe dat komt...en hoe ik het kan oplossen?

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Je code klopt niet, want je doet collection.put(h) wat niet kan met een Map.

In ieder geval, het probleem is volgens mij dat je een nieuwe equals hebt gemaakt (nl equals(Album) ipv de bestaande equals te overriden (nl equals(Object)).
Als je dus containsKey gebruikt dan klopt de Hash misschien wel, maar dan is het object niet hetzelfde (er wordt namelijk de default implementatie van Object gebruikt die de identiteit gebruikt), de HashMap benadert alles, dus ook equals, via de interface van Object en heeft dus geen boodschap aan jouw nieuwe methode.

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Remus schreef op zondag 26 oktober 2008 @ 10:18:
In ieder geval, het probleem is volgens mij dat je een nieuwe equals hebt gemaakt (nl equals(Album) ipv de bestaande equals te overriden (nl equals(Object)).
Als je dus containsKey gebruikt dan klopt de Hash misschien wel, maar dan is het object niet hetzelfde (er wordt namelijk de default implementatie van Object gebruikt die de identiteit gebruikt), de HashMap benadert alles, dus ook equals, via de interface van Object en heeft dus geen boodschap aan jouw nieuwe methode.
Scherp, ik had hem gemist. Het is inderdaad een klassieke valkuil: equals(Album) is een overload, geen override. Het feit dat de compiler niet roept dat de @Override annotatie ontbreekt is een belangrijke aanwijzing ;)

[ Voor 6% gewijzigd door Confusion op 26-10-2008 10:37 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • Gummbahla
  • Registratie: Februari 2003
  • Laatst online: 05-11 10:50
Ahh..heel scherp inderdaad, dat ik daar de hele tijd overheen heb gekeken... Hulde! _/-\o_
offtopic:
En uiteraard, collection.put(h) had natuurlijk collection.put(a, h) moeten zijn.