如何使用 Stream API 将字符串列表中的数据转换为 Map<String, Integer>?
How to convert data from the List of strings into a Map<String, Integer> with Stream API?
我尝试使用 Stream API.
将数据从 list 字符串转换为 Map<String, Integer>
但是我的做法不对:
public static Map<String, Integer> converter (List<String> data){
return data.stream().collect(Collectors.toMap(e->e, Function.identity()));
如果我们有List.of("5", "7", "5", "8", "9", "8")
task №1作为键-String
,值-字符频率
task №2作为键-String
,值-字符串转换为整数
像这样尝试一个频率。请注意,地图不能有重复的键。
List<String> list2 = List.of("5", "7", "5", "8", "9","8");
-
key
是 String
。
value
开始 1
。
Integers::sum
每次出现都会添加 1
。
Map<String, Integer> freq = list2.stream().collect(Collectors.toMap(
e->e, (a)->1, Integer::sum));
freq.entrySet().forEach(System.out::println);
打印
5=2
7=1
8=2
9=1
对于第二个任务,将字符串转换为 ints
是微不足道的。但请记住,重复项不存在,因此必须正确合并它们。这类似于第一个任务,除了我们只是转换为整数而不是计数。由于您有重复的整数,因此您需要提供 说明 说明如何操作。那就是 merge
函数 (a,b)->a
表示现有值 a
和新值 b
,只需保持 a
List<String> list2 = List.of("5", "7", "5", "8", "9","8");
Map<String, Integer> map = list2.stream().collectCollectors.toMap(e->e,
Integer::valueOf,
(a,b)->a); // just keep the first one
打印
5=5
7=7
8=8
9=9
task №1 as key - String, and value - character frequency
为了获得每个字符的频率,您需要展平列表中的每个字符串(即拆分每个字符串转换为字符).
因为 Java 9 我们可以使用方法 chars()
其中 returns 用 int
原语表示的字符流。
flatMapToInt(String::chars)
将生成一个 IntStream
,包含给定列表中每个字符串的字符。
然后 mapToObj()
为每个流元素创建一个 single-character 字符串。
要生成频率图,我们可以使用收集器 Collectors.groupingBy()
。 Function.identity()
用作第一个参数,相当于 e -> e
,它只是一种告诉流元素将用作 key 的方式,无需任何更改。第二个参数是 下游收集器 Collectors.counting()
,它生成映射到特定 key.
的元素数量
public static Map<String, Long> getCharacterFrequency(List<String> list) {
return list.stream() // Stream<String>
.flatMapToInt(String::chars) // IntStream
.mapToObj(ch -> String.valueOf((char) ch)) // String<String>
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
}
task №2 as key - String, and value - string converted to integer
您可以通过使用需要三个参数的 collector Collectors.toMap()
风格来实现:
- keyMapper - 从流元素生成 key 的函数;
- valueMapper - 从流元素生成 value 的函数;
- mergeFunction - 一个函数,用于确定当两个值恰好映射到同一个键时如何解决这种情况。
虽然下面代码中的mergeFunction没有做任何特殊的事情,但还是需要提供,否则第一次遇到duplicate会导致IllegalStateException
。
public static Map<String, Integer> getStringValuesMappedToInts(List<String> list) {
return list.stream()
.collect(Collectors.toMap(Function.identity(), // key (String)
Integer::valueOf, // value (Integer)
(v1, v2) -> v1)); // function that resolves collisions
}
main()
- 演示
public static void main(String[] args) {
List<String> source = List.of("5", "7", "57", "59", "5", "8", "99", "9", "8");
// task 1
System.out.println("task 1:\n" + getCharacterFrequency(source));
// task 2
System.out.println("task 2:\n" + getStringValuesMappedToInts(source));
}
输出
task 1:
{5=4, 7=2, 8=2, 9=4}
task 2:
{99=99, 57=57, 59=59, 5=5, 7=7, 8=8, 9=9}
我尝试使用 Stream API.
将数据从 list 字符串转换为Map<String, Integer>
但是我的做法不对:
public static Map<String, Integer> converter (List<String> data){
return data.stream().collect(Collectors.toMap(e->e, Function.identity()));
如果我们有List.of("5", "7", "5", "8", "9", "8")
task №1作为键-String
,值-字符频率
task №2作为键-String
,值-字符串转换为整数
像这样尝试一个频率。请注意,地图不能有重复的键。
List<String> list2 = List.of("5", "7", "5", "8", "9","8");
-
key
是String
。 value
开始1
。Integers::sum
每次出现都会添加1
。
Map<String, Integer> freq = list2.stream().collect(Collectors.toMap(
e->e, (a)->1, Integer::sum));
freq.entrySet().forEach(System.out::println);
打印
5=2
7=1
8=2
9=1
对于第二个任务,将字符串转换为 ints
是微不足道的。但请记住,重复项不存在,因此必须正确合并它们。这类似于第一个任务,除了我们只是转换为整数而不是计数。由于您有重复的整数,因此您需要提供 说明 说明如何操作。那就是 merge
函数 (a,b)->a
表示现有值 a
和新值 b
,只需保持 a
List<String> list2 = List.of("5", "7", "5", "8", "9","8");
Map<String, Integer> map = list2.stream().collectCollectors.toMap(e->e,
Integer::valueOf,
(a,b)->a); // just keep the first one
打印
5=5
7=7
8=8
9=9
task №1 as key - String, and value - character frequency
为了获得每个字符的频率,您需要展平列表中的每个字符串(即拆分每个字符串转换为字符).
因为 Java 9 我们可以使用方法 chars()
其中 returns 用 int
原语表示的字符流。
flatMapToInt(String::chars)
将生成一个 IntStream
,包含给定列表中每个字符串的字符。
然后 mapToObj()
为每个流元素创建一个 single-character 字符串。
要生成频率图,我们可以使用收集器 Collectors.groupingBy()
。 Function.identity()
用作第一个参数,相当于 e -> e
,它只是一种告诉流元素将用作 key 的方式,无需任何更改。第二个参数是 下游收集器 Collectors.counting()
,它生成映射到特定 key.
public static Map<String, Long> getCharacterFrequency(List<String> list) {
return list.stream() // Stream<String>
.flatMapToInt(String::chars) // IntStream
.mapToObj(ch -> String.valueOf((char) ch)) // String<String>
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
}
task №2 as key - String, and value - string converted to integer
您可以通过使用需要三个参数的 collector Collectors.toMap()
风格来实现:
- keyMapper - 从流元素生成 key 的函数;
- valueMapper - 从流元素生成 value 的函数;
- mergeFunction - 一个函数,用于确定当两个值恰好映射到同一个键时如何解决这种情况。
虽然下面代码中的mergeFunction没有做任何特殊的事情,但还是需要提供,否则第一次遇到duplicate会导致IllegalStateException
。
public static Map<String, Integer> getStringValuesMappedToInts(List<String> list) {
return list.stream()
.collect(Collectors.toMap(Function.identity(), // key (String)
Integer::valueOf, // value (Integer)
(v1, v2) -> v1)); // function that resolves collisions
}
main()
- 演示
public static void main(String[] args) {
List<String> source = List.of("5", "7", "57", "59", "5", "8", "99", "9", "8");
// task 1
System.out.println("task 1:\n" + getCharacterFrequency(source));
// task 2
System.out.println("task 2:\n" + getStringValuesMappedToInts(source));
}
输出
task 1:
{5=4, 7=2, 8=2, 9=4}
task 2:
{99=99, 57=57, 59=59, 5=5, 7=7, 8=8, 9=9}