A un certo punto del mio codice, ho creato un Set<Map.Entry<K, V>>
da una mappa. Ora voglio ricreare la stessa forma della mappa, quindi voglio convertire lo HashSet<Map.Entry<K, V>>
in uno HashMap<K, V>
. Java ha una chiamata nativa per farlo, o devo scorrere gli elementi del set e costruire manualmente la mappa?Converti Set <Map.Entry <K, V>> a HashMap <K, V>
risposta
Non vi è alcuna API incorporata in java per la conversione diretta tra HashSet
e HashMap
, è necessario scorrere il set e utilizzare Entry
compilare la mappa.
un approccio:
Map<Integer, String> map = new HashMap<Integer, String>();
//fill in map
Set<Entry<Integer, String>> set = map.entrySet();
Map<Integer, String> mapFromSet = new HashMap<Integer, String>();
for(Entry<Integer, String> entry : set)
{
mapFromSet.put(entry.getKey(), entry.getValue());
}
Anche se quello che è lo scopo qui, se fate eventuali cambiamenti Set
che rifletteranno anche nel Map
come set restituito da Map.entrySet
è backup Map
. Vedere javadoc
di seguito:
Impostare < Entry < Integer, String >> java.util.Map.entrySet()
Restituisce una vista Set delle mappature contenute in questa mappa. Il set è supportato dalla mappa, quindi le modifiche alla mappa si riflettono nel set e viceversa. Se la mappa viene modificata mentre un'iterazione sul set è in corso (tranne tramite l'operazione di rimozione dell'iteratore o tramite l'operazione setValue su una voce della mappa restituita dall'iteratore ) i risultati dell'iterazione non sono definiti. Il set supporta la rimozione degli elementi , che rimuove la mappatura corrispondente dalla mappa, tramite le operazioni Iterator.remove, Set.remove, removeAll, retainAll e clear . Non supporta le operazioni add o addAll.
Soluzione Java 8 discretamente breve. Può far fronte a chiavi duplicate.
Map<Integer, String> map = new HashMap<>();
//fill in map
Set<Map.Entry<Integer, String>> set = map.entrySet();
Map<Integer, String> mapFromSet = set.stream().collect(Collectors.toMap(Entry::getKey,
Entry::getValue,
(a,b)->b));
Edit: grazie a shmosel che merita più credito di me per questo
No. Il tuo BiConsumer non combina le mappe. – Joe
Nel codice precedente, il metodo di accettazione di BiConsumer non viene mai chiamato. Avrei preferito utilizzare null, ma il metodo di raccolta genera stupidamente un NPE in quel caso. – mikeyreilly
@mikeyreilly, [la documentazione] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util .function.BiConsumer-java.util.function.BiConsumer-) non dice esplicitamente che il combinatore non viene mai chiamato per il flusso sequenziale. Quindi violi semplicemente il contratto del metodo. –
In Java 8 con corretta combinatore
Map<Integer, String> map = new HashMap<>();
//fill in map
Set<Map.Entry<Integer, String>> set = map.entrySet();
Map<Integer, String> mapFromSet =set.stream().collect(HashMap::new,(t, u) -> t.put(u.getKey(), u.getValue()),
(Map mapToReturn, Map otherMap) ->
{
otherMap.entrySet().forEach((Map.Entry entry) -> {
mapToReturn.put(entry.getKey(),entry.getValue());
});
return mapToReturn;}););
Java-8 soluzione più semplice che coinvolge Collectors.toMap
:
Map<Integer, String> mapFromSet = set.stream()
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Viene generato un IllegalStateException
se d si trova la chiave uplicate.
Cosa sono gli NPE se qualche valore è nullo? –
Come di Guava 19 è possibile utilizzare ImmutableMap.copyOf(Iterable<Map.Entry<K,V>>)
Come di Java 9, abbiamo Map.ofEntries. Prendono solo le voci come array, quindi è necessario convertirle prima con toArray()
e buttare fuori le informazioni sul tipo.
@SuppressWarnings("unchecked")
(Map.Entry<K, V>[] array = entrySet.toArray((Map.Entry<K, V>[])new Map.Entry<?, ?>[entrySet.size()]);
Map<K, V> map = Map.ofEntries(array);
I comuni Apache hanno metodi simili.di ArrayUtils.toMap Commons Lang:
Map<Object, Object> map = ArrayUtils.toMap(entrySet.toArray());
// to recover the type...
@SuppressWarnings("unchecked")
Map<K, V> typedMap = (Map<K, V>)(Map<?, ?>)map;
Commons Collezioni MapUtils.putAll:
Map<K, V> map = MapUtils.putAll(new HashMap<K, V>(), entrySet.toArray());
Come hai creato 'set' da' Map', usando la logica chiave o un valore o personalizzato? inoltre non esiste un metodo 'nativo' per' HashSet' su 'HashMap'. È necessario iterare e utilizzare una logica mentre si inserisce in 'HashMap' come si sceglie la chiave e il valore. – harsh
@Paul grazie ora la domanda è chiara. – harsh
Non penso che Map.Entry debba essere usato in questo modo. L'implementazione utilizzata da 'HashMap' sovrascrive' hashCode' e 'equals' per esempio? –