将字符串转换为地图列表

huangapple go评论77阅读模式
英文:

Convert String to List of Map

问题

String esConnectionPropertiesStr = "ID1, 701, REST, 0, $PROJECT_ID),\n" +
               "ID2, 702, ES_USERNAME, 0, $PROJECT_ID),\n" +
               "ID3, 703, ES_PASSWORD, 0, $PROJECT_ID),\n" +
               "ID4, 704, ES_HOST, 0, $PROJECT_ID";

List<Map<Integer, String>> outputList = Arrays.stream(esConnectionPropertiesStr.split("\\),\n"))
        .map(e -> Arrays.stream(e.split(", "))
                .map(s -> s.replace("$", "").replace("(", "").replace(")", "").trim())
                .collect(Collectors.toList()))
        .map(e -> {
            Map<Integer, String> map = new HashMap<>();
            map.put(1, e.get(0));
            map.put(2, e.get(1));
            map.put(3, e.get(2));
            map.put(4, e.get(3));
            map.put(5, e.get(4));
            return map;
        })
        .collect(Collectors.toList());

Please note that the provided Java code is a direct translation of the given code and might not be the most efficient or idiomatic solution.

英文:

I have a following String. I want to convert it into List of Map as below,

String esConnectionPropertiesStr = &quot;ID1, 701, REST, 0, $PROJECT_ID),\n&quot; +
               &quot;ID2, 702, ES_USERNAME, 0, $PROJECT_ID),\n&quot; +
               &quot;ID3, 703, ES_PASSWORD, 0, $PROJECT_ID),\n&quot; +
               &quot;ID4, 704, ES_HOST, 0, $PROJECT_ID&quot;;

Output:

[ 
	{1=ID1, 2=701, 3= ES_USERNAME, 4= 0, 5= $PROJECT_ID}, 
	{1=ID2, 2=702, 3= ES_PASSWORD, 4= 0, 5= $PROJECT_ID},
	{1=ID3, 2=703, 3=ES_HOST, 4= 0, 5= $PROJECT_ID},
	{1=ID4, 2=704, 3= ES_PORT, 4= 0, 5=$PROJECT_ID} 
]

It is spliting by ), and then by comma to get map elements. I tried following which works,

AtomicInteger index = new AtomicInteger(0);
Arrays.stream(esConnectionPropertiesStr.split(&quot;\\),&quot;))
        .map(e -&gt; Arrays.stream(e.split(&quot;,&quot;))
                .collect(Collectors.toMap(n1 -&gt; index.incrementAndGet(), s -&gt; s)))
        .peek(i -&gt; index.set(0))
        .collect(Collectors.toList());

Is there any better way to do this??

答案1

得分: 1

`AtomicInteger` 在这里是多余的。它增加了更多的复杂性和更多的失败可能性。
此外,`Stream API` 的规范[不保证][1]会执行 `Stream::peek` 方法。

以下是朴素(尽管相当冗长)的解决方案:

    List<Map<Integer, String>> resultMap =
            Arrays.stream(esConnectionPropertiesStr.split("\\),"))
                  .map(row -> Arrays.stream(row.split(","))
                                    .collect(collectingAndThen(toList(), 
                                             list ->IntStream.range(0, list.size())
                                                             .boxed()
                                                             .collect(toMap(identity(), list::get)))))
                  .collect(toList());

----------

虽然上面的解决方案可以工作,但在我看来它不易读。我会将 `list-to-map` 转换提取到一个静态实用方法中:

    class Utils {
        public static Map<Integer, String> toIndexedMap(List<String> list) {
            return IntStream.range(0, list.size())
                            .boxed()
                            .collect(toMap(identity(), list::get));
    }

然后按如下方式使用实用方法:

    List<Map<Integer, String>> result =
            Arrays.stream(esConnectionPropertiesStr.split("\\),"))
                  .map(row -> Arrays.stream(row.split(","))
                                    .collect(collectingAndThen(toList(), Utils::toIndexedMap)))
                  .collect(toList());

  [1]: https://stackoverflow.com/a/33636377/10584605
英文:

The AtomicInteger is redundant here. It adds more complexity and more room for failure.
Moreover the specification of Stream API does not guarantee the execution of Stream::peek.

This is the naive (though pretty long) solution:

List&lt;Map&lt;Integer, String&gt;&gt; resultMap =
        Arrays.stream(esConnectionPropertiesStr.split(&quot;\\),&quot;))
              .map(row -&gt; Arrays.stream(row.split(&quot;,&quot;))
                                .collect(collectingAndThen(toList(), 
                                         list -&gt;IntStream.range(0, list.size())
                                                         .boxed()
                                                         .collect(toMap(identity(), list::get)))))
              .collect(toList());

Although the solution above works, IMHO it isn't readable. I would extract the list-to-map conversion into a static util method:

class Utils { // 
    public static Map&lt;Integer, String&gt; toIndexedMap(List&lt;String&gt; list) {
        return IntStream.range(0, list.size())
                        .boxed()
                        .collect(toMap(identity(), list::get));
}

then use the utility methods as follow:

List&lt;Map&lt;Integer, String&gt;&gt; result =
        Arrays.stream(esConnectionPropertiesStr.split(&quot;\\),&quot;))
              .map(row -&gt; Arrays.stream(row.split(&quot;,&quot;))
                                .collect(collectingAndThen(toList(), Utils::toIndexedMap)))
              .collect(toList());

huangapple
  • 本文由 发表于 2020年4月8日 22:10:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/61102758.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定