Qual è la differenza quando crei SetT in java [closed]

0

Quando si crea un Set in Java, qual è la differenza tra quanto segue? Quale dovrei usare e perché?

Set< T > set = new HashSet<>();

HashSet< T > set = new HashSet<>();
    
posta jason 13.10.2017 - 03:58
fonte

2 risposte

6

Nella programmazione orientata agli oggetti, esiste un concetto di "programmazione in un'interfaccia". L'idea è che non ti interessa davvero quale tipo di set usi, solo che soddisfa il contratto dell'interfaccia Set (o List o Map ).

I tuoi esempi non mostrano realmente i vantaggi del primo esempio, ma prendi in considerazione questo codice:

public class Example {
  public HashSet<String> doSomething() {
    final HashSet<String> set = new HashSet<>();
    // do stuff with the set
    return set;
  }
}

Usi questa classe dappertutto. Ci sono tonnellate di riferimenti e il codice in più posizioni deve memorizzare il risultato di tale metodo in un riferimento HashSet<String> .

Oops, ora i requisiti cambiano e l'ordine è importante. HashSet non garantisce l'ordine di iterazione, ora è necessario un TreeSet . Quindi aggiorni il metodo per usare TreeSet . Tranne ora hai un sacco di riferimenti che devono essere aggiornati. Forse il tuo IDE può aggiornarlo per te: forse hai utenti esterni della classe e questo creerà mal di testa per loro.

Un'alternativa migliore è quella di codice in un'interfaccia . Invece di definire l'implementazione nel metodo signature e body, usa plain% Set . Se il contratto del metodo è che restituisce un set ordinato, restituisce un SortedSet . Se gli utenti del set hanno bisogno non solo dell'ordine, ma c'è anche la garanzia che un iteratore possa navigare nel set, restituire un NavigableSet .

public class Example {
  public SortedSet<String> doSomething() {
    final SortedSet<String> set = new TreeSet<>();
    // do stuff with the set
    return set;
  }
}

Il framework delle collezioni Java include interfacce per la maggior parte delle implementazioni comuni. L'interfaccia Map ha sottointerfacce che rispecchiano le interfacce impostate che ho già menzionato (ha senso, perché gli insiemi delegano internamente alle mappe). Le liste sono un'eccezione ( ArrayList implementa RandomAccess , un'interfaccia marcatore), ma le code (incluso LinkedList ) hanno diverse interfacce.

Ad ogni modo, il codice all'interfaccia di livello più alto che puoi. Se un utente della tua interfaccia desidera solo eseguire l'iterazione, quindi memorizza un riferimento a tale insieme in Collection o anche Iterable , isolandolo dalle modifiche dell'interfaccia in seguito.

    
risposta data 13.10.2017 - 05:05
fonte
0

La risposta di @Snowman è corretta per il caso generale. La maggior parte delle volte è corretto codificare su un'interfaccia, per le ragioni che ha indicato.

Tuttavia, ci sono casi in cui non lo si desidera, poiché l'implementazione sottostante può fare una grande differenza per le prestazioni.

Considera il caso di un List<E> che elabori utilizzando List.get(int) e List.set(int, E) . Sebbene queste operazioni siano disponibili per tutte le implementazioni di List , produrranno un'enorme differenza nelle prestazioni, sia che tu stia lavorando su ArrayList o su LinkedList .

In questo caso potresti definire che il tuo metodo accetta solo ArrayList come parametro. Oppure puoi accettare List e quindi creare un ArrayList da esso per l'elaborazione.

Quindi la risposta è, dipende. Nella maggior parte dei casi, codifica un'interfaccia, ma quando è necessario, non aver paura di specificare il tipo esatto che ti aspetti.

    
risposta data 13.10.2017 - 11:26
fonte

Leggi altre domande sui tag