Perché java.util.Set non ha ottenuto (int index)?

Sono sicuro che c’è una buona ragione, ma qualcuno potrebbe spiegare perché manca l’interfaccia java.util.Set get(int Index) o un metodo get() simile?

Sembra che gli insiemi siano ottimi per inserire le cose, ma non riesco a trovare un modo elegante per recuperare un singolo elemento da esso.

Se so che voglio il primo elemento, posso usare set.iterator().next() , ma per il resto sembra che devo eseguire il cast su una matrice per recuperare un elemento in un indice specifico?

Quali sono i modi appropriati per recuperare i dati da un set? (diverso dall’uso di un iteratore)

Sono sicuro che il fatto che sia escluso dall’API significa che c’è una buona ragione per non farlo – qualcuno potrebbe per favore illuminarmi?

EDIT: alcune risposte estremamente grandi qui, e alcuni dicono “più contesto”. Lo scenario specifico era un test dbUnit, in cui potevo ragionevolmente affermare che il set restituito da una query aveva solo 1 elemento e stavo tentando di accedere a quell’elemento.

Tuttavia, la domanda è più valida senza lo scenario, in quanto rimane più focalizzata:

Qual è la differenza tra set e lista .

Grazie a tutti per le fantastiche risposte qui sotto.

Perché gli insiemi non hanno ordine. Alcune implementazioni (in particolare quelle che implementano l’interfaccia java.util.SortedSet ), ma questa non è una proprietà generale dei set.

Se stai cercando di utilizzare i set in questo modo, dovresti prendere in considerazione l’utilizzo di un elenco.

In realtà questa è una domanda ricorrente durante la scrittura di applicazioni JavaEE che usano Object-Relational Mapping (per esempio con Hibernate); e da tutte le persone che hanno risposto qui, Andreas Petersson è l’unico che ha capito il vero problema e ha offerto la risposta corretta ad esso: Java manca a UniqueList! (oppure puoi anche chiamarlo OrderedSet o IndexedSet).

Maxwing ha menzionato questo caso d’uso (nel quale avete bisogno di dati AND ordinati e unici) e ha suggerito l’SortedSet, ma questo non è ciò di cui Marty Pitt aveva veramente bisogno.

Questo “IndexedSet” NON è lo stesso di un SortedSet – in un SortedSet gli elementi sono ordinati usando un Comparator (o usando il loro ordinamento “naturale”).

Ma è più vicino a un LinkedHashSet (che altri hanno suggerito), o ancora più a un “ArrayListSet” (anche inesistente), perché garantisce che gli elementi vengano restituiti nello stesso ordine in cui sono stati inseriti.

Ma LinkedHashSet è un’implementazione, non un’interfaccia! È necessaria un’interfaccia IndexedSet (o ListSet, o OrderedSet o UniqueList)! Ciò consentirà al programmatore di specificare che ha bisogno di una raccolta di elementi che hanno un ordine specifico e senza duplicati e quindi di istanziarlo con qualsiasi implementazione (ad esempio un’implementazione fornita da Hibernate).

Dato che JDK è open-source, forse questa interfaccia sarà finalmente inclusa in Java 7 …

Aggiungendo solo un punto che non è stato menzionato nella risposta di mmyers .

Se so che voglio il primo elemento, posso usare set.iterator (). Next (), ma per il resto sembra che devo eseguire il cast su una matrice per recuperare un elemento in un indice specifico?

Quali sono i modi appropriati per recuperare i dati da un set? (diverso dall’uso di un iteratore)

Dovresti anche familiarizzare con l’interfaccia SortedSet (la cui implementazione più comune è TreeSet ).

Un SortedSet è un Set (cioè gli elementi sono unici) che viene mantenuto ordinato dall’ordinamento naturale degli elementi o usando un Comparator . Puoi facilmente accedere al primo e all’ultimo object usando i metodi first() e last() . Un SortedSet è utile ogni tanto, quando è necessario mantenere la raccolta sia libera da duplicare sia ordinata in un determinato modo.

Modifica : se hai bisogno di un Set i cui elementi sono tenuti in ordine di inserzione (proprio come un elenco), dai un’occhiata a LinkedHashSet .

Questo tipo di porta alla domanda quando dovresti usare un set e quando dovresti usare una lista. Di solito, il consiglio va:

  1. Se hai bisogno di dati ordinati, usa una lista
  2. Se hai bisogno di dati unici, usa un Set
  3. Se è necessario entrambi, utilizzare uno: SortedSet (per i dati ordinati dal comparatore) o OrderedSet / UniqueList (per i dati ordinati per inserimento). Sfortunatamente l’API Java non ha ancora OrderedSet / UniqueList.

