Как выполнить итерацию массива вложенной карты, затем агрегировать значения указанного поля c, собирая его с помощью stream (). Map (); - PullRequest
1 голос
/ 08 апреля 2020

Я хочу получить значения из массива связанных объектов HashMap со значением ключа = "VALUE".

В моем коде ниже я вручную итерировал каждый объект arrayOfObjects, используя stream.map (), затем получил значение полей "VALUE". Затем у каждого объекта arrayOfObjects есть дочерний элемент, который также является массивом объектов, я также собрал значение полей «VALUE», используя stream.map () по отдельности.

        // Object 1
        HashMap<String, Object> outerObject1 = new LinkedHashMap<>();
        outerObject1.put("VALUE", "val1");
        // Child 1 of Object 1
        HashMap<String, Object> inner1Child1 = new LinkedHashMap<>();
        inner1Child1.put("VALUE", "val1Child1");
        // Child 2 of Object 1
        HashMap<String, Object> inner1Child2 = new LinkedHashMap<>();
        inner1Child2.put("VALUE", "val1Child2");
        // Child 3 of Object 1
        HashMap<String, Object> inner1Child3 = new LinkedHashMap<>();
        inner1Child3.put("VALUE", "DUPLICATE");

        List<HashMap<String, Object>> childrenOfOuterObject1 = new ArrayList<>(
                Arrays.asList(inner1Child1, inner1Child2, inner1Child3));
        outerObject1.put("CHILD", childrenOfOuterObject1);

        // Object 2
        HashMap<String, Object> outerObject2 = new LinkedHashMap<>();
        outerObject2.put("VALUE", "val2");
        // Child 1 of Object 2
        HashMap<String, Object> inner2Child1 = new LinkedHashMap<>();
        inner2Child1.put("VALUE", "val2Child1");
        // Child 2 of Object 2
        HashMap<String, Object> inner2Child2 = new LinkedHashMap<>();
        inner2Child2.put("VALUE", "val2Child2");
        // Child 3 of Object 2
        HashMap<String, Object> inner2Child3 = new LinkedHashMap<>();
        inner2Child3.put("VALUE", "DUPLICATE");

        List<HashMap<String, Object>> childrenOfOuterObject2 = new ArrayList<>(
                Arrays.asList(inner2Child1, inner2Child2, inner2Child3));
        outerObject2.put("CHILD", childrenOfOuterObject2);

        List<HashMap<String, Object>> arrayOfObjects = new ArrayList<>(Arrays.asList(outerObject1, outerObject2));

        List<String> outerValues = arrayOfObjects.stream().map(obj -> (String) obj.get("VALUE")).collect(
                Collectors.toList());
        System.out.println(outerValues);

        List<HashMap<String, Object>> innerChildren1 = (List<HashMap<String, Object>>)outerObject1.get("CHILD");
        List<String> innerValues1 = innerChildren1.stream().map(obj -> (String) obj.get("VALUE")).collect(Collectors.toList());
        System.out.println(innerValues1);

        List<HashMap<String, Object>> innerChildren2 = (List<HashMap<String, Object>>)outerObject2.get("CHILD");
        List<String> innerValues2 = innerChildren2.stream().map(obj -> (String) obj.get("VALUE")).collect(Collectors.toList());
        System.out.println(innerValues2);

        Set<String> aggregatedValues = new HashSet<>(outerValues);
        aggregatedValues.addAll(innerValues1);
        aggregatedValues.addAll(innerValues2);

        System.out.println(aggregatedValues);

Мои данные аналогичны структура ниже:

[
    {
        "VALUE": "val1",
        "CHILD": [
            {
                "VALUE": "val1Child1"
            },
            {
                "VALUE": "val1Child2"
            },
            {
                "VALUE": "DUPLICATE"
            }
        ]

    },
    {
        "VALUE": "val2",
        "CHILD": [
            {
                "VALUE": "val2Child1"
            },
            {
                "VALUE": "val2Child2"
            },
            {
                "VALUE": "DUPLICATE"
            }
        ]

    }
]

Я хочу, чтобы мои выходные данные были такими же, как и ниже, без итераций с использованием вложенных L OOP:

[DUPLICATE, val2, val1, val2Child1, val2Child2, val1Child1, val1Child2]

1 Ответ

1 голос
/ 08 апреля 2020

Прежде всего, использование сложного Типа, как вы делаете, HashMap<String, Object>, где Object является списком, не является хорошим выбором, для этого я бы предложил использовать OOP для решения вашей проблемы, поэтому создайте класс как this:

public class MyObject {
    private String value;
    private List<MyObject> child;

    public MyObject(String value) {
        this.value = value;
    }

    public MyObject(String value, List<MyObject> child) {
        this.value = value;
        this.child = child;
    }
    // Getters and setters
}

Во-вторых, сохраните ваши данные, например, так:

List<MyObject> parents = Arrays.asList(
        new MyObject("val1", Arrays.asList(
                new MyObject("val1Child1"),
                new MyObject("val1Child2"),
                new MyObject("DUPLICATE")
        )),
        new MyObject("val2", Arrays.asList(
                new MyObject("val2Child1"),
                new MyObject("val2Child2"),
                new MyObject("DUPLICATE")
        ))
);

и, наконец, вы можете получить значения, подобные этим:

Set<String> result = parents.stream()
        .flatMap(p -> {
            Set<String> values = new HashSet<>();
            values.add(p.getValue());
            values.addAll(p.getChild().stream()
                    .map(MyObject::getValue)
                    .collect(Collectors.toSet()));
            return values.stream();
        }).collect(Collectors.toSet());

и вывод:

[DUPLICATE, val2, val1, val2Child1, val2Child2, val1Child1, val1Child2]
...