Esercizio per comprendere l' uso HashSet<T>

di il
3 risposte

Esercizio per comprendere l' uso HashSet<T>

Ho svolto il seguente esercizio pero' ancora non capito bene l'interfaccia HashSet<T>.

L'esercizio e' il seguente e in allegato il file .jpg dove ho eseguito l'implementazione e la prova del programma .

Ho aggiunto dei commenti teorici su informazioni riguardanti l'interfaccia HashSet<T>.

Ho racchiuso il programma in un package e creato un main con due classi .

Il main si chiama ProveHashSet e le due classi rispettivamente Evento.java e Catastrofe.java.

IL problema e' che non ho capito fino in fondo cosa fa questo programma.

Il programma dovrebbe escludere da un insieme di numeri gli elementi uguali .

Dal risultato sembrerebbe che nell'anno 2000 ci sono stati un evento e due Catastrofi .

Pero' sembra non aver senso questo risultato semmai il contrario .

Voi cosa ne pensate ?







/* Obiettivo: comprensione uso HashSet<T>

La HashSet e' una delle nove interfacce disponibili nel Framwork collctions del package java.util.
L'interfaccia SET ammette oggetti [ non duplicati] identificabili univocamente tramite il metodo equals()
SET astrae il concetto di insieme matematico

- cosa stampa questo programma?

run:

set1.size()=1
set2.size()=2
BUILD SUCCESSFUL (total time: 0 seconds)

- compilare

compilazione OK

- eseguire il programma e verificare la propria risposta

*/
import java.util.*;
class Catastrofe {
private int anno;
Catastrofe(int anno) {
this.anno = anno;
}
}
class Evento {
private int anno;
Evento (int anno) {
this.anno = anno;
}
public int hashCode() {
return this.anno;
}
public int getAnno() {
return this.anno;
}
public boolean equals(Object o) {
Evento e = (Evento) o;
return this.anno == e.getAnno();
}
}
public class ProveHashSet {
public static void main(String[] argv) {
Set<Evento> set1 = new HashSet<Evento>(); // interfaccia HashSet vincolata alla classe Evento che contiene oggetti di tipo stato .
// set soddisfano una condizione, cioè se hanno una variabile booleana settata a true
Evento e = new Evento(2000); // Istanzio e inizializzo 'e'
set1.add(e); // add aggiunge elementi
e = new Evento(2000);
set1.add(e);

Set<Catastrofe> set2 = new HashSet<Catastrofe>(); // interfaccia HashSet vincolata alla classe Catastrofe verifica se nel 2000 ci sono
// state alluvione
Catastrofe c = new Catastrofe(2000);
set2.add(c);
c = new Catastrofe(2000);
set2.add(c);
System.out.println("set1.size()="+set1.size()); // Size ci indica la dimensione della nostra lista
System.out.println("set2.size()="+set2.size());
}
}
Allegati:
21412_2784fa25b35d472c2e9afb25aaac5a70.jpg
21412_2784fa25b35d472c2e9afb25aaac5a70.jpg

21412_ac5d49f553a07014e7d59485e4714c82.jpg
21412_ac5d49f553a07014e7d59485e4714c82.jpg

21412_468fef259671af5a35284002aea8e8fd.jpg
21412_468fef259671af5a35284002aea8e8fd.jpg

