问答

java8数据结构优雅的转换方式

作者:admin 2021-05-09 我要评论

如题,已知如下结构: map的大小不确定,但是 map中的v(也就是list)的大小都是一致的。 MapString, ListObject map = new HashMap(ImmutableMap.of( "a", List...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

如题,已知如下结构:

map的大小不确定,但是 map中的v(也就是list)的大小都是一致的。

Map<String, List<Object>> map = new HashMap<>(ImmutableMap.of(
                "a", Lists.newArrayList(1, 2, 3),
                "b", Lists.newArrayList(4, 5, 6)
        ));

要转换成如下结构:

List<Map<String, Object>> list = Lists.newArrayList(
                Maps.newHashMap(ImmutableMap.of(
                        "a", 1,
                        "b", 4
                )),
                Maps.newHashMap(ImmutableMap.of(
                        "a", 2,
                        "b", 5
                )),
                Maps.newHashMap(ImmutableMap.of(
                        "a", 3,
                        "b", 6
                ))
        );

怎么转换比较方便呢?

###

本来想不劳而获的,算了自己写把

int total = map.values().iterator().next().size();
        List<Map<String, Object>> list = IntStream.range(0, total)
                .boxed()
                .parallel()
                .map(i -> map.entrySet()
                        .stream()
                        .reduce(new HashMap<>(total), (accMap, entry) -> {
                            accMap.put(entry.getKey(), entry.getValue().get(i));
                            return accMap;
                        }, (BinaryOperator<Map<String, Object>>) (accMap1, accMap2) -> {
                            accMap1.putAll(accMap2);
                            return accMap1;
                        }))
                .collect(Collectors.toList());
###

如果用库:abacus-util

// 这里取value的最大size,假设它们的size可能不一样
int maxValueSize = Stream.ofValues(map).mapToInt(it -> it.size()).max().orZero();

List<Map<String, Object>> list = IntStream.range(0, maxValueSize)
        .mapToObj(it -> Stream.of(map).filter(e -> e.getValue().size() > it).toMap(e -> e.getKey(), e -> e.getValue().get(it)))
        .toList();

如果以后可能需要重用这个代码,也可以准备一个方法:

public static <K, V> List<Map<K, V>> flatToMap(final Map<K, ? extends List<? extends V>> map) {
    if (map == null) {
        return new ArrayList<>();
    }

    int maxValueSize = 0;

    for (List<? extends V> v : map.values()) {
        maxValueSize = N.max(maxValueSize, N.size(v));
    }

    final List<Map<K, V>> result = new ArrayList<>(maxValueSize);

    for (int i = 0; i < maxValueSize; i++) {
        final Map<K, V> m = new HashMap<>();

        for (Map.Entry<K, ? extends List<? extends V>> entry : map.entrySet()) {
            if (entry.getValue() != null || entry.getValue().size() > i) {
                m.put(entry.getKey(), entry.getValue().get(i));
            }
        }

        result.add(m);
    }

    return result;
}

这样代码就可以简化为:

Stream.of(map).map(it -> flatToMap(it)).findFirst().orElseThrow();

最后,一个建议,想着这样的轻操作,没有必要用parallel(),不但没有什么性能优势,反而会更慢。

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • grom设置json默认值

    grom设置json默认值

  • Vue路由报错,看着没问题

    Vue路由报错,看着没问题

  • 思否邮箱登录为什么区分大小写了呢?

    思否邮箱登录为什么区分大小写了呢?

  • 有没有能够直接上传markdown文件作为博

    有没有能够直接上传markdown文件作为博

腾讯云代理商
海外云服务器