Vorrei convertire un array in un set in Java. Ci sono alcuni modi ovvi per farlo (cioè con un ciclo) ma vorrei qualcosa di un po 'più ordinato, qualcosa del tipo:
java.util.Arrays.asList(Object[] a);
Qualche idea?
Vorrei convertire un array in un set in Java. Ci sono alcuni modi ovvi per farlo (cioè con un ciclo) ma vorrei qualcosa di un po 'più ordinato, qualcosa del tipo:
java.util.Arrays.asList(Object[] a);
Qualche idea?
Risposte:
Come questo:
Set<T> mySet = new HashSet<>(Arrays.asList(someArray));
In Java 9+, se il set non modificabile è ok:
Set<T> mySet = Set.of(someArray);
In Java 10+, il parametro di tipo generico può essere dedotto dal tipo di componente array:
var mySet = Set.of(someArray);
Arrays.asList
è O (1).
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);
Quello è Collections.addAll (java.util.Collection, T ...) da JDK 6.
Inoltre: cosa succede se il nostro array è pieno di primitivi?
Per JDK <8, scriverei semplicemente il for
ciclo ovvio per eseguire il wrapping e aggiungere il set in un passaggio.
Per JDK> = 8, un'opzione interessante è qualcosa di simile:
Arrays.stream(intArray).boxed().collect(Collectors.toSet());
java.util.Collections.addAll
. Inoltre, non consiglierei più le Collezioni Commons, cosa che non viene generata e che Guava esiste.
addAll
sarà O ( n ).
Con Guava puoi fare:
T[] array = ...
Set<T> set = Sets.newHashSet(array);
new HashSet<T>(Arrays.asList(someArray))
. Vedi google.github.io/guava/releases/19.0/api/docs/com/google/common/…
Java 8:
String[] strArray = {"eins", "zwei", "drei", "vier"};
Set<String> strSet = Arrays.stream(strArray).collect(Collectors.toSet());
System.out.println(strSet);
// [eins, vier, zwei, drei]
Abbiamo anche la possibilità di utilizzare Stream
. Possiamo ottenere lo streaming in vari modi:
Set<String> set = Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new));
System.out.println(set);
String[] stringArray = {"A", "B", "C", "D"};
Set<String> strSet1 = Arrays.stream(stringArray).collect(Collectors.toSet());
System.out.println(strSet1);
// if you need HashSet then use below option.
Set<String> strSet2 = Arrays.stream(stringArray).collect(Collectors.toCollection(HashSet::new));
System.out.println(strSet2);
Il codice sorgente Collectors.toSet()
mostra che gli elementi vengono aggiunti uno alla volta a un HashSet
ma la specifica non garantisce che sarà un HashSet
.
"Non ci sono garanzie sul tipo, la mutabilità, la serializzabilità o la sicurezza del thread del set restituito."
Quindi è meglio usare l'opzione successiva. L'output è:
[A, B, C, D]
[A, B, C, D]
[A, B, C, D]
Java 9 introdotto Set.of
metodo factory statico che restituisce un set immutabile per gli elementi forniti o l'array.
@SafeVarargs
static <E> Set<E> of(E... elements)
Controllare i metodi di fabbrica statici impostati immutabili per i dettagli.
Possiamo anche ottenere un set immutabile in due modi:
Set.copyOf(Arrays.asList(array))
Arrays.stream(array).collect(Collectors.toUnmodifiableList());
Il metodo Collectors.toUnmodifiableList()
utilizza internamente Set.of
introdotto in Java 9. Controlla anche questa mia risposta per ulteriori informazioni.
Stream.of()
- Non lo sapevo. Un piccolo cavillo su Collectors.toSet()
: dici che la specifica non garantisce l'aggiunta di elementi uno per uno, ma è questo che significa: "accumula ... in un nuovo Set
". Ed è più leggibile, quindi preferibile a me, se non hai bisogno delle garanzie di tipo concreto, mutabilità, serializzazione e sicurezza dei thread.
HashSet
. Garantisce solo che sarà un Set
e questo è ciò che intendo. Spero di averlo chiarito.
Dopo averlo fatto Arrays.asList(array)
puoi eseguireSet set = new HashSet(list);
Ecco un metodo di esempio, puoi scrivere:
public <T> Set<T> GetSetFromArray(T[] array) {
return new HashSet<T>(Arrays.asList(array));
}
Nelle raccolte Eclipse , funzionerà quanto segue:
Set<Integer> set1 = Sets.mutable.of(1, 2, 3, 4, 5);
Set<Integer> set2 = Sets.mutable.of(new Integer[]{1, 2, 3, 4, 5});
MutableSet<Integer> mutableSet = Sets.mutable.of(1, 2, 3, 4, 5);
ImmutableSet<Integer> immutableSet = Sets.immutable.of(1, 2, 3, 4, 5);
Set<Integer> unmodifiableSet = Sets.mutable.of(1, 2, 3, 4, 5).asUnmodifiable();
Set<Integer> synchronizedSet = Sets.mutable.of(1, 2, 3, 4, 5).asSynchronized();
ImmutableSet<Integer> immutableSet = Sets.mutable.of(1, 2, 3, 4, 5).toImmutable();
Nota: sono un committer per le raccolte Eclipse
Rapidamente: puoi fare:
// Fixed-size list
List list = Arrays.asList(array);
// Growable list
list = new LinkedList(Arrays.asList(array));
// Duplicate elements are discarded
Set set = new HashSet(Arrays.asList(array));
e per invertire
// Create an array containing the elements in a list
Object[] objectArray = list.toArray();
MyClass[] array = (MyClass[])list.toArray(new MyClass[list.size()]);
// Create an array containing the elements in a set
objectArray = set.toArray();
array = (MyClass[])set.toArray(new MyClass[set.size()]);
Ho scritto quanto segue dai consigli sopra - rubalo ... è bello!
/**
* Handy conversion to set
*/
public class SetUtil {
/**
* Convert some items to a set
* @param items items
* @param <T> works on any type
* @return a hash set of the input items
*/
public static <T> Set<T> asSet(T ... items) {
return Stream.of(items).collect(Collectors.toSet());
}
}
C'è stato un sacco di grandi risposte già, ma la maggior parte di essi non funziona con array di primitive (come int[]
, long[]
, char[]
,byte[]
, etc.)
In Java 8 e versioni successive, è possibile eseguire il box dell'array con:
Integer[] boxedArr = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Quindi converti in set usando stream:
Stream.of(boxedArr).collect(Collectors.toSet());
A volte l'utilizzo di alcune librerie standard aiuta molto. Prova a guardare le collezioni Apache Commons . In questo caso i tuoi problemi si trasformano semplicemente in qualcosa del genere
String[] keys = {"blah", "blahblah"}
Set<String> myEmptySet = new HashSet<String>();
CollectionUtils.addAll(pythonKeywordSet, keys);
Ed ecco le CollezioniUtils javadoc
java.util.Collections.addAll(myEmptySet, keys);
??
Usa CollectionUtils
o ArrayUtils
dastanford-postagger-3.0.jar
import static edu.stanford.nlp.util.ArrayUtils.asSet;
or
import static edu.stanford.nlp.util.CollectionUtils.asSet;
...
String [] array = {"1", "q"};
Set<String> trackIds = asSet(array);
In Java 10 :
String[] strs = {"A", "B"};
Set<String> set = Set.copyOf(Arrays.asList(strs));
Set.copyOf
restituisce un non modificabile Set
contenente gli elementi del dato Collection
.
Il dato Collection
non deve essere null
e non deve contenere alcun null
elemento.
private Map<Integer, Set<Integer>> nobreaks = new HashMap();
nobreaks.put(1, new HashSet(Arrays.asList(new int[]{2, 4, 5})));
System.out.println("expected size is 3: " +nobreaks.get(1).size());
l'uscita è
expected size is 3: 1
cambiarlo in
nobreaks.put(1, new HashSet(Arrays.asList( 2, 4, 5 )));
l'uscita è
expected size is 3: 3
Per chiunque risolva per Android:
L'asterisco *
è l' spread
operatore. Applica tutti gli elementi in una raccolta singolarmente, ciascuno passato in ordine a un vararg
parametro di metodo. È equivalente a:
val myArray = arrayOf("data", "foo")
val mySet = setOf(*myArray)
// Equivalent to
val mySet = setOf("data", "foo")
// Multiple spreads ["data", "foo", "bar", "data", "foo"]
val mySet = setOf(*myArray, "bar", *myArray)
Passando senza parametri si setOf()
ottiene un set vuoto.
Inoltre setOf
, puoi anche utilizzare uno di questi per un tipo di hash specifico:
hashSetOf()
linkedSetOf()
mutableSetOf()
sortableSetOf()
Ecco come definire esplicitamente il tipo di elemento di raccolta.
setOf<String>()
hashSetOf<MyClass>()
new HashSet<Object>(Arrays.asList(Object[] a));
Ma penso che questo sarebbe più efficiente:
final Set s = new HashSet<Object>();
for (Object o : a) { s.add(o); }
HashSet
viene impostata in base alla dimensione dell'array, ad esempio.
Set<T> b = new HashSet<>(Arrays.asList(requiredArray));