Как напечатать вложенный список, используя поток Java, где объект содержит список ссылок на себя - PullRequest
0 голосов
/ 14 октября 2018

У меня есть объект, который выглядит примерно так, как показано ниже:

public class Obj {
  private List<Obj> objs;
  private String objId;

  public List<Obj> getObjs() {
    return objs;
  }

  public String getobjId() {
    return objId;
  }

  @Override
  public String toString() {
    return "Obj [objs=" + objs + ", objId=" + objId + "]";
  }

}

Как мне распечатать список objId с использованием потоков?

EDIT

Obj может содержать список объектов Obj, а его дочерние объекты могут содержать список объектов obj.Если глубина составляет 5 уровней, можно ли распечатать все значения objId от самого верхнего obj до значений дочернего элемента на 5-м уровне.Я хочу избегать вложенных циклов.

Ответы [ 2 ]

0 голосов
/ 14 октября 2018

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

private Stream<Obj> allObjs() {
    return Stream.concat(
        Stream.of(this), 
        objs == null ? Stream.empty() : objs.stream().flatMap(Obj::allObjs));
}

@Override
public String toString() {
    return allObjs()
        .map(Obj::getobjId)
        .collect(Collectors.joining(", "));
}

Обратите внимание, что это работает хорошо, пока ваши Obj экземпляры расположены в древовидной структуре.Если у вас есть конкретный экземпляр Obj, который является одновременно родителем на каком-то уровне и потомком на каком-то более низком уровне (т.е. если ваши Obj экземпляры образуют график), это решение не будет работать, и вы получите огромныйStackOverflowError.


Если вы не можете изменить класс Obj, вы можете достичь того же с помощью вспомогательных методов, которые получают экземпляр Obj, то есть в классе ObjService:

public static Stream<Obj> allObjs(Obj o) {
    if (o == null) return Stream.empty(); // in case the argument is null
    return Stream.concat(
            Stream.of(o), 
            o.getObjs() == null ?
                Stream.empty() :
                o.getObjs().stream().flatMap(ObjService::allObjs));
}

public static String deepToString(Obj o) {
    return ObjService.allObjs(o)
        .map(Obj::getobjId)
        .collect(Collectors.joining(", "));
}
0 голосов
/ 14 октября 2018

Ну, используя Stream, вы можете начать отсюда:

objs.stream().
            map(Obj::getObjId).
            forEachOrdered(System.out::println);

И немного улучшить:

    List<String> collect = objs.stream()
            .filter(Objects::nonNull) // Filter only nonNull objects. Avoid NullPointerException
            .map(Obj::getObjId)
            .peek(System.out::println) // Print the ObjId value from Obj
            .collect(Collectors.toList()); // Return the result to a List, if you need.

Теперь у вас есть основной способ получения значений от детей,Узнайте немного о Stream и улучшите пример кода;)

Несколько приятных ссылок:

Надеюсь, это поможет!

...