java 8 流如何将 2 列映射到映射中
java 8 stream how to map 2 column into the map
我有一个 table:
name | data | num
item1 | 16 | 2
item2 | 17 | 3
item1 | 16 | 5
我想将其转换为:
{ item1: {16+16, 2+5}, item2: {17, 3}}
然而我只成功地产生了以下结果:
{ item1: 16+16, item2: 17}
使用以下代码:
Stats class 存储了这两个字段,但我不知道如何将这两个字段添加到数据中
class Stats {
public Integer data, num;
public Stats(Integer td, Integer nf) {
data = td;
num = nf;
}
public Integer getdata(){
return data;
}
public Integer getnum(){
return num;
}
}
Map<String, Stats> map = new HashMap<>();
Stream<String> lines = Files.lines(Paths.get(table));
map = lines.map(x ->
.collect(Collectors.toMap(
z -> z[0],
z -> Integer.parseInt(z[1]),
(a, b) -> a+b));
以上代码仅适用于 Map<String, Int>
,因为我不确定如何使 Map<String, Stats>
有效。
知道如何在仅使用 1 个管道的情况下将第二列中的项目放入地图吗?
您首先需要创建一个包含两个整数的class:
public final class TwoInts {
private final int data;
private final int num;
public TwoInts(int data, int num) {
this.data = data;
this.num = num;
}
// getters omitted for brevity
}
然后您可以重用已有的逻辑,除了不使用整数,您将使用 TwoInts 实例。因此,您需要能够将两个 TwoInts 实例相加以生成另一个 TwoInts 实例(就像您通过将两个整数相加来生成一个新整数一样):
public final class TwoInts {
private final int data;
private final int num;
public TwoInts(int data, int num) {
this.data = data;
this.num = num;
}
public static TwoInts sum(TwoInts first, TwoInts second) {
return new TwoInts(first.data + second.data,
first.num + second.num);
}
// getters omitted for brevity
}
好了:
Stream<String> lines = Files.lines(Paths.get(table));
Map<String, TwoInts> map =
lines.map(line -> toArrayOfStrings(line))
.collect(Collectors.toMap(
row -> row[0],
row -> new TwoInts(Integer.parseInt(row[1]), Integer.parseInt(row[2])),
(a, b) -> TwoInts.sum(a, b));
这是一个实现:
- 不需要任何额外的类
- 适用于任何长度的数值(不仅仅是 2)
- (技术上)只是一行
Stream<String> lines = Stream.of("item1,16,2",
"item2,17,3",
"item1,16,5"); // sample input
Map<String, List<Integer>> map = lines.map(s -> s.split(","))
.collect(Collectors.toMap(a -> a[0],
a -> Arrays.asList(a).stream()
.skip(1).map(Integer::parseInt)
.collect(Collectors.toList()),
(a, b) -> {for (int i = 0; i < a.size(); i++)
a.set(i, a.get(i) + b.get(i)); return a;}));
在 运行 之后打印地图输出:
{item2=[17, 3], item1=[32, 7]}
请参阅此代码的 live demo。
首先你可以让你的 Stats class 更友好地添加合并方法(我也稍微美化了它):
class Stats {
final int data, num;
public Stats() {
data = num = 0;
}
public Stats(int data, int num) {
this.data = data;
this.num = num;
}
public Stats merge(Stats stats) {
return new Stats(this.data+stats.data, this.num+stats.num);
}
public int getData(){
return data;
}
public int getNum(){
return num;
}
@Override
public String toString() {
return "{" + data + "," + num + "}";
}
}
现在您可以使用收集器链来解决您的任务。假设您的输入来自波西米亚答案中的字符串流:
Stream<String> lines = Stream.of("item1,16,2",
"item2,17,3",
"item1,16,5"); // sample input
现在生成的地图可以这样构建:
Map<String, Stats> map = lines.map(s -> s.split(",")).collect(
Collectors.groupingBy(a -> a[0],
Collectors.mapping(a -> new Stats(Integer.parseInt(a[1]), Integer.parseInt(a[2])),
Collectors.reducing(new Stats(), Stats::merge))));
System.out.println(map);
现场演示是 here。
我有一个 table:
name | data | num
item1 | 16 | 2
item2 | 17 | 3
item1 | 16 | 5
我想将其转换为:
{ item1: {16+16, 2+5}, item2: {17, 3}}
然而我只成功地产生了以下结果:
{ item1: 16+16, item2: 17}
使用以下代码: Stats class 存储了这两个字段,但我不知道如何将这两个字段添加到数据中
class Stats {
public Integer data, num;
public Stats(Integer td, Integer nf) {
data = td;
num = nf;
}
public Integer getdata(){
return data;
}
public Integer getnum(){
return num;
}
}
Map<String, Stats> map = new HashMap<>();
Stream<String> lines = Files.lines(Paths.get(table));
map = lines.map(x ->
.collect(Collectors.toMap(
z -> z[0],
z -> Integer.parseInt(z[1]),
(a, b) -> a+b));
以上代码仅适用于 Map<String, Int>
,因为我不确定如何使 Map<String, Stats>
有效。
知道如何在仅使用 1 个管道的情况下将第二列中的项目放入地图吗?
您首先需要创建一个包含两个整数的class:
public final class TwoInts {
private final int data;
private final int num;
public TwoInts(int data, int num) {
this.data = data;
this.num = num;
}
// getters omitted for brevity
}
然后您可以重用已有的逻辑,除了不使用整数,您将使用 TwoInts 实例。因此,您需要能够将两个 TwoInts 实例相加以生成另一个 TwoInts 实例(就像您通过将两个整数相加来生成一个新整数一样):
public final class TwoInts {
private final int data;
private final int num;
public TwoInts(int data, int num) {
this.data = data;
this.num = num;
}
public static TwoInts sum(TwoInts first, TwoInts second) {
return new TwoInts(first.data + second.data,
first.num + second.num);
}
// getters omitted for brevity
}
好了:
Stream<String> lines = Files.lines(Paths.get(table));
Map<String, TwoInts> map =
lines.map(line -> toArrayOfStrings(line))
.collect(Collectors.toMap(
row -> row[0],
row -> new TwoInts(Integer.parseInt(row[1]), Integer.parseInt(row[2])),
(a, b) -> TwoInts.sum(a, b));
这是一个实现:
- 不需要任何额外的类
- 适用于任何长度的数值(不仅仅是 2)
- (技术上)只是一行
Stream<String> lines = Stream.of("item1,16,2",
"item2,17,3",
"item1,16,5"); // sample input
Map<String, List<Integer>> map = lines.map(s -> s.split(","))
.collect(Collectors.toMap(a -> a[0],
a -> Arrays.asList(a).stream()
.skip(1).map(Integer::parseInt)
.collect(Collectors.toList()),
(a, b) -> {for (int i = 0; i < a.size(); i++)
a.set(i, a.get(i) + b.get(i)); return a;}));
在 运行 之后打印地图输出:
{item2=[17, 3], item1=[32, 7]}
请参阅此代码的 live demo。
首先你可以让你的 Stats class 更友好地添加合并方法(我也稍微美化了它):
class Stats {
final int data, num;
public Stats() {
data = num = 0;
}
public Stats(int data, int num) {
this.data = data;
this.num = num;
}
public Stats merge(Stats stats) {
return new Stats(this.data+stats.data, this.num+stats.num);
}
public int getData(){
return data;
}
public int getNum(){
return num;
}
@Override
public String toString() {
return "{" + data + "," + num + "}";
}
}
现在您可以使用收集器链来解决您的任务。假设您的输入来自波西米亚答案中的字符串流:
Stream<String> lines = Stream.of("item1,16,2",
"item2,17,3",
"item1,16,5"); // sample input
现在生成的地图可以这样构建:
Map<String, Stats> map = lines.map(s -> s.split(",")).collect(
Collectors.groupingBy(a -> a[0],
Collectors.mapping(a -> new Stats(Integer.parseInt(a[1]), Integer.parseInt(a[2])),
Collectors.reducing(new Stats(), Stats::merge))));
System.out.println(map);
现场演示是 here。