0

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??

4
  • 1
    Does this answer your question? Is there a concise way to iterate over a stream with indices in Java 8? Commented Apr 8, 2020 at 14:32
  • Could you explain what is the difference that you are looking other than from the existing questions? Commented Apr 9, 2020 at 8:08
  • The existing question that might look duplicate has simple String which could be easily converted to Map. In my question, I have split String by ), to get list elements and by a comma to get map elements. I have added what I tried but just thought that this could be improved. Commented Apr 9, 2020 at 9:40
  • Can you explain the use-case for having a List<Map<?, ?>> data structure here? If anything else, let's see if we can reduce this to something simpler. Commented Apr 9, 2020 at 14:44

1 Answer 1

1

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());
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.