2013-01-31 6 views
7

Zastanawiam się, czy możliwe jest podzielenie HashMap na mniejsze pod-mapy.Jak podzielić HashMap w Javie

W moim przypadku mam HashMap 100 elementów i chciałbym utworzyć 2 (lub więcej) mniejszych HashMaps z oryginalnego, pierwszego zawierającego Wpisy od 0 do 49, drugiego zawierającego Wpisy od 50 do 99.

Map <Integer, Integer> bigMap = new HashMap <Integer, Integer>(); 

//should contains entries from 0 to 49 of 'bigMap' 
Map <Integer, Integer> smallMap1 = new HashMap <Integer, Integer>(); 


//should contains entries from 50 to 99 of 'bigMap' 
Map <Integer, Integer> smallMap2 = new HashMap <Integer, Integer>(); 

Jakieś sugestie? Wielkie dzięki!

Odpowiedz

12

Czy musisz użyć HashMap?

TreeMap jest naprawdę dobre dla tego rodzaju rzeczy. Oto przykład.

TreeMap<Integer, Integer> sorted = new TreeMap<Integer, Integer>(bigMap); 

SortedMap<Integer, Integer> zeroToFortyNine = sorted.subMap(0, 50); 
SortedMap<Integer, Integer> fiftyToNinetyNine = sorted.subMap(50, 100); 
+0

dziękuję Spróbuję, aby – RNO

+2

dół opieki nad komentarzem, dlaczego to nie jest dobra odpowiedź? – sharakan

+0

Nie wiem, dlaczego otrzymałeś jakieś poparcie, wybrałem twoją odpowiedź, ponieważ nie marnuje ona dużo pamięci. TreeMap umożliwił mi sprawne osiągnięcie tego, co chciałem. P.S. Powinienem był sprecyzować, że wynik powinien być spełniony, a twoja sugestia tak. Jeszcze raz dziękuję – RNO

3

Będziesz musiał powtórzyć wpisy w pozycji bigMap i podjąć decyzję, czy należy je dodać do smallMap1 lub smallMap2.

+0

lub ustawić próg i iteracyjne do niego, poruszając się wpis z dużych do małych każdy iteracja – amphibient

+0

@foampile: Próg? Co masz na myśli? (Pamiętaj, że mapa mieszająca nie jest sortowana) –

+0

iterować do pewnej liczby iteracji, np. 50% zaokrąglone do następnego rozmiaru pierwotnego. ale nawet jeśli nie jest posortowany, przenosi wpisy, czyli umieszcza je w nowych, usuwając stare, więc jest bezpieczny. więc kiedy będzie się ponownie sprawdzał, przeniesione wpisy nie będą tam w starym – amphibient

0
for (Map.Entry<Integer,Integer> entry : bigMap.entrySet()) { 
    // ... 
} 

jest najszybszym sposobem na iterację oryginalnej mapie. Następnie należy użyć klucza Map.Entry, aby zdecydować, która nowa mapa ma zostać wypełniona.

3

Ponieważ pozycja HashMap jest nieuporządkowana (pozycje mogą być w dowolnej kolejności), nie ma sensu dokładnie go podzielić. Możemy po prostu użyć naprzemiennej flagi boolowskiej.

boolean b = false; 
for (Map.Entry e: bigMap.entrySet()) { 
    if (b) 
    smallMap1.put(e.getKey(), e.getValue()); 
    else 
    smallMap2.put(e.getKey(), e.getValue()); 
    b = !b; 
} 
+2

huh? na HashMap nie byłby to arbitralnie wybrać wszystkie inne wpisy? – sharakan

+0

Nie ma czegoś takiego jak kolejność wpisów w HashMap. Jeśli zamówienie jest ważne dla twojego zadania, użyj LinkedHashMap, a następnie oczywiście musi to być inny algorytm. – h22

+0

Co się stanie, jeśli nie będę zamawiał zamówienia, ale chcę podzielić mapę na mniejsze mapy. Jak mogę to zrobić ? – vkrishna17

1

iteracyjne nad bigMap z for (Entry<Integer, Integer> entry : bigMap.entrySet()), a przyrost jest i, by sprawdzić, czy trzeba dodać wpis w pierwszej małej mapie lub w drugim.

1

Oto rozwiązanie z SortedMap:

public static <K, V> List<SortedMap<K, V>> splitMap(final SortedMap<K, V> map, final int size) { 
    List<K> keys = new ArrayList<>(map.keySet()); 
    List<SortedMap<K, V>> parts = new ArrayList<>(); 
    final int listSize = map.size(); 
    for (int i = 0; i < listSize; i += size) { 
     if (i + size < listSize) { 
      parts.add(map.subMap(keys.get(i), keys.get(i + size))); 
     } else { 
      parts.add(map.tailMap(keys.get(i))); 
     } 
    } 
    return parts; 
} 
+0

To zdecydowanie jest idealna odpowiedź .. – Chinni

0

Była to jedna z funkcji, które wykonałem robotę mnie, mam nadzieję, że jej pomocne dla innych. Ta działa niezależnie od obiektu/prymitywu zapisanego jako klucz.

Podejście TreeMap zasugerowano powyżej będzie działać tylko wtedy, gdy klucze są prymitywni, uporządkowane i dokładnie w kolejności indeksu ..

public List<Map<Integer, EnrichmentRecord>> splitMap(Map<Integer, EnrichmentRecord> enrichmentFieldsMap, 
      int splitSize) { 

     float mapSize = enrichmentFieldsMap.size(); 
     float splitFactorF = splitSize; 
     float actualNoOfBatches = (mapSize/splitFactorF); 
     double noOfBatches = Math.ceil(actualNoOfBatches); 



     List<Map<Integer, EnrichmentRecord>> listOfMaps = new ArrayList<>(); 

     List<List<Integer>> listOfListOfKeys = new ArrayList<>(); 


     int startIndex = 0; 
     int endIndex = splitSize; 

     Set<Integer> keys = enrichmentFieldsMap.keySet(); 
     List<Integer> keysAsList = new ArrayList<>(); 
     keysAsList.addAll(keys); 

     /* 
     * Split the keys as a list of keys, 
     * For each key sub list add to a Primary List - listOfListOfKeys 
     */ 
     for (int i = 0; i < noOfBatches; i++) { 
      listOfListOfKeys.add(keysAsList.subList(startIndex, endIndex));   
      startIndex = endIndex; 
      endIndex = (int) (((endIndex + splitSize) > mapSize) ? mapSize : (endIndex + splitSize)); 
     } 

     /** 
     * For Each list of keys, prepare a map 
     * 
     **/ 
     for(List<Integer> keyList: listOfListOfKeys){ 
      Map<Integer,EnrichmentRecord> subMap = new HashMap<>(); 
      for(Integer key: keyList){ 
       subMap.put(key,enrichmentFieldsMap.get(key)); 
      } 
      listOfMaps.add(subMap); 
     } 

     return listOfMaps; 
    }