【问题标题】:Split the keys of a Map and create a new Map with the new keys and the associated values拆分 Map 的键并使用新键和关联值创建新 Map
【发布时间】:2019-02-18 18:11:38
【问题描述】:

我有一个 ListObjects,每个都包含一个 X、Y 值 (Doubles) 和一个名称 String。由于我有多个与坐标对应的同名条目,因此我想将每个名称链接到所有坐标,我通过创建Map 类型的<String, List<Object>> 设法做到这一点

输出示例:

One             [[0.1,0.1,0.1],[0.2,0.3,0.4]]
One,Two         [[0.1,0.1]    ,[0.4,0.5]]         
One,Two,Three   [[0.1,0.1]    ,[0.6,0.7]]

我现在要做的是将有逗号,的名称拆分并达到以下结果:

One   [[0.1,0.1,0.1,0.1,0.1,0.1],[0.2,0.3,0.4,0.5,0.6,0.7]]
Two   [[0.01,0.01,0.01,0.01]    ,[0.4,0.5,0.6,0.7]]                    
Three [[0.01,0.01]              ,[0.6,0.7]]

我的 WORKS 代码是:

Map<String, List<Coordinates>> newList = coordinateList.stream()
                .collect(Collectors.groupingBy(Coordinates::getName));

创建第一个Map

为了完成第二部分,我尝试了以下各种组合,但没有运气:

newList.entrySet().stream()
        .flatMap(entry -> Arrays.stream(entry.getKey().split(","))
                .map(s -> new AbstractMap.SimpleEntry<>(s, entry.getValue())))
        .collect(Collectors.groupingBy(Map.Entry::getKey, 
                Collectors.flatMapping(entry -> entry.getValue().stream(), Collectors.toList())));

我得到的错误是:

The method flatMapping((<no type> entry) -> {}, Collectors.toList()) is undefined for the type Collectors

请注意,将flatMapping 更改为mapping 可以工作,但不能解决问题。

我尝试过的代码的另一个变体是:

Map<String, List<Object>> collect1 = map.entrySet().stream()
        .flatMap(entry -> Arrays.stream(entry.getKey().split(","))
                .map(s -> new AbstractMap.SimpleEntry<>(s, entry.getValue())))
        .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())))
        .entrySet().stream()
        .flatMap(entry -> entry.getValue().stream()
                .flatMap(Collection::stream)
                .map(o -> new AbstractMap.SimpleEntry<>(entry.getKey(), o)))
        .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));

仍然没有运气,我经常收到错误Cannot infer type argument(s) for &lt;R&gt; flatMap(Function&lt;? super T,? extends Stream&lt;? extends R&gt;&gt;)

有什么想法吗?

【问题讨论】:

  • 您的第一次尝试对我有用。请注意,Collectors.flatMapping 直到 Java 9 才出现。您确定您配置了正确的目标 JDK?
  • @teppic 我将最新的 java 库 (11.0...) 添加到我的项目文件夹中,但仍然是同样的错误。

标签: java dictionary java-8 java-stream java-9


【解决方案1】:

看来您没有使用 java9。如果您使用的是 Java9,则使用 Collectors.flatMapping 的前一种方法将起作用。但是我仍然认为在这里创建一个新的Map.Entry 没有任何意义。看看这个解决方案。

private static final Pattern COMMA_DELIMITER = Pattern.compile(",\\s*");

Map<String, Set<Coordinate>> nameToCoordinates = coordinates.stream()
    .flatMap(
        c -> COMMA_DELIMITER.splitAsStream(c.getName())
            .map(n -> new Coordinate(n, c.getX(), c.getY())))
    .collect(Collectors.groupingBy(Coordinate::getName, Collectors.toSet()));

对于每个坐标,获取它的名称并使用 , 分隔符将其拆分,然后为每个此类名称标记创建一个具有该新名称和 x、y 坐标的新坐标。然后只需使用 groupingBy 收集器收集它。由于您只需要保留不同的 Coordinate 值,因此您必须覆盖 Coordinate 类中的 equals 和 hashCode 方法。这是它的外观。

@Override
public int hashCode() {
    int result = name.hashCode();
    result = 31 * result + Double.hashCode(x);
    result = 31 * result + Double.hashCode(y);
    return result;
}

@Override
public boolean equals(Object obj) {
    return obj instanceof Coordinate && ((Coordinate) obj).getX() == x 
        && ((Coordinate) obj).getY() == y
        && ((Coordinate) obj).getName().equals(name);
}

由于某种原因,如果你真的需要使用第一步创建的中间图,那么你的解决方案就是这样。

newList.values().stream().flatMap(Collection::stream)
    .flatMap(
        c -> COMMA_DELIMITER.splitAsStream(c.getName())
            .map(n -> new Coordinate(n, c.getX(), c.getY())))
    .collect(Collectors.groupingBy(Coordinate::getName, Collectors.toSet()));

这是输出。

{One=[[name=One, x=0.1, y=0.2], [name=One, x=0.1, y=0.4], [name=One, x=0.1, y=0.3], [name=One, x=0.1, y=0.5], [name=One, x=0.1, y=0.6], [名称=一,x=0.1,y=0.7]],二=[[名称=二,x=0.1,y=0.4],[名称=二, x=0.1, y=0.5], [name=Two, x=0.1, y=0.6], [name=Two, x=0.1, y=0.7]], 三=[[name=三, x=0.1, y=0.6], [name=三, x=0.1, y=0.7]]}

【讨论】:

  • 感谢您提出的解决方案,第一种方法对我有用。我也尝试了第二个,但我没有得到正确的格式。
  • 第二个应该也可以。这是我得到的输出。 {One=[[name=One, x=0.1, y=0.4], [name=One, x=0.1, y=0.2], [name=One, x=0.1, y=0.5], [name=One, x=0.1, y=0.3], [name=One, x=0.1, y=0.6], [name=One, x=0.1, y=0.7]], Two=[[name=Two, x=0.1, y=0.4], [name=Two, x=0.1, y=0.5], [name=Two, x=0.1, y=0.6], [name=Two, x=0.1, y=0.7]], Three=[[name=Three, x=0.1, y=0.6], [name=Three, x=0.1, y=0.7]]}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-31
  • 2018-11-29
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多