如果 java 中的第一个索引值相同,则合并列表中列表的索引
merge indexes of lists in a list if first index value is same in java
如果 Java 8 中的第一个索引匹配,我希望将列表合并到列表中。
我有一个列表
[[ABC, 1.0, 4.0, 4.0], [ABC, 2.0, 4.0, 4.0], [ABC, 1.0, 72.0, 72.0], [XYZ, 1.0, 36.0, 36.0], [XYZ, 2.0, 16.0, 16.0]]
而且我希望以一种有效的方式得到如下结果,就像在 java 中使用流一样。
结果应该是
[[ABC, 4.0, 116.0, 116.0], [XYZ, 3.0, 52.0, 52.0]]
有人可以帮忙吗?
在这种情况下,Collectors.toMap
应与选择的键一起使用作为第一个索引,并使用合并函数对其余元素求和。
示例:
List<List<Object>> input = Arrays.asList(
Arrays.asList("ABC", 1.0, 4.0, 4.0),
Arrays.asList("ABC", 2.0, 40.0, 40.0),
Arrays.asList("ABC", 1.0, 72.0, 72.0),
Arrays.asList("XYZ", 1.0, 36.0, 36.0),
Arrays.asList("XYZ", 2.0, 16.0, 16.0)
);
List<List<Object>> merged = new ArrayList<>(input.stream()
.collect(Collectors.toMap(
list -> list.get(0),
list -> list,
(l1, l2) -> Stream.concat(
Stream.of(l1.get(0)),
IntStream.range(1, l1.size())
.mapToObj(i -> (Double)l1.get(i) + (Double)l2.get(i))
)
.collect(Collectors.toList()),
LinkedHashMap::new // keep insertion order
))
.values() // Collection<List<Object>>
);
System.out.println(merged);
// -> [[ABC, 4.0, 116.0, 116.0], [XYZ, 3.0, 52.0, 52.0]]
但是,输入列表似乎是字符串和双精度数据的混合,它们应该更好地转换为具有适当 merge
函数的 class/record。
这里是使用 record
的示例,自 Java 16 以来可用 merge
方法和覆盖的 toString
方法。
record Item(String name, double ... values) {
Item merge(Item that) {
return new Item(
this.name,
IntStream.range(0, this.values.length)
.mapToDouble(i -> this.values[i] + that.values[i])
.toArray()
);
}
@Override
public String toString() {
return String.format("[%s, %s]", name,
Arrays.stream(values)
.mapToObj(String::valueOf)
.collect(Collectors.joining(", "))
);
}
};
List<Item> data = Arrays.asList(
new Item("ABC", 1.0, 4.0, 4.0),
new Item("ABC", 2.0, 40.0, 40.0),
new Item("ABC", 1.0, 72.0, 72.0),
new Item("XYZ", 1.0, 36.0, 36.0),
new Item("XYZ", 2.0, 16.0, 16.0)
);
List<Item> items = data.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(
Item::name,
item -> item,
Item::merge,
LinkedHashMap::new // keep insertion order
),
map -> new ArrayList<>(map.values())
));
System.out.println(items);
// -> [[ABC, 4.0, 116.0, 116.0], [XYZ, 3.0, 52.0, 52.0]]
- 对于列表列表中的每个列表
- 如果第一个值不在哈希图中,使用第一个值作为键添加到哈希图中
- 如果键已经在 hashmap 中,则与 hashmap 中已有的列表合并
- 根据 hashmap 条目集创建新的列表列表
额外功劳:使用 LinkedHashMap 保留外观顺序,如果您希望按字母顺序排列,则使用 TreeMap
如果 Java 8 中的第一个索引匹配,我希望将列表合并到列表中。 我有一个列表
[[ABC, 1.0, 4.0, 4.0], [ABC, 2.0, 4.0, 4.0], [ABC, 1.0, 72.0, 72.0], [XYZ, 1.0, 36.0, 36.0], [XYZ, 2.0, 16.0, 16.0]]
而且我希望以一种有效的方式得到如下结果,就像在 java 中使用流一样。 结果应该是
[[ABC, 4.0, 116.0, 116.0], [XYZ, 3.0, 52.0, 52.0]]
有人可以帮忙吗?
在这种情况下,Collectors.toMap
应与选择的键一起使用作为第一个索引,并使用合并函数对其余元素求和。
示例:
List<List<Object>> input = Arrays.asList(
Arrays.asList("ABC", 1.0, 4.0, 4.0),
Arrays.asList("ABC", 2.0, 40.0, 40.0),
Arrays.asList("ABC", 1.0, 72.0, 72.0),
Arrays.asList("XYZ", 1.0, 36.0, 36.0),
Arrays.asList("XYZ", 2.0, 16.0, 16.0)
);
List<List<Object>> merged = new ArrayList<>(input.stream()
.collect(Collectors.toMap(
list -> list.get(0),
list -> list,
(l1, l2) -> Stream.concat(
Stream.of(l1.get(0)),
IntStream.range(1, l1.size())
.mapToObj(i -> (Double)l1.get(i) + (Double)l2.get(i))
)
.collect(Collectors.toList()),
LinkedHashMap::new // keep insertion order
))
.values() // Collection<List<Object>>
);
System.out.println(merged);
// -> [[ABC, 4.0, 116.0, 116.0], [XYZ, 3.0, 52.0, 52.0]]
但是,输入列表似乎是字符串和双精度数据的混合,它们应该更好地转换为具有适当 merge
函数的 class/record。
这里是使用 record
的示例,自 Java 16 以来可用 merge
方法和覆盖的 toString
方法。
record Item(String name, double ... values) {
Item merge(Item that) {
return new Item(
this.name,
IntStream.range(0, this.values.length)
.mapToDouble(i -> this.values[i] + that.values[i])
.toArray()
);
}
@Override
public String toString() {
return String.format("[%s, %s]", name,
Arrays.stream(values)
.mapToObj(String::valueOf)
.collect(Collectors.joining(", "))
);
}
};
List<Item> data = Arrays.asList(
new Item("ABC", 1.0, 4.0, 4.0),
new Item("ABC", 2.0, 40.0, 40.0),
new Item("ABC", 1.0, 72.0, 72.0),
new Item("XYZ", 1.0, 36.0, 36.0),
new Item("XYZ", 2.0, 16.0, 16.0)
);
List<Item> items = data.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(
Item::name,
item -> item,
Item::merge,
LinkedHashMap::new // keep insertion order
),
map -> new ArrayList<>(map.values())
));
System.out.println(items);
// -> [[ABC, 4.0, 116.0, 116.0], [XYZ, 3.0, 52.0, 52.0]]
- 对于列表列表中的每个列表
- 如果第一个值不在哈希图中,使用第一个值作为键添加到哈希图中
- 如果键已经在 hashmap 中,则与 hashmap 中已有的列表合并
- 根据 hashmap 条目集创建新的列表列表
额外功劳:使用 LinkedHashMap 保留外观顺序,如果您希望按字母顺序排列,则使用 TreeMap