2

从我以前的一本旧 Java 认证书中提取了一个面试问题。

不想真正想知道这是否是一个好的面试问题。它的目的是作为一个简单的健全性检查,该人已经在 J​​ava 中使用简单的集合进行了足够的工作......我没想到一个不正确的答案,无论如何,他们在几个步骤中都弄错了......所以它达到了它的目的.

令我惊讶的部分是,在将它放入 RAD 并运行它之后,它是第 8 步的输出...... java 的行为就像在 addAll 之后的 list1 没有保存 list2 中包含的值,引用list2 中的值?!由于 list2 的清除改变了 list1 的内容?!?

然而,在第 7 步清除之前对 list2 的修改对列表 1 没有影响......我一天的工作现在将通过收集实施的文档脱轨哈哈......这根本不是我所期望的......可以有人在第 8 步解释 list1 内容的原因吗?

public static void main(String[] args)
{
    List list = new ArrayList();
    System.out.println("1: List1 Post - Constructor\t\t" + list);
    System.out.println();

    list.add("1");
    System.out.println("2: List1 Post - Add 1\t\t\t\t" + list);
    System.out.println();

    list.add("2");
    System.out.println("3: List1 Post - Add 2\t\t\t\t" + list);
    System.out.println();

    list.add(1,"3");
    System.out.println("4: List1 Post - Add three at index 1\t\t" + list);
    System.out.println();

    List list2 = new ArrayList(list);
    System.out.println("5: List1 Post - list2 Constructor\t\t" + list);
    System.out.println("5: List2 Post - list2 Constructor\t\t" + list2);
    System.out.println();

    list.addAll(list2);
    System.out.println("6: List1 Post - Add list2 to list1\t\t" + list);
    System.out.println("6: List2 Post - Add list2 to list1\t\t" +list2);
    System.out.println();

    list2 = list.subList(2,5);
    System.out.println("7: List1 Post - List 2 sublist of list 2,5\t" + list);
    System.out.println("7: List2 Post - List 2 sublist of list 2,5\t" + list2);
    System.out.println();

    list2.clear();
    System.out.println("8: List1 Post - list2 clear\t\t\t" + list);
    System.out.println("8: List2 Post - list2 clear\t\t\t" + list2);
    System.out.println();
}

1: List1 Post - Constructor                 []    
2: List1 Post - Add 1                       [1]    
3: List1 Post - Add 2                       [1, 2]    
4: List1 Post - Add three at index 1        [1, 3, 2]    
5: List1 Post - list2 Constructor           [1, 3, 2]    
5: List2 Post - list2 Constructor           [1, 3, 2]    
6: List1 Post - Add list2 to list1          [1, 3, 2, 1, 3, 2]    
6: List2 Post - Add list2 to list1          [1, 3, 2]    
7: List1 Post - List 2 sublist of list 2,5  [1, 3, 2, 1, 3, 2]    
7: List2 Post - List 2 sublist of list 2,5  [2, 1, 3]    
8: List1 Post - list2 clear                 [1, 3, 2]    
8: List2 Post - list2 clear                 []
4

2 回答 2

4

由于 list2 的清除改变了 list1 的内容

是的。因为ArrayList.subList遵循以下记录的行为List.subList

返回此列表在指定的 fromIndex(包括)和 toIndex(不包括)之间的部分的视图。(如果 fromIndex 和 toIndex 相等,则返回列表为空。)返回列表由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。

这种方法消除了显式范围操作的需要(通常存在于数组中的那种)。通过传递 subList 视图而不是整个列表,任何需要列表的操作都可以用作范围操作。例如,以下习惯用法从列表中删除一系列元素:

 list.subList(from, to).clear();

特别给出了一个通过调用clear子列表视图来删除列表的一部分的示例。

于 2013-11-12T18:02:19.387 回答
1

每当ArrayList.subList(fromIndex, toIndex)调用该函数时,它都会返回一个SubList类的实例:

public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

ArrayList类中,SubList是一个实现的私有内部类:

private class SubList extends AbstractList<E> implements RandomAccess {
        private final AbstractList<E> parent;
        private final int parentOffset;
        private final int offset;
        int size;

        SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) {
            // constructor assignment variable
        }
        // other implemented function
 }

这个类有几个实现的功能,包括:get(), set(int index, E e), size(), add(E e), remove(E e), removeRange(int fromIndex, int toIndex)等等;调用最终对parent AbstractList. 为了与您的上下文相关,让我们查看removeRange(int fromIndex, int toIndex)函数的实现:

protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        parent.removeRange(parentOffset + fromIndex,
                           parentOffset + toIndex);   // <--- removing parent
        this.modCount = parent.modCount;
        this.size -= toIndex - fromIndex;
    }

作为SubList扩展AbstractList类,其clear()功能实现如下:

public void clear() {
        removeRange(0, size());
    }

因此,调用clear()返回的列表实例的函数ArrayList.subList(fromIndex, toIndex)会对其自身进行更改ArrayList。该文档通过以下语句支持此实现:

返回此列表在指定的 fromIndex(包括)和 toIndex(不包括)之间的部分的视图。(如果 fromIndex 和 toIndex 相等,则返回列表为空。)返回列表 由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。返回的列表支持所有可选的列表操作

.

于 2013-11-12T18:26:55.433 回答