Как разбить 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;
}