1

I am trying to get a HashMap<String,String> from a CSV String value using Java 8 Streams API. I am able to get the values etc, but how do I add the index of the List as the key in my HashMap.

(HashMap<String, String>) Arrays.asList(sContent.split(",")).stream()
        .collect(Collectors.toMap(??????,i->i );

So my map will contain like Key ,Value as below.

0->Value1
1->Value2
2->Value3
...

Using Normal Java I can do it easily but I wanted to use the JAVA 8 stream API.

3 Answers 3

2

That’s a strange requirement. When you call Arrays.asList(sContent.split(",")), you already have a data structure which maps int numbers to their Strings. The result is a List<String>, something on which you can invoke .get(intNumber) to get the desired value as you can with a Map<Integer,String>

However, if it really has to be a Map and you want to use the stream API, you may use

Map<Integer,String> map=new HashMap<>();
Pattern.compile(",").splitAsStream(sContent).forEachOrdered(s->map.put(map.size(), s));

To explain it, Pattern.compile(separator).splitAsStream(string) does the same as Arrays.stream(string.split(separator)) but doesn’t create an intermediate array, so it’s preferable. And you don’t need a separate counter as the map intrinsically maintains such a counter, its size.

The code above in the simplest code for creating such a map ad-hoc whereas a clean solution would avoid mutable state outside of the stream operation itself and return a new map on completion. But the clean solution is not always the most concise:

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

While the first two arguments to collect define an operation similar to the previous solution, the biggest obstacle is the third argument, a function only used when requesting parallel processing though a single csv line is unlikely to ever benefit from parallel processing. But omitting it is not supported. If used, it will merge two maps which are the result of two parallel operations. Since both used their own counter, the indices of the second map have to be adapted by adding the size of the first map.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use below approach to get you the required output

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

I have written below test to verify the output.

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

    }

Comments

0

You can do it creating a range of indices like this:

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

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.