java – 展平具有自引用的列表列表

展平具有自引用的列表列表.

我有列表列表,其中包含对自身的引用,我需要展平此列表.
例如.我有清单

A = [ 1, [2,[3]], A, ]

扁平列表看起来像这样

A =[1,2,3]

这是我尝试过的(在Java中):

public static void flattenRecurser(List<Integer> result, List<?> nested) {          
    for (Object item : nested) {
        if (item instanceof List<?> && !freq.containsKey((List<?>) item)) {  
            flattenRecurser(result, (List<?>) item);
        } else if (item instanceof Integer) {
            result.add((Integer) item);
        }
    }
}

我在调用flattenRecurser之前添加嵌套到名为freq的map

static Map<List<?>, List<?>> freq = new HashMap<>();

freq.put(nested,nested);
List<Integer> result = new ArrayList<Integer>();
flattenRecurser(result, nested);

但是当我将嵌套列表放入freq映射时,我收到错误.
查找嵌套对象的哈希码会导致错误.我将如何以不同的方式处理此问题,或者是否有找到嵌套对象的哈希的方法.

这是我得到的错误:

Exception in thread “main” java.lang.StackOverflowError at
java.util.ArrayList.iterator(ArrayList.java:834) at
java.util.AbstractList.hashCode(AbstractList.java:540)

我的代码中根本没有行号834或540

最佳答案 您必须跟踪已添加到结果列表中的列表.你可以使用哈希集来做到这一点,但似乎有一个带有List.hashCode实现的bug(?):当List.toString可以处理包含自引用的列表时,List.hashCode会遇到无限递归.相反,您可以使用System.identityHashCode.

public static List flatten(List flatten, Set<Integer> ignore) {
    List result = new LinkedList();
    ignore.add(System.identityHashCode(flatten));
    for (Object o : flatten) {
        if (o instanceof List) {
            if (! ignore.contains(System.identityHashCode(o))) {
                result.addAll(flatten((List) o, ignore));
            }
        } else {
            result.add(o);
        }
    }
    return result;
}

例:

List C = new ArrayList(Arrays.asList(4, 5, 6));
List B = new ArrayList(Arrays.asList(2, 3, C, 7));
List A = new ArrayList(Arrays.asList(1, B, 8, 9, C));
C.add(C);
B.add(B);
A.add(A);

System.out.println(A);
System.out.println(flatten(A, new HashSet<>()));

输出:

[1, [2, 3, [4, 5, 6, (this Collection)], 7, (this Collection)], 8, 9, [4, 5, 6, (this Collection)], (this Collection)]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

注意,可能存在与该方法的冲突,即具有相同标识哈希码的两个不同列表.在这种情况下,其中一个列表不会添加到结果中.或者,您可以循环整个忽略集,并使用==将每个元素与当前列表进行比较.

点赞