Reputation: 840
I have one hashmap with K, V value of and that I want to split into two subMaps.
HashMap<Long,JSONObject>
One way is this I have found that we can use treemap and do subMapping.
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);
But the thing is I am not getting subMap for jsonObject and I want to do it with HashMap only.
Thanks
Upvotes: 6
Views: 22529
Reputation: 184
You can split a Map into any number of parts by calculating the number of items per partition ("recordsPerChunk").
The following should work.
// number of parts for you is 2
int n = 2;
int size = yourMap.size();
int recordsPerChunk =
(size % n == 0) ?
(size / n) :
((size / n) + 1);
// Counter
AtomicInteger ai = new AtomicInteger();
// List with n chunks
Collection chunks =
yourMap
.entrySet()
.stream()
.collect(Collectors.groupingBy(it -> ai.getAndIncrement() / recordsPerChunk))
.values();
Upvotes: 0
Reputation: 846
You can use some of Guava functionalities which allow to partition a collection.
Map<Object, Object> map = new HashMap<>();
List<List<Map.Entry<Object, Object>>> list = Lists.newArrayList(Iterables.partition(map.entrySet(), map.size() / 2 + 1));
Map<Object, Object> map1 = list.get(0).stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Map<Object, Object> map2 = list.get(1).stream()
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Upvotes: 0
Reputation: 2318
It seems from your question that you don't care about criteria for spliting, you just want to split it in half. The below solution will work accordingly. Just create a counter and insert in first half hashmap while counter<(size of original hashmap)/2 and when counter> (size of original hashmap)/2, insert into second half hashmap.
HashMap<Integer,JSONObject> hmap;
HashMap<Integer,JSONObject> halfhmap1=new HashMap<>();
HashMap<Integer,JSONObject> halfhmap2=new HashMap<>();
int count=0;
for(Map.Entry<Long, JSONObject> entry : map.entrySet()) {
(count<(hmap.size()/2) ? halfhmap1:halfhmap2).put(entry.getKey(), entry.getValue());
count++;
}
Upvotes: 1
Reputation: 14572
If you can't use the values or the key to know where to split, simply count the iteration :
Map<Long, String> map = new HashMap<>();
Map<Long, String> sub1 = new HashMap<>();
Map<Long, String> sub2 = new HashMap<>();
int i = 0;
for(Map.Entry<Long, String> e : map.entrySet()){
(i++ % 2 == 0 ? sub1:sub2).put(e.getKey(), e.getValue());
}
I used a ternary to increment the counter and select the map. So it will equally split the values on those two maps.
Test:
Map<Long, String> map = new HashMap<>();
map.put(1L, "foo");
map.put(2L, "bar");
map.put(3L, "for");
map.put(4L, "far");
Map<Long, String> sub1 = new HashMap<>();
Map<Long, String> sub2 = new HashMap<>();
int i = 0;
for(Map.Entry<Long, String> e : map.entrySet()){
(i++ % 2 == 0 ? sub1:sub2).put(e.getKey(), e.getValue());
}
System.out.println(sub1);
System.out.println(sub2);
{1=foo, 3=for}
{2=bar, 4=far}
That would be easily adapted to split in 3, 4, or any number of maps if wanted :
public static void main(String[] args) {
Map<Long, String> map = new HashMap<>();
map.put(1L, "foo");
map.put(2L, "bar");
map.put(3L, "for");
map.put(4L, "far");
Map<Long, String> sub1 = new HashMap<>();
Map<Long, String> sub2 = new HashMap<>();
Map<Long, String> sub3 = new HashMap<>();
split(map, sub1, sub2, sub3);
System.out.println(sub1);
System.out.println(sub2);
System.out.println(sub3);
}
@SafeVarargs
public static <T, U> void split(Map<T,U> map, Map<T,U>... array){
int i = 0;
for(Map.Entry<T, U> e : map.entrySet()){
array[i++% array.length].put(e.getKey(), e.getValue());
}
}
{1=foo, 4=far}
{2=bar}
{3=for}
Upvotes: 2
Reputation: 19910
You can make use of the Java 8 Streaming API:
Map<Long, JSONObject> map = ...;
AtomicInteger counter = new AtomicInteger(0);
Map<Boolean, Map<Long, JSONObject>> collect = map.entrySet()
.stream()
.collect(Collectors.partitioningBy(
e -> counter.getAndIncrement() < map.size() / 2, // this splits the map into 2 parts
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
)
));
This collects the map into 2 halfes, the first (map.get(true)
) containing all the elements from below the middle and the second (map.get(false)
) half containing all the elements from the middle upwards.
Upvotes: 6
Reputation: 45339
You can loop through the set of entries and populate two different maps:
Map<Long, JSONObject> m = null;
Map<Long, JSONObject> zeroToFortyNine = new HashMap<>();
Map<Long, JSONObject> fiftyToNinetyNine = new HashMap<>();
m.forEach((k, v) -> {
if(k < 50) {
zeroToFortyNine.put(k, v);
} else {
fiftyToNinetyNine.put(k, v);
}
});
m.clear();
Upvotes: 1