3 Risposte

  • Re: Esercizio per comprendere l' uso HashSet<T>

    FabioJ ha scritto:


    Ho svolto il seguente esercizio pero' ancora non capito bene l'interfaccia HashSet<T>.

    /* Obiettivo: comprensione uso HashSet<T>

    La HashSet e' una delle nove interfacce disponibili nel Framwork collctions del package java.util.
    L'interfaccia SET ammette oggetti [ non duplicati] identificabili univocamente tramite il metodo equals()
    SET astrae il concetto di insieme matematico
    Set (java.util.Set) è una interfaccia, HashSet (java.util.HashSet) è una classe (non interfaccia) che implementa Set.

    I "set" sono concettualmente degli insiemi di elementi "non duplicati", dal javadoc di Set:

    "A collection that contains no duplicate elements."

    HashSet è una implementazione basata su hash-table interna, vuol dire innanzitutto che il concetto di "non duplicati" si basa sulla appropriata e coerente implementazione di equals() E hashCode() nella classe degli oggetti da inserire nel HashSet.

    FabioJ ha scritto:


    Set<Evento> set1 = new HashSet<Evento>();
    Evento e  = new Evento(2000);
    set1.add(e);
    e = new Evento(2000);
    set1.add(e);
    Dal momento che Evento implementa equals()/hashCode() e rispetta il contratto tra i due metodi, allora la unicità è ben definita. Due oggetti Evento con lo stesso anno sono visti da HashSet come "uguali", pertanto il primo add ha successo (e inserisce materialmente il Evento nel HashSet ) mentre il secondo add semplicemente non fa e non cambia nulla, poiché appunto è ritenuto un "duplicato".

    Nota che il tuo equals NON è perfetto al 100%. Il cast "diretto" ad Evento non va bene. Bisogna sempre prima effettuare il test del tipo e se il Object passato è null oppure non è quanto ci si aspetta, il equals DEVE ritornare false.
    Il equals NON deve mai schiantare con ClassCastException.

    FabioJ ha scritto:


    Set<Catastrofe> set2 = new HashSet<Catastrofe>();
    Catastrofe c = new Catastrofe(2000);
    set2.add(c);
    c = new Catastrofe(2000);
    set2.add(c);
    Dal momento che Catastrofe NON ridefinisce né equals() né hashCode(), rimangono gli equals/hashCode "ereditati" da java.lang.Object, che si basano solo sulla "identità" degli oggetti. Pertanto due oggetti Catastrofe distinti (cioè 2 creati ciascuno con new) sono ritenuti diversi indipendentemente dal loro contenuto.
    Quindi nel secondo HashSet<Catastrofe> vengono inseriti entrambi gli oggetti ANCHE se hanno lo stesso anno.

    Questo infatti è l'errore/problema nel non aver ridefinito equals/hashCode.
  • Re: Esercizio per comprendere l' uso HashSet<T>

    Grazie andbin .

    Comunque non e' proprio di facile comprensione questa classe HashSet.
    Spero che facendo esercizio riesco a capirlo bene.
    Per esempio non riesco a capire la funzione di questo costruttore :

    public boolean equals(Object o) {
    Evento e = (Evento) o;
    return this.anno == e.getAnno();


    Sto' provando a cambiare i parametri per capire le variazioni nella visualizzazione pero' per il momento non mi e' molto chiaro.
    Ho capito solo che restituisce un valore booleano o zero o uno .
  • Re: Esercizio per comprendere l' uso HashSet<T>

    FabioJ ha scritto:


    Comunque non e' proprio di facile comprensione questa classe HashSet.
    Il concetto della unicità, ovvero del "non duplicati" per HashSet l'ho spiegato (e credo bene) prima.

    FabioJ ha scritto:


    Per esempio non riesco a capire la funzione di questo costruttore :
    public boolean equals(Object o) {
    	  Evento e = (Evento) o;
    	  return this.anno == e.getAnno();
    In generale equals serve per determinare se due oggetti sono di contenuto, significato "equivalente". E si contrappone all'uso dell'operatore di uguaglianza == per i reference per cui a == b è true SOLO se le due variabili a e b fanno riferimento allo stesso identico oggetto (quindi non c'entra il contenuto).

    FabioJ ha scritto:


    Sto' provando a cambiare i parametri
    Se intendi il parametro definito in equals, quello DEVE essere Object. Se metti un tipo diverso da Object es.

    public boolean equals(Evento e)

    allora stai facendo un overload e non un override. Se vuoi ridefinire equals in modo che sia il tuo ad essere invocato invece che quello definito in java.lang.Object devi appunto fare un override e quindi rispettare le regole sul overriding.

    Quindi la forma lecita è:

    public boolean equals(Object)
Devi accedere o registrarti per scrivere nel forum
3 risposte