当前位置: 首页 > 面试题库 >

展平地图>到地图 与流和lambda

宋新知
2023-03-14
问题内容

我想展平一个MapInteger键关联到的列表的a
String,而不会丢失键映射。我很好奇,就好像它是可能的,与这样做有用的streamlambda

我们从这样的东西开始:

Map<Integer, List<String>> mapFrom = new HashMap<>();

假设mapFrom填充在某处,如下所示:

1: a,b,c
2: d,e,f
etc.

我们还假设列表中的值是唯一的。

现在,我想“展开”它以获得第二张地图,例如:

a: 1
b: 1
c: 1
d: 2
e: 2
f: 2
etc.

我可以这样做(或使用,非常类似foreach):

Map<String, Integer> mapTo = new HashMap<>();
for (Map.Entry<Integer, List<String>> entry: mapFrom.entrySet()) {
    for (String s: entry.getValue()) {
        mapTo.put(s, entry.getKey());
    }
}

现在,假设我要使用lambda而不是嵌套for循环。我可能会做这样的事情:

Map<String, Integer> mapTo = mapFrom.entrySet().stream().map(e -> {
    e.getValue().stream().?
    // Here I can iterate on each List, 
    // but my best try would only give me a flat map for each key, 
    // that I wouldn't know how to flatten.
}).collect(Collectors.toMap(/*A String value*/,/*An Integer key*/))

我也尝试了flatMap,但是我不认为这是正确的方法,因为尽管它可以帮助我摆脱维度问题,但在此过程中我失去了关键。

简而言之,我的两个问题是:

  • 有可能使用streamslambda实现这一目标吗?
  • 这样做有用(性能,可读性)吗?

问题答案:

您需要使用flatMap将值展平到一个新的流中,但是由于仍然需要原始键来收集到中Map,因此您必须映射到一个包含键和值的临时对象,例如

Map<String, Integer> mapTo = mapFrom.entrySet().stream()
       .flatMap(e->e.getValue().stream()
                    .map(v->new AbstractMap.SimpleImmutableEntry<>(e.getKey(), v)))
       .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));

Map.Entry是一个独立的为不存在的元组类型,能够保持不同类型的两个对象的任何其它类型的是足够的。

不需要这些临时对象的替代方法是自定义收集器:

Map<String, Integer> mapTo = mapFrom.entrySet().stream().collect(
    HashMap::new, (m,e)->e.getValue().forEach(v->m.put(v, e.getKey())), Map::putAll);

这不同于toMap静默覆盖重复键,而toMap如果没有重复键,则没有合并功能将引发异常。基本上,此自定义收集器是

Map<String, Integer> mapTo = new HashMap<>();
mapFrom.forEach((k, l) -> l.forEach(v -> mapTo.put(v, k)));

但是请注意,即使输入图非常大,此任务也不会从并行处理中受益。只有在流管道中还有其他可以从SMP中受益的计算密集型任务时,才有可能从并行流中受益。因此,也许简洁的顺序Collection
API解决方案是可取的。



 类似资料:
  • 问题内容: 我怎么能展平的(同类型)s到一个用Java 8? 问题答案: 我的语法可能有些偏离,但是flatMap应该为您完成大部分工作:

  • 问题内容: 我目前的理解非常模糊,我倾向于认为map是同步的,而flatMap是异步的,但是我真的无法解决它。 这是一个例子: 我有文件(a ),我想将其复制到服务器上的某些文件中。 本示例摘自一本书。 我可以将所有更改为to ,反之亦然,一切仍然正常。我不知道有什么区别。 问题答案: 用于同步,非阻塞,一对一转换 用于异步(非阻塞)1-to-N转换 区别在方法签名中可见: 取a 并返回a 取a

  • 问题内容: 我有一个Map是一个到值列表的映射,但是我需要将其求逆,以便 变成 例如我有 我想看看 除了要遍历映射条目并创建set条目(如果不存在)并添加到列表等之外,Java 8中还有什么更简单的方法可以做到这一点?我一直认为这确实很明显,但我无法解决。 提前致谢 问题答案: 未经测试,但是您可以执行以下操作:

  • 我已经找到了很多关于RxJava的答案,但我想了解它在Reactor中是如何工作的。 我目前的理解是非常模糊的,我倾向于认为map是同步的,flatMap是异步的,但我不能真正理解它。 以下是一个例子: 我有文件(a

  • 问题内容: 如何转换 为? 这不起作用: 问题答案: 如果您只包含,则可以这样操作: 如果不是,则可以替换 为。

  • 在闪光灯下,平面图也可以发出一条记录。似乎平面图可以代替地图。有人能告诉我这种情况下的区别吗?谢谢你。