1

Input: List<Foo> rawdata

Desired Output: Map<Foo, Bar>

Method implementation: Java 8

public Map<Foo, Bar> getMap(List<Foo> rawdata) {
    rawData.stream().flatmap(d -> {
        val key = method1(d);
        val value = method2(d);
    })
    // Now I want to create a map using the Key/Value
    // pair which was obtained from calling method 1 and 2.
}

I did try this:

public Map<Foo, Bar> getMap(List<Foo> rawdata) {
    rawData.stream()
        .flatmap(
            d -> {
                val key = method1(d);
                val value = method2(d);
                return Stream.of(new Object[][]{key, value});
            })
        .collect(Collectors.toMap(
            key -> key[0],
            key -> key[1]));
}

However want to see if there is less expensive way of doing this or any better way.

0

2 Answers 2

5

There's no point in creating an intermediate stream and then using flatMap().

You can just collect() directly into a map:

public Map<Foo, Bar> getMap(List<Foo> rawData) {
    return rawData.stream()
            .collect(Collectors.toMap(foo -> method1(foo), foo -> method2(foo)));
              // OR: Collectors.toMap(this::method1, this::method2);
}
Sign up to request clarification or add additional context in comments.

Comments

0

You can use toMap(keyMapper,valueMapper,mergeFunction) method with three parameters that allows to merge duplicates into a list, for example:

List<String[]> list = List.of(
        new String[]{"Foo1", "Bar1"},
        new String[]{"Foo1", "Bar2"},
        new String[]{"Foo2", "Baz"});

Map<String, List<String>> map1 = list.stream()
        .collect(Collectors.toMap(
                e -> e[0],
                e -> new ArrayList<>(List.of(e[1])),
                (list1, list2) -> {
                    list1.addAll(list2);
                    return list1;
                }));

System.out.println(map1);
// {Foo1=[Bar1, Bar2], Foo2=[Baz]}

If you are sure that there are no duplicates, you can use toMap(keyMapper,valueMapper) method with two parameters:

List<String[]> list = List.of(
        new String[]{"Foo1", "Bar1"},
        new String[]{"Foo2", "Baz"});

Map<String, String> map2 = list.stream()
        .collect(Collectors.toMap(e -> e[0], e -> e[1]));

System.out.println(map2);
// {Foo1=Bar1, Foo2=Baz}

Anyway you can collect a list of Map.Entrys:

List<String[]> list = List.of(
        new String[]{"Foo1", "Bar1"},
        new String[]{"Foo1", "Bar2"},
        new String[]{"Foo2", "Baz"});

List<Map.Entry<String, String>> list1 = list.stream()
        .map(arr -> Map.entry(arr[0], arr[1]))
        .collect(Collectors.toList());

System.out.println(list1);
// [Foo1=Bar1, Foo1=Bar2, Foo2=Baz]

See also: Ordering Map<String, Integer> by List<String> using streams

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.