使用 Stream lambda 将 CSV 字符串值转换为 Hashmap
Convert CSV string value to Hashmap using Stream lambda
我正在尝试使用 Java 8 条流 API 从 CSV 字符串值中获取 HashMap<String,String>
。我能够获取值等,但是如何将 List
的索引添加为 HashMap
.
中的键
(HashMap<String, String>) Arrays.asList(sContent.split(",")).stream()
.collect(Collectors.toMap(??????,i->i );
所以我的地图将包含如下所示的 Key 和 Value。
0->Value1
1->Value2
2->Value3
...
使用普通 Java 我可以轻松做到,但我想使用 JAVA 8 流 API.
您可以使用以下方法获得所需的输出
private Map<Integer, String> getMapFromCSVString(String csvString) {
AtomicInteger integer = new AtomicInteger();
return Arrays.stream(csvString.split(","))
.collect(Collectors.toMap(splittedStr -> integer.getAndAdd(1), splittedStr -> splittedStr));
}
我写了下面的测试来验证输出。
@Test
public void getCsvValuesIntoMap(){
String csvString ="shirish,vilas,Nikhil";
Map<Integer,String> expected = new HashMap<Integer,String>(){{
put(0,"shirish");
put(1,"vilas");
put(2,"Nikhil");
}};
Map<Integer,String> result = getMapFromCSVString(csvString);
System.out.println(result);
assertEquals(expected,result);
}
您可以像这样创建一系列索引:
String[] values = sContent.split(",");
Map<Integer, String> result = IntStream.range(0, values.length)
.boxed()
.collect(toMap(Function.identity(), i -> values[i]));
这是一个奇怪的要求。当您调用 Arrays.asList(sContent.split(","))
时,您已经拥有一个将 int
数字映射到它们的 String
的数据结构。结果是 List<String>
,您可以调用 .get(intNumber)
来获得所需的值,就像您可以使用 Map<Integer,String>
...
但是,如果它确实必须是 Map
并且您想使用流 API,您可以使用
Map<Integer,String> map=new HashMap<>();
Pattern.compile(",").splitAsStream(sContent).forEachOrdered(s->map.put(map.size(), s));
解释一下,Pattern.compile(separator).splitAsStream(string)
与 Arrays.stream(string.split(separator))
的作用相同,但不创建中间数组,因此更可取。而且您不需要单独的计数器,因为地图本质上维护这样一个计数器,它的大小。
上面的代码是创建此类临时地图的最简单代码,而干净的解决方案将避免流操作本身之外的可变状态,并 return 完成时创建新地图。但是干净的解决方案并不总是最简洁的:
Map<Integer,String> map=Pattern.compile(",").splitAsStream(sContent)
.collect(HashMap::new, (m,s)->m.put(m.size(), s),
(m1,m2)->{ int off=m1.size(); m2.forEach((k,v)->m1.put(k+off, v)); }
);
虽然 collect
的前两个参数定义了与之前解决方案类似的操作,但最大的障碍是第三个参数,该函数仅在通过单个 csv 行请求并行处理时使用,不太可能受益于并行处理。但不支持省略它。如果使用,它将合并两个映射,这是两个并行操作的结果。由于两者都使用自己的计数器,因此必须通过添加第一张地图的大小来调整第二张地图的索引。
我正在尝试使用 Java 8 条流 API 从 CSV 字符串值中获取 HashMap<String,String>
。我能够获取值等,但是如何将 List
的索引添加为 HashMap
.
(HashMap<String, String>) Arrays.asList(sContent.split(",")).stream()
.collect(Collectors.toMap(??????,i->i );
所以我的地图将包含如下所示的 Key 和 Value。
0->Value1
1->Value2
2->Value3
...
使用普通 Java 我可以轻松做到,但我想使用 JAVA 8 流 API.
您可以使用以下方法获得所需的输出
private Map<Integer, String> getMapFromCSVString(String csvString) {
AtomicInteger integer = new AtomicInteger();
return Arrays.stream(csvString.split(","))
.collect(Collectors.toMap(splittedStr -> integer.getAndAdd(1), splittedStr -> splittedStr));
}
我写了下面的测试来验证输出。
@Test
public void getCsvValuesIntoMap(){
String csvString ="shirish,vilas,Nikhil";
Map<Integer,String> expected = new HashMap<Integer,String>(){{
put(0,"shirish");
put(1,"vilas");
put(2,"Nikhil");
}};
Map<Integer,String> result = getMapFromCSVString(csvString);
System.out.println(result);
assertEquals(expected,result);
}
您可以像这样创建一系列索引:
String[] values = sContent.split(",");
Map<Integer, String> result = IntStream.range(0, values.length)
.boxed()
.collect(toMap(Function.identity(), i -> values[i]));
这是一个奇怪的要求。当您调用 Arrays.asList(sContent.split(","))
时,您已经拥有一个将 int
数字映射到它们的 String
的数据结构。结果是 List<String>
,您可以调用 .get(intNumber)
来获得所需的值,就像您可以使用 Map<Integer,String>
...
但是,如果它确实必须是 Map
并且您想使用流 API,您可以使用
Map<Integer,String> map=new HashMap<>();
Pattern.compile(",").splitAsStream(sContent).forEachOrdered(s->map.put(map.size(), s));
解释一下,Pattern.compile(separator).splitAsStream(string)
与 Arrays.stream(string.split(separator))
的作用相同,但不创建中间数组,因此更可取。而且您不需要单独的计数器,因为地图本质上维护这样一个计数器,它的大小。
上面的代码是创建此类临时地图的最简单代码,而干净的解决方案将避免流操作本身之外的可变状态,并 return 完成时创建新地图。但是干净的解决方案并不总是最简洁的:
Map<Integer,String> map=Pattern.compile(",").splitAsStream(sContent)
.collect(HashMap::new, (m,s)->m.put(m.size(), s),
(m1,m2)->{ int off=m1.size(); m2.forEach((k,v)->m1.put(k+off, v)); }
);
虽然 collect
的前两个参数定义了与之前解决方案类似的操作,但最大的障碍是第三个参数,该函数仅在通过单个 csv 行请求并行处理时使用,不太可能受益于并行处理。但不支持省略它。如果使用,它将合并两个映射,这是两个并行操作的结果。由于两者都使用自己的计数器,因此必须通过添加第一张地图的大小来调整第二张地图的索引。