Un quarto caso che appare spesso è che non hai bisogno di nessuno dei due. In questo caso vedi alcuni programmatori andare con le liste e alcuni con i set. Personalmente trovo molto dannoso vedere set come una lista senza ordini – perché è davvero tutta un’altra bestia. A meno che tu non abbia bisogno di cose come l’unicità dell’insieme o l’eguaglianza, preferisci sempre le liste.

Non sono sicuro che qualcuno lo abbia scritto esattamente in questo modo, ma è necessario comprendere quanto segue:

Non esiste un “primo” elemento in un set.

Perché, come altri hanno già detto, gli insiemi non hanno ordine. Un set è un concetto matematico che specificamente non include l’ordinamento.

Naturalmente, il tuo computer non può davvero tenere una lista di cose che non sono ordinate in memoria. Deve avere qualche ordine. Internamente è un array o una lista collegata o qualcosa del genere. Ma tu non sai veramente cosa sia, e in realtà non ha un primo elemento; l’elemento che esce “prima” viene fuori per caso, e potrebbe non essere la prima volta la prossima volta. Anche se hai preso le misure per “garantire” un particolare primo elemento, esso viene comunque fuori per caso, perché ti è capitato di farlo bene per una particolare implementazione di un Set; una diversa implementazione potrebbe non funzionare in questo modo con quello che hai fatto. E, in effetti, potresti non conoscere l’implementazione che stai utilizzando così come pensi di fare.

Le persone si imbattono in questo TUTTO. IL. TEMPO. con i sistemi RDBMS e non capisco. Una query RDBMS restituisce un set di record. Questo è lo stesso tipo di set di matematica: una collezione non ordinata di elementi, solo che in questo caso gli elementi sono record. Un risultato della query RDBMS non ha alcun ordine garantito a meno che non si utilizzi la clausola ORDER BY, ma per tutto il tempo si presume che funzioni e si riprenda un giorno quando la forma dei propri dati o codice cambia leggermente e triggers il Query Optimizer per funzionare in un modo diverso e improvvisamente i risultati non escono nell’ordine che si aspettano. Queste sono in genere le persone che non hanno prestato attenzione nella class del database (o durante la lettura della documentazione o delle esercitazioni) quando gli è stato spiegato, in anticipo, che i risultati della query non hanno un ordine garantito.

alcune strutture dati mancano dalle collezioni standard Java.

Borsa (come set ma può contenere elementi più volte)

UniqueList (elenco ordinato, può contenere ciascun elemento solo una volta)

sembra che tu abbia bisogno di un univoco in questo caso

se hai bisogno di strutture dati flessibili, potresti essere interessato a Google Collections

È vero, l’elemento in Set non è ordinato, per definizione della Set Collection. Quindi non possono accedere a un indice.

Ma perché non abbiamo un metodo get (object), non fornendo l’indice come parametro, ma un object che è uguale a quello che stiamo cercando? In questo modo, possiamo accedere ai dati dell’elemento all’interno del Set, solo conoscendo i suoi attributi usati dal metodo uguale.

Se hai intenzione di fare molti accessi casuali per indice in un set, puoi ottenere una vista in array dei suoi elementi:

 Object[] arrayView = mySet.toArray(); //do whatever you need with arrayView[i] 

Ci sono due svantaggi principali però:

  1. Non è efficiente in termini di memoria, poiché è necessario creare un array per l’intero set.
  2. Se l’insieme viene modificato, la vista diventa obsoleta.

Questo perché Set garantisce solo l’unicità, ma non dice nulla sull’accesso ottimale o sui modelli di utilizzo. Cioè, un Set può essere una Lista o una Mappa, ognuna delle quali ha caratteristiche di recupero molto diverse.

L’unica ragione per cui posso pensare di usare un indice numerico in un set sarebbe per l’iterazione. Per quello, usa

 for(A a : set) { visit(a); } 

Mi sono imbattuto in situazioni in cui volevo effettivamente un set ordinato con accesso tramite indice (concordo con altri poster che non hanno senso accedere a un set non ordinato con un indice). Un esempio potrebbe essere un albero in cui volevo che i bambini fossero ordinati e che i bambini duplicati non erano ammessi.

Avevo bisogno dell’accesso tramite indice per visualizzarli e gli attributi dell’insieme sono stati utili per eliminare in modo efficiente i duplicati.

