简体   繁体   中英

Convert String to List of Map

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

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";

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("\\),"))
        .map(e -> Arrays.stream(e.split(","))
                .collect(Collectors.toMap(n1 -> index.incrementAndGet(), s -> s)))
        .peek(i -> index.set(0))
        .collect(Collectors.toList());

Is there any better way to do this??

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

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<Integer, String> toIndexedMap(List<String> list) {
        return IntStream.range(0, list.size())
                        .boxed()
                        .collect(toMap(identity(), list::get));
}

then use the utility methods as follow:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM