0

I'm trying to learn how to use the Java 8 collections and I was wondering if there was a way to convert my list to a map using a java stream.

    List<PrimaryCareDTO> batchList = new ArrayList<>();

    PrimaryCareDTO obj = new PrimaryCareDTO();
    obj.setProviderId("123");
    obj.setLocatorCode("abc");
    batchList.add(obj);

    obj = new PrimaryCareDTO();
    obj.setProviderId("456");
    obj.setLocatorCode("def");
    batchList.add(obj);

I'm wondering how I would go about creating my list above into a map using a stream. I know how to use the foreach etc with puts, but I was just wondering if there was a more elegant way to build the map using a stream. (I'm aware the syntax below is not correct, I'm new to streams and not sure how to write it)

    AtomicInteger index = new AtomicInteger(0);

    Map<String, Object> result = batchList.stream()
            .map("providerId" + index.getAndIncrement(), PrimaryCareDTO::getProviderId)
            .map("locatorCode" + index.get(), PrimaryCareDTO::getLocatorCode);

The goal is to represent the following.

    Map<String, Object> map = new HashMap<>();

    //Group a
    map.put("providerId1", "123");
    map.put("locatorCode1", "abc");

    //Group b
    map.put("providerId2", "456");
    map.put("locatorCode2", "def");
Code Junkie
  • 7,602
  • 26
  • 79
  • 141
  • similiar question, you can check it. https://stackoverflow.com/questions/35650974/create-list-of-object-from-another-using-java8-streams – ahmettolga Oct 12 '18 at 14:12
  • You need to keep track of the index (and your solution couild break if the stream is parallel for example) and you need to create two map entries for each list item. Those two constraints don't work well with streams. So there may be a solution but it will probably be uglier than using loops. – assylias Oct 12 '18 at 14:12
  • @assylias so you're recommending sticking with a for loop rather than a stream? – Code Junkie Oct 12 '18 at 14:17
  • In that specific example yes. – assylias Oct 12 '18 at 15:18
  • 1
    Possible duplicate of [Java 8 List into Map](https://stackoverflow.com/questions/20363719/java-8-listv-into-mapk-v) – 1201ProgramAlarm Oct 13 '18 at 01:55

2 Answers2

2
...
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Map.Entry;
...

AtomicInteger index = new AtomicInteger(0);

List<SimpleEntry<String, String>> providerIds =
        batchList.stream()
                 .map(e -> new SimpleEntry<>("providerId" + index.incrementAndGet(), e.getProviderId()))
                 .collect(Collectors.toList());

index.set(0);

List<SimpleEntry<String, String>> locatorCodes =
        batchList.stream()
                 .map(e -> new SimpleEntry<>("locatorCode" + index.incrementAndGet(), e.getLocatorCode()))
                 .collect(Collectors.toList());

Map<String, String> map = Stream.of(providerIds,
                                    locatorCodes)
                                .flatMap(e -> e.stream())
                                .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

First it creates two lists, using Entry (from Map) to represent String-String tuples:

  • list with tuples providerId# as 'key' with the values e.g. "123"
  • list with tuples locatorCode# as 'key' with the values e.g. "abc"

It then creates a stream containing these two lists as 'elements', which are then concatenated with flatMap() to get a single long stream of Entry,

(The reason the first two can't stay stream and I have to go through a List and back to stream is because the two invocations of index.incrementAndGet() would otherwise only be evaluated when the streams are consumed, which is after index.set(0);.)

It then creates new key-value pairs with the counter and puts them into a map (with Collectors.toMap().

Mark Jeronimus
  • 9,278
  • 3
  • 37
  • 50
0

You would have to steam twice as you want to add two of the properties to map

    AtomicInteger index = new AtomicInteger(1);

    Map<String, String> result1 = batchList.stream()
            .collect(Collectors
                    .toMap(ignored -> "providerId" + index.getAndIncrement(), PrimaryCareDTO::getProviderId)
                    );

    index.set(1);
    Map<String, String> result2 = batchList.stream()
            .collect(Collectors
                    .toMap(ignored -> "locatorCode" + index.getAndIncrement(), PrimaryCareDTO::getLocatorCode)
                    );

    Map<String, String> result = new HashMap<>();
    result.putAll(result1);
    result.putAll(result2);
gherkin
  • 476
  • 7
  • 24