为什么列表层次结构中没有RandomAccess?

Pet*_*Pro 5 java inheritance list

RandomAccess是Java中的标记接口,用于List表示它们可以快速随机访问其元素.由于它是专门为List实现而设计的,为什么不在List层次结构中呢?例如,请考虑以下方法,该方法需要RandomAccess列表作为输入并返回随机元素:

public <E, L extends List<E> & RandomAccess> E getRandomElement(L list) {...}
Run Code Online (Sandbox Code Playgroud)

我必须将此方法传递给匿名列表或具有声明类型的列表ArrayList<E>,具体类,而不是使用某些接口声明的列表List<E>.但是,如果RandomAccess参数化和扩展List<E>,那么我的方法可能如下所示:

public <E, L extends RandomAccess<E>> E getRandomElement(L list) {...}
Run Code Online (Sandbox Code Playgroud)

我可以传递一个声明类型的列表RandomAccess<E>,这是一个接口,而不是具体的类.ArrayList<E>然后才会实施RandomAccess<E>,而不是List<E>.

5go*_*der 2

我认为答案可能在(强调我的)的文档RandomAccess中。

实现使用标记接口List来指示它们支持快速(通常是恒定时间)随机访问。 该接口的主要目的是允许通用算法改变其行为,以便在应用于随机或顺序访问列表时提供良好的性能。

操作随机访问列表(例如ArrayList)的最佳算法在应用于顺序访问列表(例如LinkedList)时可以产生二次行为。 鼓励通用列表算法在应用算法之前检查给定列表是否是instanceofthis 接口,如果将其应用于顺序访问列表,则性能会很差,并在必要时更改其行为以保证可接受的性能。

看起来他们并不打算给集合类层次结构增加额外的复杂性,而只是为算法提供优化机会。

这对我来说确实有一定道理。算法的用户通常不需要关心实现细节。每个适用于List实现的算法RandomAccess也适用于List不执行此操作的算法。唯一的区别是性能。

考虑以下情况:

  • List对于不提供高效随机访问的 s,没有办法重写算法来提高其效率。(或者还没有人愿意这样做。)在这种情况下,有一个缓慢的算法可能仍然比没有更好。如果用户经常需要该算法,则应该切换到不同的List实现。
  • 该算法可以用两种略有不同的方式重写,每种方式都能为List支持和不支持高效随机访问的 s 提供最佳性能。在这里,用户通常更愿意简单地输入List并让算法决定使用什么版本。如果使用重载解析而不是运行时类型自省,则用户在处理抽象List类型时可能会意外错过优化版本。让调用者每次都检查代码是否List乱七八糟instanceof RandomAccess,比在算法本身中检查一次要多。最后,如果以后改进算法以支持两个版本,我们无需去更改客户端代码。

因此,我认为他们这样做是为了主动阻止接口被按照您希望的方式使用。当然,这种选择可能会对合法用途产生负面影响,但这似乎是一个合理的权衡。