在Java8中将hashmap拆分为分区
我有hashmap:在Java8中将hashmap拆分为分区,java,collections,hashmap,java-8,Java,Collections,Hashmap,Java 8,我有hashmap:Map myMap 我想将其拆分为包含映射的列表: List<Map<String,Set<String>>> listofMaps; 地图列表; ,每个地图最多有100个关键点。 我知道如何以常规的方式来做这件事……(在入口集中使用foreach,每100个项目创建一个新地图)。 有没有办法用Java8Lambda或其他什么东西来实现?(类似于Lists.partitions())?将流拆分为有序的固定大小块(如Lists.parti
Map myMap
我想将其拆分为包含映射的列表
:
List<Map<String,Set<String>>> listofMaps;
地图列表;
,每个地图最多有100个关键点。
我知道如何以常规的方式来做这件事……(在入口集中使用foreach,每100个项目创建一个新地图)。
有没有办法用Java8Lambda或其他什么东西来实现?(类似于
Lists.partitions()
)?将流拆分为有序的固定大小块(如Lists.partition
)是不可能的,因为在并行执行中,每个块都必须等待其左空间块被完全处理
但是,如果您不关心生成的子映射中键的顺序(因为它将由Map#iterator
的方法返回),则可以滚动自定义收集器
private static <K, V> Collector<Map.Entry<K, V>, ?, List<Map<K, V>>> mapSize(int limit) {
return Collector.of(ArrayList::new,
(l, e) -> {
if (l.isEmpty() || l.get(l.size() - 1).size() == limit) {
l.add(new HashMap<>());
}
l.get(l.size() - 1).put(e.getKey(), e.getValue());
},
(l1, l2) -> {
if (l1.isEmpty()) {
return l2;
}
if (l2.isEmpty()) {
return l1;
}
if (l1.get(l1.size() - 1).size() < limit) {
Map<K, V> map = l1.get(l1.size() - 1);
ListIterator<Map<K, V>> mapsIte = l2.listIterator(l2.size());
while (mapsIte.hasPrevious() && map.size() < limit) {
Iterator<Map.Entry<K, V>> ite = mapsIte.previous().entrySet().iterator();
while (ite.hasNext() && map.size() < limit) {
Map.Entry<K, V> entry = ite.next();
map.put(entry.getKey(), entry.getValue());
ite.remove();
}
if (!ite.hasNext()) {
mapsIte.remove();
}
}
}
l1.addAll(l2);
return l1;
}
);
}
我还没有对它进行广泛的测试。我还认为你可以修改它,使它更通用
例如,您可以接受任意对象,并使用两个函数为正在处理的每个实例生成一个键和一个值
private static <T, K, V> Collector<T, ?, List<Map<K, V>>> mapSize(Function<T, K> keyFunc, Function<T, V> mapFunc, int limit) {
把它叫做:
.collect(mapSize(Map.Entry::getKey, Map.Entry::getValue, size));
使用my
unorderedBatches()
collector from answer:
收集器批处理收集器=
无序批次(100,
Collectors.toMap(Entry::getKey,Entry::getValue),Collectors.toList();
List listofMaps=myMap.entrySet().stream()
.收集(批次收集器);
并不特别。这不是一种可以用Java 8流轻松表达的操作(甚至根本不是)。如果你指的是Guava的列表.partition
,这是一种可行的方法,可能与Java 8结合使用,尽管你可能会使用Iterables.partition
。与我之前的方法相比,它的可重用性更强,做得很好。。再说一遍:-)。
private static <T, K, V> Collector<T, ?, List<Map<K, V>>> mapSize(Function<T, K> keyFunc, Function<T, V> mapFunc, int limit) {
l.get(l.size() - 1).put(keyFunc.apply(e), mapFunc.apply(e));
.collect(mapSize(Map.Entry::getKey, Map.Entry::getValue, size));
Collector<Entry<String, Set<String>>, ?, List<Map<String, Set<String>>>> batchesCollector =
unorderedBatches(100,
Collectors.toMap(Entry::getKey, Entry::getValue), Collectors.toList());
List<Map<String, Set<String>>> listofMaps = myMap.entrySet().stream()
.collect(batchesCollector);