拆分 Map 的键并使用新键和关联值创建新 Map
Split the keys of a Map and create a new Map with the new keys and the associated values
我有一个 List
of Objects
,其中每个都包含一个 X、Y 值 (Doubles
) 和一个名称 String
。由于我有多个与坐标对应的同名条目,我想 link 所有坐标的每个名称,我设法通过创建 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]]
我的有效代码是:
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 <R> flatMap(Function<? super T,? extends Stream<? extends R>>)
有什么想法吗?
您似乎没有使用 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 收集器收集它。由于您只需要保留不同的坐标值,因此您必须覆盖坐标 class 中的 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],
[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]]}
我有一个 List
of Objects
,其中每个都包含一个 X、Y 值 (Doubles
) 和一个名称 String
。由于我有多个与坐标对应的同名条目,我想 link 所有坐标的每个名称,我设法通过创建 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]]
我的有效代码是:
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 <R> flatMap(Function<? super T,? extends Stream<? extends R>>)
有什么想法吗?
您似乎没有使用 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 收集器收集它。由于您只需要保留不同的坐标值,因此您必须覆盖坐标 class 中的 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], [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]]}