Java 为什么不是';列表层次结构中的随机访问?
Java 为什么不是';列表层次结构中的随机访问?,java,list,inheritance,Java,List,Inheritance,RandomAccess是Java中的一个标记接口,List实现使用它来指示它们对元素的快速随机访问。既然它是专门为列表实现而设计的,为什么不在列表层次结构中?例如,考虑下面的方法,该方法需要一个随机访问< /代码>列表作为输入,并返回一个随机元素: public <E, L extends List<E> & RandomAccess> E getRandomElement(L list) {...} 我可以向它传递一个声明了类型的列表RandomAccess
RandomAccess
是Java中的一个标记接口,List
实现使用它来指示它们对元素的快速随机访问。既然它是专门为列表
实现而设计的,为什么不在列表
层次结构中?例如,考虑下面的方法,该方法需要一个<代码>随机访问< /代码>列表作为输入,并返回一个随机元素:
public <E, L extends List<E> & RandomAccess> E getRandomElement(L list) {...}
我可以向它传递一个声明了类型的列表
RandomAccess
,它是一个接口,而不是一个具体的类ArrayList
etc随后将实现RandomAccess
,而不是List
,,因为List
比RandomAccess
早几个版本
列表
was接口在1.2中引入,而随机访问
直到1.4(引入时)才添加。他们没有返回并更改世界上所有现有的列表,而是添加了一个标记接口
有关设计决策的更多信息,请查看。我认为答案可能在
随机访问中(重点是我的)
列表
实现使用的标记接口,用于指示它们支持快速(通常为固定时间)随机访问此接口的主要目的是允许通用算法在应用于随机或顺序访问列表时改变其行为,以提供良好的性能。
操作随机访问列表的最佳算法(如ArrayList
)在应用于顺序访问列表(如LinkedList
)时会产生二次行为鼓励通用列表算法在将算法应用于顺序访问列表时,检查给定列表是否为该接口的实例
,并在必要时改变其行为,以确保可接受的性能
似乎他们并不打算给集合类层次结构增加额外的复杂性,而只是为算法提供了一个优化机会
这对我来说是有道理的。算法的用户通常不需要关心实现细节。在列表
上工作的每个算法实现随机访问
也将在不这样做的列表
上工作。唯一的区别是性能
考虑以下情况:
- 对于不提供有效随机访问的
列表
s,没有办法重新编写更有效的算法。(或者还没有人愿意这么做。)在这种情况下,拥有一个缓慢的算法可能比完全没有要好。如果用户经常需要算法,则应切换到不同的列表
实现
- 该算法可以用两种稍有不同的方式重新编写,每种方式都可以为支持和不支持有效随机访问的
列表
产生最佳性能。在这里,用户通常更愿意简单地将其放入列表中
,并让算法决定使用哪个版本。如果使用重载解析而不是运行时类型内省,则在处理抽象列表类型时,用户可能会意外错过优化版本。让调用者每次检查列表
是否是随机访问的实例
会比在算法本身中执行一次更浪费代码。最后,如果一个算法后来被改进为支持两个版本,我们就不需要修改客户机代码
因此,我认为他们这样做是为了积极防止接口被使用,因为您希望使用它。当然,这种选择可能会对合法使用产生负面影响,但这似乎是一种合理的权衡。因为列表可以是链接列表,而链接列表不提供快速随机访问。(访问第k个元素需要O(k)个时间,“快速”意味着恒定的时间。)您所说的“更改世界上所有现有列表”是什么意思?在我的场景中必须更改的列表实际上也必须更改(ArrayList、CopyOnWriteArrayList等)。我不认为任何现有的客户端代码会因为我的建议而中断。如果扩展了列表而不是标记接口,您希望在RandomAccess
中定义什么方法?目前,这只是一种表明List
的给定实现具有某种行为的方式(使用List.get(i)
的for循环将比使用迭代器的for循环运行得更快)。@azurefrog我不认为List.get(i)比随机访问的迭代器快,只有List.get(i)大约有O(1)运行时。此外,ArrayList
无法实现假设的RandomAccess
而不是List
。它不直接实现列表
,而是通过扩展抽象列表
(并非所有抽象列表都支持随机访问)。@azurefrog Java支持在子类中实现更具体的接口,所以这不会有问题。OP意味着随机访问扩展了列表。LinkedList仍将仅实现列表。正确,LinkedList
仍将仅实现List
。
public <E, L extends RandomAccess<E>> E getRandomElement(L list) {...}