Jak to zapisać funkcyjnie?

0

help

public class ContextDataEntry {
    private String id;
    private Map<String, String> parameters = new HashMap();
}
// ...
    public Map<String, Map<String, String>> toData(final List<ContextDataEntry> entries) {
        Map<String, Map<String, String>> result = new HashMap<>();

        entries.forEach(contextDataEntry -> {
            if (!result.containsKey(contextDataEntry.getId())) {
                result.put(contextDataEntry.getId(), new HashMap<>());
            }
            Map<String, String> stringStringMap = result.get(contextDataEntry.getId());
            contextDataEntry.getParameters().forEach((key, value) -> {
                stringStringMap.merge(key, value, (v1, v2) -> v2);
            });
        });
        return result;
    }

nie umiem takiego zgrabnego merdża zrobić :(

Test pod to:

@Test
void test() {
       var result = uut.toData(List.of(new ContextDataEntry("id", Map.of("value", "dupa1")),
                new ContextDataEntry("id2", Map.of("value", "dupa2")),
                new ContextDataEntry("id", Map.of("value", "dupa3"))));
       assertThat(result.get("id").get("value")).isEqualTo("dupa3");
       assertThat(result.get("id2").get("value")).isEqualTo("dupa2");
}
11
  1. Wywalasz wszystkie importy z java.util.* ten pakiet to bryndza, dno, bagno i rozpacz

  2. Dodajesz do projektu io.vavr i robisz import io.vavr.collection.*

  3. Piszesz sobie tak funkcję toData

    public Map<String, Map<String, String>> toData(final List<ContextDataEntry> entries) {
        return entries.groupBy(e -> e.getId())
                .mapValues(v  -> v.foldLeft(HashMap.empty(), (accuMap, elem)-> accuMap.merge(elem.getParameters(), (first,second)->second)));
    }
  4. Koniec

6

Ludzie małej wiary:

    public static Map<String, Map<String, String>> toData2(final List<ContextDataEntry> entries) {
        return entries.stream()
                .collect(Collectors.groupingBy(
                        ContextDataEntry::getId,
                        Collectors.flatMapping(entry -> entry.getParameters().entrySet().stream(), Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue,
                                (first, second) -> second
                        ))
                ));
    }

Wcale nie wygląda specjalnie gorzej niz to vavrowe.

Albo trochę bardziej rozwlekle (niemniej pod spodem ten flatMapping+toMap się do tego sprowadza)

    public static Map<String, Map<String, String>> toData3(final List<ContextDataEntry> entries) {
        return entries.stream()
                .collect(Collectors.groupingBy(
                        ContextDataEntry::getId,
                        Collectors.mapping(ContextDataEntry::getParameters, Collectors.reducing(
                                new HashMap<>(),
                                Function.identity(),
                                ContextDataEntry::combine)
                        ))
                );
    }

    private static Map<String, String> combine(Map<String, String> a, Map<String, String> b) {
        return Stream.of(a, b)
                .map(Map::entrySet)
                .flatMap(Collection::stream)
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (first, second) -> second
                ));
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0