当前位置: 首页 > 知识库问答 >
问题:

为什么是收藏。内部使用instanceof check的synchronizedList(list)?

裴楚青
2023-03-14

我正在查看Collections类的源代码。我偶然发现了方法集合。synchronizedList(list)

public static <T> List<T> synchronizedList(List<T> list) {
    return (list instanceof RandomAccess ?
            new SynchronizedRandomAccessList<>(list) :
            new SynchronizedList<>(list));
}

我不明白为什么我们要检查list是否是RAnywhere Access类型。我知道ArrayList实现了这个接口,而LinkedList没有。

此外,SynchronizedRandomAccessList继承SynchronizedList。那么这张支票的意义是什么?请解释一下

共有2个答案

梁盛
2023-03-14

您必须回想一下随机访问标记接口的最初目的。如果您将List传递给另一个方法,它应该能够选择一种适合随机访问或顺序列表的算法。选择正确的算法需要通过list instanceof随机访问对标记接口进行测试。

举个例子

public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
    if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
        return Collections.indexedBinarySearch(list, key);
    else
        return Collections.iteratorBinarySearch(list, key);
 }

(另请参见反向、无序、复制和填充)

现在,如果您只是将列表包装到实现List接口的另一个对象中,所有此类方法都看到是包装器对象,因此此信息会丢失。但是,像同步列表这样的包装器不会改变get等随机访问方法的时间复杂度。因此,如果包装的列表是随机访问列表,则希望包装器也应该实现随机访问,以便接收此类包装器的方法仍然能够检测快速随机访问是否可用。

如果你看一下同步随机访问列表(SynchronizedRandomAccessList)的实现,你会发现它所做的一切,就是扩展同步列表(SynchronizedList)并实现随机访问(RandomAccess),以继承行为并将自身标记为具有快速随机访问。它覆盖的唯一方法是子列表,原因完全相同。如果列表具有有效的随机访问,则其子列表也具有有效的随机访问,因此它们也应该实现随机访问。

static class SynchronizedRandomAccessList<E>
    extends SynchronizedList<E>
    implements RandomAccess {

    SynchronizedRandomAccessList(List<E> list) {
        super(list);
    }

    SynchronizedRandomAccessList(List<E> list, Object mutex) {
        super(list, mutex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        synchronized (mutex) {
            return new SynchronizedRandomAccessList<>(
                list.subList(fromIndex, toIndex), mutex);
        }
    }

请注意,其他包装工厂(如check edList)遵循相同的模式。因此,这甚至在组合工厂时也有效:

System.out.println(
    Collections.synchronizedList(Collections.checkedList(new ArrayList<>(), String.class))
    instanceof RandomAccess);

→ 真的

System.out.println(
    Collections.synchronizedList(Collections.checkedList(new LinkedList<>(), String.class))
    instanceof RandomAccess);

→ 假

储毅
2023-03-14

你就快到了<代码>集合。synchronizedList(list)检查随机访问,因为一些列表实现了随机访问,而其他列表则没有。

这是一个标记接口,就像可序列化的一样。它告诉我们是否可以随机访问列表中的项目。一、 e.从数组列表中,我们可以以相同的计算成本检索任何项。另一方面,我们需要遍历一个链接列表(LinkedList),以获得第n个元素。

那么,集合中发生了什么。synchronizedList(列表)?它将随机访问列表包装成同步列表,而将非随机访问列表包装成非随机访问同步列表。否则,这些列表是相同的。下面是同步随机访问列表的代码。这是一个很好的差分编程示例。这两个类几乎相同。

static class SynchronizedRandomAccessList<E>
    extends SynchronizedList<E>
    implements RandomAccess {

    SynchronizedRandomAccessList(List<E> list) {
        super(list);
    }

    SynchronizedRandomAccessList(List<E> list, Object mutex) {
        super(list, mutex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        synchronized (mutex) {
            return new SynchronizedRandomAccessList<>(
                list.subList(fromIndex, toIndex), mutex);
        }
    }

    private static final long serialVersionUID = 1530674583602358482L;

    /**
     * Allows instances to be deserialized in pre-1.4 JREs (which do
     * not have SynchronizedRandomAccessList).  SynchronizedList has
     * a readResolve method that inverts this transformation upon
     * deserialization.
     */
    private Object writeReplace() {
        return new SynchronizedList<>(list);
    }
}

你可能会问,RandomAccess界面有什么意义?正如霍尔格指出的那样,<代码>集合。binarySearch()基于此接口做出决策。另一个例子是Collections.reverse()。

 类似资料:
  • Spring留档指出: “如果最后两段代码实际上存在于同一个应用程序中,那么可以删除两个RowMapper匿名内部类中存在的重复,并将其提取到单个类(通常是静态内部类)中,然后根据需要由DAO方法引用。” 本例中的“最后两个片段”是使用两个具有相同逻辑的行映射器映射其调用结果的数据库方法。 我的问题是为什么内部RowMapper类需要是静态的。。。还是一定要这样?我的DAO中有一个自动连接的服务方

  • 在中使用会在中创建一个奇怪的空白空间(如底部填充),导致不必要的滚动,因为没有更多的元素要显示。 这个填充随着而增长,我的意思是: 如果在中有0到2个元素,这非常适合屏幕,并且没有滚动。这里工作得很好。 如果在< code > recycle view 中有3到5个元素,这些元素会继续显示在屏幕上,但在这种情况下,会有更多的空白空间,从而导致不必要的滚动。 随着元素的增多,空白区域不断扩大,并创建

  • 我对java.util.HashMap的概念理解如下:

  • 我是个新手,一直在浏览源代码,发现: 这个函数定义这样的内部函数有什么原因吗?为什么不直接写:

  • 问题内容: Python的内部/嵌套类使我感到困惑。没有他们,有什么事情是无法完成的吗?如果是这样,那是什么东西? 问题答案: 引用自http://www.geekinterview.com/question_details/64739: 内部类的优点: 类的逻辑分组 :如果一个类仅对另一个类有用,那么将其嵌入该类并将两者保持在一起是合乎逻辑的。嵌套此类“帮助程序类”可使它们的程序包更加简化。 增

  • 本文向大家介绍lucence内部结构是什么?相关面试题,主要包含被问及lucence内部结构是什么?时的应答技巧和注意事项,需要的朋友参考一下 面试官:想了解你的知识面的广度和深度。 解答: Lucene是有索引和搜索的两个过程,包含索引创建,索引,搜索三个要点。可以基于这个脉络展开一些。