2013-04-19 16 views
17

W pewnym momencie w moim kodzie utworzyłem Set<Map.Entry<K, V>> z mapy. Teraz chcę odtworzyć ten sam formularz mapy, więc chcę przekonwertować HashSet<Map.Entry<K, V>> z powrotem na HashMap<K, V>. Czy Java ma natywne wezwanie do robienia tego, czy też muszę zapętlić ustawione elementy i ręcznie zbudować mapę?Konwertuj zestaw <Map.Entry <K, V>> na HashMap <K, V>

+0

Skąd stworzony '' Map' Set' z logiką, używając klucza lub wartości lub niestandardowy? poza tym nie ma "natywnej" metody dla 'HashSet' na' HashMap'. Musisz przejść do iteracji i użyć jakiejś logiki podczas wstawiania do 'HashMap' sposobu wyboru klucza i wartości. – harsh

+0

@Paul dziękuję teraz pytanie brzmi jednoznacznie – harsh

+1

Nie sądzę, że 'Map.Entry' ma być używany w ten sposób. Czy implementacja używana na przykład przez 'HashMap' nadpisuje' hashCode' i 'equals'? –

Odpowiedz

17

Nie ma wbudowany interfejs API w Java dla bezpośredniej konwersji pomiędzy HashSet i HashMap, trzeba wykonać iterację zestaw i korzystania Entry wypełnić mapie.

jedno podejście:

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()); 
    } 

Choć Jaki jest cel tutaj, jeśli nie żadnych zmian w Set że odbije się także w Map jako zbioru zwróconego przez Map.entrySet jest tworzenie kopii zapasowych przez Map. Zobacz javadoc poniżej:

Ustaw < Wstęp < Integer, String >> java.util.Map.entrySet()

zwraca zestaw widok mapowania zawartych w tej mapie. Zbiór jest wspierany przez mapę, więc zmiany na mapie są odzwierciedlone w zestawie i na odwrót. Jeśli mapa zostanie zmodyfikowana, gdy trwa iteracja nad zestawem, to w toku (z wyjątkiem operacji usuwania iteratora lub poprzez operację setValue na pozycji mapy zwróconej przez iterator ) wyniki iteracji są niezdefiniowane. Zestaw obsługuje usuwanie elementu , który usuwa odpowiednie mapowanie z mapy, za pomocą operacji Iterator.remove, Set.remove, removeAll, retainAll i clear . Nie obsługuje operacji dodawania ani dodawania.

1

Dość krótkie rozwiązanie Java 8. Może poradzić sobie z duplikatami kluczy.

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: dzięki shmosel kto zasługuje na więcej punktów niż ja w tym

+0

Nie. Twój BiConsumer nie łączy map. – Joe

+0

W powyższym kodzie metoda akceptacji BiConsumer nigdy nie jest wywoływana. Wolałbym użyć wartości NULL, ale metoda zbierania głupio wyrzuca NPE w tym przypadku. – mikeyreilly

+1

@mikeyreilly, [dokumentacja] (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-) nie mówi wprost, że kombinator nigdy nie jest wywoływany dla strumienia sekwencyjnego. W ten sposób po prostu naruszysz umowę z tą metodą. –

0

w Java 8 z prawidłowym sumator

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;});); 
26

Prostsze-8 Java rozwiązanie obejmujące Collectors.toMap:

Map<Integer, String> mapFromSet = set.stream() 
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 

An IllegalStateException zostanie wyrzucony, jeśli d pojawia się klucz uplicate.

+0

co aboug NPEs, jeśli dowolna wartość jest null? –

0

Jako Java 9, mamy Map.ofEntries. Biorą one jednak tylko wpisy jako tablice, więc musisz je najpierw przekonwertować z toArray() i wyrzucić informacje o typie.

@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); 

Apache Commons ma podobne metody.Fotografia Langa ArrayUtils.toMap:

Map<Object, Object> map = ArrayUtils.toMap(entrySet.toArray()); 

// to recover the type... 
@SuppressWarnings("unchecked") 
Map<K, V> typedMap = (Map<K, V>)(Map<?, ?>)map; 

Commons Collections' MapUtils.putAll:

Map<K, V> map = MapUtils.putAll(new HashMap<K, V>(), entrySet.toArray()); 
Powiązane problemy