Set ordinati e no

Da Head First Java O'Reilly, capitolo 16 che tratta collezioni e programmazione generica.

Abbiamo detto che gli elementi di un Set sono unici. Ma dobbiamo specificare cosa si intende essere unico per un elemento.

Due oggetti sono considerati uguali in Java se vale one.equals(two) e one e two hanno il medesimo codice hash, come ritornato dal metodo hashcode(). Perché Set consideri un oggetto come duplicato dobbiamo ridefinire hashCode() e equals() in modo che i due oggetti siano visti come identici.

Per vedere se due reference puntino allo stesso oggetto possiamo usare l'operatore ==.

Dunque, se vogliamo poter usare la classe Song che abbiamo visto in questo post in un Set dobbiamo ridefinire il modo in cui due oggetti di tipo Song sono riconosciuti come identici. Aggiungeremo perciò la ridefinizione per il metodo equals() e hashCode() in questo modo:

public class Song implements Comparable<Song> {

private String title;
private String artist;
private int rating;

// ...

@Override
public boolean equals(Object o) {
if(o instanceof Song) {
Song s = (Song) o;
return s.title.equals(title) && s.artist.equals(artist);
}
return false;
}

@Override
public int hashCode() {
return title.hashCode() + artist.hashCode();
}

// ...
}

Data questa classe Song, possiamo riscrivere il nostro JukeBox per fare in modo che accetti in input una lista di brani non unici ma la collezione risultante contenga solo elementi unici.

Dobbiamo di nuovo prendere la decisione se vogliamo che la nostra collezione sia ordinata o meno. Se non siamo interessati all'ordinamento ci conviene usare HashSet, altrimenti TreeSet ci permette di mantenere la nostra collezione ordinata, al costo di un leggero aggravio dei tempi d'uso.
Nell'esempio che segue usiamo entrambi gli approcci:

package Chap16;

import java.util.*;

public class JukeBoxC {
private HashSet<Song> hs = new HashSet<Song>();
private TreeSet<Song> ts = new TreeSet<Song>();

public JukeBoxC() {
getSongs();
System.out.println(hs);
System.out.println(ts);
}

private void getSongs() {
// fake implementation
String[] fakeList = {"Pink Moon/Nick Drake/5", "Somersault/Zero 7/4",
"Shiva Moon/Prem Joshua/5", "Circles/BT (Brian Wayne Transeau)/3",
"Deep Channel/Afro Celts/3", "Passenger/Headmix/4",
"Pink Moon/Nick Drake/5", "Listen/Tahiti 80/3", "Listen/Tahiti 80/3"};
for(String s : fakeList) {
System.out.println(s);
String[] tokens = s.split("/");

int rating = Integer.parseInt(tokens[2]);
Song aSong = new Song(tokens[0], tokens[1], rating);
if(hs.add(aSong) == false) {
System.out.println("Duplicated song discarded");
}
ts.add(aSong);
}
}

public static void main(String[] args) {
new JukeBoxC();
}
}

Nessun commento:

Posta un commento