如何使用java流打印嵌套列表,其中Object包含对自身的引用列表

Ros*_*a14 6 java tostring java-8 java-stream

我有一个类似于下图所示的对象:

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 + "]";
  }

}
Run Code Online (Sandbox Code Playgroud)

如何打印objId使用流的列表?

编辑

Obj可以包含Obj列表,它的子节点可以包含obj对象列表.如果深度为5级,是否可以将最顶层obj中的所有objId值打印到第5级的子级值.我想避免嵌套for循环.

Fed*_*ner 5

你应该使用递归.使用流进行此操作的一种可能方法如下:

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(", "));
}
Run Code Online (Sandbox Code Playgroud)

请注意,只要您的Obj实例以树状结构排列,这种方法就可以正常工作.如果你有一个特定的Obj实例,它既是某个级别的父级,又是某个较低级别的子级(即,如果你的Obj实例形成一个图形),这个解决方案将不起作用,你会得到一个巨大的StackOverflowError.


如果你不能修改Obj类,你可以通过在类中接收Objie 的实例的helper方法来实现相同的功能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(", "));
}
Run Code Online (Sandbox Code Playgroud)