How to split an HashMap in Java
Solution 1
Do you have to use HashMap
?
TreeMap
is really good for this kind of things. Here's an example (note that 0, 50, and 99 are map keys, not indices):
TreeMap<Integer, Integer> sorted = new TreeMap<Integer, Integer>(bigMap);
SortedMap<Integer, Integer> zeroToFortyNine = sorted.subMap(0, 50); // toKey inclusive, fromKey exclusive
SortedMap<Integer, Integer> fiftyToNinetyNine = sorted.subMap(50, true, 99, true);
Solution 2
You'll basically need to iterate over the entries in bigMap
, and make a decision as to whether they should be added to smallMap1
or smallMap2
.
Solution 3
As the HashMap
is unordered (entries may come in any order), it makes no sense to exactly split it. We can simply use the alternating boolean flag.
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;
}
Solution 4
Here are two simple methods to split the map by,
size of the partition or
number of partitions
/** * * @param bulkyMap - your source map to be partitioned * @param batchSize - partition size * @return */ public List<Map<String, Object>> getMiniMapsInFixedSizeBatches(Map<String, Object> bulkyMap, int batchSize) { if (batchSize >= bulkyMap.size() || batchSize <= 0) { return Arrays.asList(bulkyMap); } List<Map<String, Object>> batches = new ArrayList<>(); int innerBatchcount = 1; int count = 1; Map<String, Object> tempMap = new HashMap<>(); for (Map.Entry<String, Object> entry : bulkyMap.entrySet()) { tempMap.put(entry.getKey(), entry.getValue()); innerBatchcount++; count++; if (innerBatchcount > batchSize || count > bulkyMap.size()) { innerBatchcount = 1; Map<String, Object> batchedMap = new HashMap<>(); batchedMap.putAll(tempMap); batches.add(batchedMap); tempMap.clear(); } } return batches; } /** * the number of partitions is not always guaranteed as the algorithm tries to optimize the number of partitions * @param bulkyMap - your source map to be partitioned * @param numPartitions - number of partitions (not guaranteed) * @return */ public List<Map<String, Object>> getMiniPartitionedMaps(Map<String, Object> bulkyMap, int numPartitions) { int size = bulkyMap.size(); int batchSize = Double.valueOf(Math.ceil(size * 1.0 / numPartitions)).intValue(); return getMiniMapsInFixedSizeBatches(bulkyMap, batchSize); }
Solution 5
Iterate over the bigMap
with for (Entry<Integer, Integer> entry : bigMap.entrySet())
, and increment an i
to check whether you have to add the entry in the first small map or in the second one.
RNO
Updated on July 23, 2022Comments
-
RNO almost 2 years
I was wondering if it is possible to split a HashMap into smaller sub-maps.
In my case I have a HashMap of 100 elements and I would like to create 2 (or more) smaller HashMaps from the original one, the first containing the Entries from 0 to 49, the second containing the Entries from 50 to 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>();
Any suggestions? Many thanks!
-
amphibient over 11 yearsor set a threshold and iterate to it, moving an entry from big to small each iteration
-
Oliver Charlesworth over 11 years@foampile: A threshold? What do you mean? (Remember that a hash-map isn't sorted)
-
amphibient over 11 yearsiterate up to a certain number of iterations, e.g. 50% rounded up to the next int of the original size. but even if it is not sorted, he is moving entries, i.e. putting them in new, deleting from old, so it is safe. so when he iterates again, the moved entries won't be there in the old
-
sharakan over 11 yearshuh? on a HashMap wouldn't this just arbitrarily pick every other entry?
-
Oliver Charlesworth over 11 years@foampile: Oh, I see. I had misread the OP's question. I assumed that (s)he wanted to filter the entries based on their values. But it sounds like they actually just want 50% to go one way, and 50% the other.
-
Audrius Meškauskas over 11 yearsThere is no such thing as the order of entries in HashMap. If the order is important for your task, use LinkedHashMap and then of course it must be a different algorithm.
-
RNO over 11 yearsI don't know why you received some downvote, I have chosen your answer because it does not waste much memory. The TreeMap enabled me to efficiently achieve what I wanted. P.S. I should have specified that the result should have been performing, and your suggestion it was. Thanks again
-
Shane over 10 yearsIn this answer's current state items 49 and 99 will not be included in either map, because the toKey argument of SortedMap's subMap method is exclusive. Why they didn't include an inclusive version I have no idea.
-
Shane over 10 yearsWhat you probably want is Java 6's NavigableMap, which includes subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive);
-
sharakan over 10 years@Shane Thanks for the pointer, fixed the indexing. Note that TreeMap is a NavigableMap, so that method exists on TreeMap as well.
-
Olivier Faucheux over 9 yearsThis answer will only work with a map having as keys the numbers from 0 to 99. The parameters of method
subMap(a,b)
does not refers to the number of elements but to the values of the keys.If your maps contains the 100 numbers from 500 to 599,subMap(0,49)
will be empty, as well alssubMap(50,99)
. The only full map would besubMap(100, 99999999)
. -
sharakan over 9 years@OlivierFaucheux That's correct, I made a simplifying assumption given that the OP didn't specify the actual values of the keys. The specific constants I selected also wouldn't work with negative ranges, wouldn't simply translate to non-contiguous ranges etc. Safe to say I didn't solve every problem, but I did provide an answer to his problem.
-
Fabrice TIERCELIN about 8 yearsThis answer is confusing: it does not take the indices of entries into account but directly the keys. It can't be called a solution to split a map.
-
vkrishna17 over 7 yearsWhat if I don't consider ordering, its just that i want to split Map into smaller maps. How can I do it ?