Фильтровать объекты, сопоставляя его с другим списком по вложенным элементам списка с условием - PullRequest
1 голос
/ 20 июня 2019

Я пытаюсь фильтровать и собирать объекты с условием, используя потоки Java8

У меня есть список экземпляров, который имеет вложенный список элементов

public class Model {
List<Instance> instances;
}
public class Instance {
private String name;
List<Element> elements;
}
public class Element {
private String partNumber;
}

Ниже приведен пример josn

{
    "instances": [
        {
            "name": "instance1",
            "elements": [
                {
                    "partNumber": "partNumber1"
                },
                {
                    "partNumber": "partNumber2"
                }
            ]
        },
        {
            "name": "instance2",
            "elements": [
                {
                    "partNumber": "partNumber3"
                },
                {
                    "partNumber": "partNumber4"
                }
            ]
        }
    ]
}

И другой объект ответа

public class Response {
private List<Domain> domains;
}
public class Domain {
private String name;
private List<Hardware> hardwares;
}
public class Hardware {
private String partNumber;
}

sample json

{
    "domains": [
        {
            "name": "domain1",
            "hardwares": [
                {
                    "partNumber": "partNumber1"
                }
            ]
        },
        {
            "name": "domain2",
            "hardwares": [
                {
                    "partNumber": "partNumber2"
                },
                {
                    "partNumber": "partNumber3"
                },
                {
                    "partNumber": "partNumber4"
                }
            ]
        },
        {
            "name": "domain3",
            "hardwares": [
                {
                    "partNumber": "partNumber5"
                },
                {
                    "partNumber": "partNumber6"
                }
            ]
        }
    ]
}

Я пытаюсь передавать и собирать объекты ответа, сравнивая, если Hardwares из доменапо крайней мере, содержат по одному partnumber от каждого элемента запроса.Это означает, что по крайней мере один hardware от каждого Instance должен присутствовать в Domains hardwares, чтобы считаться Domain действительным.

Для приведенных выше примеров данных,

  1. domain1 не является допустимым доменом, поскольку он содержит только один partnumber partNumber1 от instance1, но не содержит по крайней мере один partnumber от instance2
  2. domain2 является допустимым доменомпотому что он содержит по крайней мере один partnumber partNumber2 из instance1 и содержит по крайней мере один partnumber partNumber3 из instance2.Он может содержать дополнительные номера участников, и это нормально.
  3. domain3 не является допустимым доменом, поскольку он не содержит по крайней мере один partnumber из instance1 и не содержит по крайней мере один partnumber из instance2

Я начал писать

request.getInstances().stream().flatMap(instance -> instance.getElement().stream().filter(element -> response.getDomains().stream().flatMap(domain -> domain.getHardwares.stream().anyMatch(hardware-> element.contains()

, но у меня возникли трудности с завершением, так как у меня ограниченное понимание потоков

1 Ответ

3 голосов
/ 20 июня 2019

Возможно, вы могли бы сделать все это в одном потоке, но вместо этого я бы предложил использовать два потока.Сначала создайте список наборов имен деталей из модели;затем выполните потоковую передачу ответа, чтобы найти домены, в которых для каждого экземпляра есть имя части этого домена, содержащееся в наборе имен частей этого экземпляра.

List<Set<String>> parts = model.getInstances().stream()
        .map(i -> i.getElements().stream()
                .map(Element::getPartNumber)
                .collect(Collectors.toSet()))
        .collect(Collectors.toList());

response.getDomains().stream()
        .filter(d -> parts.stream()
                .allMatch(p -> d.getHardwares().stream()
                        .map(Hardware::getPartNumber)
                        .anyMatch(p::contains)))
        .forEach(System.out::println);

О ваших комментариях: прямо сейчас,это должно удалить все Домены, если существует Экземпляр без Элементов, так как allMatch в этом случае не удастся.Если вместо этого экземпляры без элементов следует просто игнорировать, вы можете добавить еще один filter в первый поток для создания списка parts (не тестировался):

        .filter(i -> ! i.getElements().isEmpty())

или, возможно, i.getElements() != null, в зависимости ото том, как это инициализировано.

...