Non trovando alcuna raccolta adatta nelle raccolte java.util o google, ho trovato semplice implementarla da solo. L’idea di base è di racchiudere un SortedSet e creare un Elenco quando è richiesto l’accesso tramite indice (e si dimentica l’elenco quando viene modificato il SortedSet). Questo ovviamente funziona in modo efficiente solo quando si modifica l’SortedSet spostato e l’accesso alla lista è separato nel corso della vita della Raccolta. Altrimenti si comporta come una lista ordinata spesso, cioè troppo lenta.

Con un numero elevato di bambini, questa prestazione è migliorata molto rispetto a un elenco che ho tenuto in ordine tramite Collections.sort.

Si prega di notare solo 2 struttura dei dati di base è ansible accedere tramite indice.

  • È ansible accedere alla struttura dati dell’array tramite indice con complessità temporale O(1) per ottenere un’operazione get(int index) .
  • La struttura dei dati di LinkedList è accessibile anche tramite l’indice, ma con la complessità del tempo O(n) per ottenere l’operazione get(int index) .

In Java, ArrayList viene implementato utilizzando la struttura dati Array .

Mentre la struttura dei dati Set di solito può essere implementata tramite la struttura dati HashTable / HashMap o BalancedTree , per rilevare rapidamente se un elemento esiste e aggiungere elementi non esistenti, in genere un Set ben implementato può raggiungere O(1) complessità temporale contains operazioni. In Java, HashSet è l’implementazione utilizzata più comunemente di Set , viene implementata chiamando HashMap API HashMap e HashMap viene implementato utilizzando il concatenamento separato con elenchi collegati (una combinazione di Array e LinkedList ).

Poiché Set può essere implementato tramite una diversa struttura dati, non esiste get(int index) metodo get(int index) per esso.

Puoi fare un new ArrayList(set).get(index)

Il motivo per cui l’ interfaccia Set non ha una chiamata di tipo index get o anche qualcosa di ancora più elementare, come first () o last (), è perché è un’operazione ambigua e quindi un’operazione potenzialmente pericolosa. Se un metodo restituisce un Set, e tu chiami, dicci metodo first (), qual è il risultato atteso, dato che un Set generico non garantisce l’ordine? L’object risultante potrebbe benissimo variare tra ogni chiamata del metodo, o potrebbe non esserlo e farti cullare da un falso senso di sicurezza, finché la libreria che stai usando cambia le modifiche sotto l’implementazione e ora trovi che tutte le tue interruzioni di codice per nessun motivo particolare

I suggerimenti sui rimedi qui elencati sono buoni. Se hai bisogno di accesso indicizzato, usa un elenco. Prestare attenzione nell’usare iteratori o toArray con un Set generico, perché a) non vi è alcuna garanzia sull’ordinazione e b) non vi è alcuna garanzia che l’ordine non cambierà con invocazioni successive o con diverse implementazioni sottostanti. Se hai bisogno di qualcosa in mezzo, un SortedSet o un LinkedHashSet è quello che vuoi.

// Vorrei che l’interfaccia Set avesse un elemento get-random.

java.util.Set è una raccolta di elementi non ordinati. Non ha alcun senso se il Set ha un get (indice int), perché Set non ha un indice e anche tu puoi solo indovinare il valore.

Se vuoi davvero questo, codifica un metodo per ottenere elementi casuali da Set.

Se non ti dispiace che il set sia ordinato, potresti essere interessato a dare un’occhiata al progetto della mappa ad albero indicizzato .

Il TreeSet / TreeMap avanzato fornisce l’accesso agli elementi per indice o ottenere l’indice di un elemento. E l’implementazione si basa sull’aggiornamento dei pesi del nodo nell’albero RB. Quindi nessuna iterazione o backup da un elenco qui.

Prova questo codice come opzione alternativa per accedere attraverso gli indici

 import java.io.*; import java.util.*; class GFG { public static void main (String[] args) { HashSet  mySet=new HashSet(); mySet.add(100); mySet.add(100); int n = mySet.size(); Integer arr[] = new Integer[n]; arr = mySet.toArray(arr); System.out.println(arr[0]); } } 

Questo stamperà 100.

Per ottenere un elemento in un Set, io uso il seguente:

 public T getElement(Set set, T element) { T result = null; if (set instanceof TreeSet) { T floor = ((TreeSet) set).floor(element); if (floor != null && floor.equals(element)) result = floor; } else { boolean found = false; for (Iterator it = set.iterator(); !found && it.hasNext();) { if (true) { T current = it.next(); if (current.equals(element)) { result = current; found = true; } } } } return result; }