Как разбить HashMap на Java

мне было интересно, можно ли разделить хэш-карту на более мелкие под-карты.

в моем случае у меня есть хэш-карта из 100 элементов, и я хотел бы создать 2 (или более) меньших хэш-карты из исходного, первый из которых содержит записи от 0 до 49, второй содержит записи от 50 до 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>();

какие предложения? Большое спасибо!

7 ответов


вы должны использовать HashMap?

TreeMap действительно хорошо для такого рода вещей. Вот пример.

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

вам в основном нужно будет перебирать записи в bigMap, и принять решение о том, следует ли их добавлять в smallMap1 или smallMap2.


Как HashMap неупорядочен (записи могут поступать в любом порядке), нет смысла точно разбивать его. Мы можем просто использовать переменный логический флаг.

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

цикл bigMap с for (Entry<Integer, Integer> entry : bigMap.entrySet()), и увеличить i чтобы проверить, нужно ли добавлять запись в первую небольшую карту или во вторую.


вот решение с 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;
}

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

Это самый быстрый способ перебирать исходную карту. Затем вы используете карта.Запись ключ, чтобы решить, какую новую карту для заполнения.


Это была одна из функций, которые сделали работу мне, я надеюсь, что это полезно для других. Это работает независимо от объекта / примитива, хранящегося как ключ.

подход TreeMap, предложенный выше, будет работать только в том случае, если ключи являются примитивами, упорядоченными и в точной последовательности индекса..

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