RandomAccess
是List
实现中使用的Java标记接口,表示它们可以快速随机访问其元素。由于它是专为List
实现而设计的,为什么不在List
层次结构中?例如,请考虑以下方法,该方法需要RandomAccess
列表作为输入并返回随机元素:
public <E, L extends List<E> & RandomAccess> E getRandomElement(L list) {...}
我必须将此方法传递给匿名列表或声明类型为ArrayList<E>
的列表,这是一个具体的类,而不是使用某些接口(如List<E>
声明的列表)。但是,如果RandomAccess
已参数化并已扩展List<E>
,那么我的方法可能如下所示:
public <E, L extends RandomAccess<E>> E getRandomElement(L list) {...}
我可以传递一个声明类型为RandomAccess<E>
的列表,这是一个接口,而不是具体的类。然后ArrayList<E>
等会实施RandomAccess<E>
,而不是List<E>
。
答案 0 :(得分:2)
我认为答案可能在RandomAccess
List
(强调我的)。
ArrayList
实现使用的标记接口,表示它们支持快速(通常是恒定时间)随机访问。 此接口的主要目的是允许通用算法更改其行为,以便在应用于随机或顺序访问列表时提供良好的性能。操作随机访问列表(例如
LinkedList
)的最佳算法在应用于顺序访问列表(例如instanceof
)时会产生二次行为。 鼓励使用通用列表算法检查给定列表是否为List
此接口,然后再应用一种算法,如果将其应用于顺序访问列表,则会提供较差的性能,并更改其必要时的行为以保证可接受的表现。
似乎他们并不打算为集合类层次结构添加额外的复杂性,而只是为算法提供优化机会。
这确实对我有意义。算法的用户通常不需要关心实现细节。适用于RandomAccess
实施List
的每个算法也适用于不List
的{{1}}。唯一的区别是表现。
考虑以下情况:
List
提高效率。 (或者没有人觉得这样做了。)在这种情况下,拥有一个缓慢的算法可能仍然比没有算法更好。如果用户经常需要算法,则应切换到不同的List
实现。List
的最佳性能,这些性能支持和不支持高效的随机访问。在这里,用户通常更喜欢简单地放入List
并让算法决定使用哪个版本。如果使用重载决策而不是运行时类型内省,则在处理抽象List
类型时,用户可能会意外错过优化版本。每次调用者都会检查instanceof
是RandomAccess
{{1}}是否比算法本身更多地执行代码。最后,如果稍后改进算法以支持两个版本,我们不需要改变客户端代码。因此,我认为他们是按照他们的方式做的,以便主动阻止使用它的界面。当然,这种选择可能会对合法用途产生负面影响,但这似乎是一种合理的权衡。
答案 1 :(得分:1)
因为List
早于RandomAccess
几个版本。
List
界面是在1.2中引入的,并且RandomAccess
没有被添加到1.4(引入Java Collections Framework时)。他们只是添加了一个标记界面,而不是返回并更改世界上所有现有的列表。
有关设计决策的更多信息,请查看FAQ。
答案 2 :(得分:-1)
因为List
可能是链接列表,并且链接列表不提供快速随机访问。 (访问 k th元素需要O( k )时间,“fast”表示恒定时间。)