【问题标题】:Convert CSV string value to Hashmap using Stream lambda使用 Stream lambda 将 CSV 字符串值转换为 Hashmap
【发布时间】:2023-03-26 10:27:01
【问题描述】:

我正在尝试使用 Java 8 Streams 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。

【问题讨论】:

    标签: java dictionary java-8 java-stream


    【解决方案1】:

    这是一个奇怪的要求。当您调用Arrays.asList(sContent.split(",")) 时,您已经有了一个数据结构,它将int 数字映射到它们的Strings。结果是List&lt;String&gt;,您可以在其上调用.get(intNumber) 来获得所需的值,就像使用Map&lt;Integer,String&gt; 一样......

    但是,如果它确实必须是 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)) 的作用相同,但不会创建中间数组,因此更可取。而且您不需要单独的计数器,因为地图本质上维护了这样一个计数器,即它的大小。

    上面的代码是创建这种临时地图的最简单代码,而干净的解决方案将避免流操作本身之外的可变状态并在完成时返回一个新地图。但干净的解决方案并不总是最简洁的:

    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 行不太可能从并行处理中受益.但不支持省略它。如果使用,它将合并两个映射,这是两个并行操作的结果。由于两者都使用自己的计数器,因此必须通过添加第一个映射的大小来调整第二个映射的索引。

    【讨论】:

      【解决方案2】:

      您可以使用以下方法来获得所需的输出

        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);
      
          }
      

      【讨论】:

        【解决方案3】:

        您可以像这样创建一系列索引:

        String[] values = sContent.split(",");
        Map<Integer, String> result = IntStream.range(0, values.length)
                                               .boxed()
                                               .collect(toMap(Function.identity(), i -> values[i]));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-17
          • 2014-03-10
          • 2013-06-26
          • 2021-03-30
          • 2014-07-20
          • 1970-01-01
          • 2021-12-05
          相关资源
          最近更新 更多