【问题标题】:Filtering objects with circular reference to itself (ObjectA has property List<ObjectA>)过滤具有对自身的循环引用的对象(ObjectS 具有属性 List<Object>)
【发布时间】:2016-10-14 18:01:54
【问题描述】:

我有一个带有嵌套值的大型 json 结构,我已将其转换为要使用的对象列表。我想过滤掉所有不包含特定属性值的对象。问题是,到目前为止,我所想出的只是 for 循环中的 for 循环中的 for 循环(并且假设我们知道 json 结构只有三个嵌套级别)。我只想过滤掉包含整数的对象(如果它为空,它可能是包含有效内容的父对象)或为空的父对象)。如果我尝试使用扁平化进行流式传输 - 我可以过滤掉所有对象和嵌套对象,但不会丢失我的结构吗?

快速例如。

public class ObjectA { 
 Integer id;
 List<ObjectA> sublist;
}


List<ObjectA> fullList;
Set<Integer> keeptheseIntegers;
for (ObjectA obj : fullList) {
  if (obj.getId() != null && !keeptheseIntegers.contains(obj.getId()){
  fullList.remove(obj);
  }  else if (obj.getId() == null && obj.getSubList().size() > 0) {
  for (ObjectA subObj : obj.getSubList()){
   (same thing as above)
  }
}

edit - 后来我确实意识到删除无法正常工作并使用了 iterator.remove。虽然仍然是同样的逻辑问题

【问题讨论】:

  • 你的意思是 ObjectA 包含一个有效的 Integer 或一个有效的 subList,但不能同时包含这两者?
  • 我假设 fullList.remove(obj) 会抛出异常,因为它不允许在自己的迭代器中更改集合。
  • 是的,我会编辑,哈哈,我确实最终使用了 iterator.remove,但同样的逻辑问题是需要在循环中循环等。好吧,是的,我想这是正确的,因为自结束节点以来有效整数/子列表应该是一个有效整数。

标签: java json loops java-stream circular-reference


【解决方案1】:

首先:我会在算法过程中将想要的项目收集到自己的列表中,而不是操纵您的原始结构(删除不需要的)。

第二:遍历嵌套结构是递归模式的一个很好的候选者。

第三:使用 java 8 我会使用流和 lambdas 来实现它。

类似这样的:

public class ObjectA
{
    Integer id;
    List<ObjectA> sublist;
}

private static final Set<Integer> keeptheseIntegers = new HashSet<>();
static
{
    keeptheseIntegers.add( 1 );
}

private List<ObjectA> filter( List<ObjectA> list)
{
    List<List<ObjectA>> subLists = new ArrayList<>();
    List<ObjectA> result = list.stream()
            // get all objects with sublist and add the sublist to interim subLists:
            .peek( obj -> {
                if ( obj.sublist == null )
                {
                    // assert your assumption that Integer is assigned
                    if ( obj.id == null )
                    {
                        throw new IllegalArgumentException();
                    }
                }
                else
                {
                    subLists.add( obj.sublist );
                }
            } )
            // filter for the objects you want in result:
            .filter( (obj -> obj.id != null && keeptheseIntegers.contains(obj.id)))
            // and convert the resulting stream to a list:
            .collect( Collectors.toList());

    // call this method recusively for all found sublists:
    subLists.forEach( i -> result.addAll(filter( i)) );
    return result;
}

在你的主程序流程中你称之为:

...
List<ObjectA> fullList = new ArrayList<>();
List<ObjectA> objWithInt = filter( fullList);
// process the received list. Your original fullList is unchanged.

【讨论】:

  • 嘿@Heri 感谢您的建议和对延迟响应表示歉意 - 但是,创建的列表似乎根本没有嵌套 - 所以结果只是一个扁平列表而不是包含层次结构
猜你喜欢
  • 2019-09-16
  • 1970-01-01
  • 2020-09-02
  • 2013-12-12
  • 2012-01-17
  • 2016-08-03
  • 1970-01-01
  • 2012-12-24
  • 1970-01-01
相关资源
最近更新 更多