从“arraylist list=new arraylist()”中选择“list list=new arraylist()”真的合适吗?

mfuanj7w  于 2021-07-12  发布在  Java
关注(0)|答案(3)|浏览(396)

例如,这个问答说 List list = new ArrayList() 是可取的,因为它很容易处理更改,您可以更改到其他列表,例如linkedlist。
然而,在下面的例子中,它真的是可取的吗

List<MyClass> data = new ArrayList<>();

//... long code

Random rand = new Random();
for (int i = 0; i < data.size(); i++) {
    MyClass record = data.get(rand.nextInt(data.size()));
    ...//processing
}

此代码包含太多随机访问。如果继任者读到 List<MyClass> data = new ArrayList<>(); 并认为“好的,任何列表在这个代码上都没有问题。我添加了一些插入处理,将arraylist更改为linkedlist”。当执行过多的随机访问时,这会导致处理过慢。
不仅是列表,除非实现方法以类似的方式工作,否则按接口声明是可取的,不是吗?
编辑:更改为真正的随机访问

j8ag8udp

j8ag8udp1#

一般原则是,变量的类型应该反映它的用途,而不是对象的“构成”(即其内部实现细节)。
在大多数情况下,重要的是对象可以用作列表,而列表由数组“组成”并不重要,因此标准建议是声明一个类型的变量 List<Foo> 而不是 ArrayList<Foo> .
在您的特定情况下,您希望使用对象进行快速随机访问;对象是否由数组“组成”仍然无关紧要,因为任何其他具有快速随机访问的列表实现都可以(例如,的返回值 Arrays.asList )所以在您的案例中应用一般原则,类型应该反映您希望使用它进行快速随机访问的事实。
不幸的是,java没有这样的类型 RandomAccessList<Foo> . 有一个标记接口 RandomAccess 可由实现 List 表示它们支持快速随机访问,但声明为 RandomAccess fooList = new ArrayList(); 因为marker接口没有类似 get .
因此,适当的做法是将变量声明为类型 List<Foo> 或者写一条评论说它应该支持快速随机访问(如果列表是本地创建的),或者检查一下 fooList instanceof RandomAccess 扔一个 IllegalArgumentException 否则(如果列表是从其他地方提供的)。

u0sqgete

u0sqgete2#

在我看来,这取决于兼容性/抽象是否比性能更重要。如果随机访问是函数性的一个关键特性,那么我认为将输入压缩为arraylist是可以接受的,消费者将不得不将其输入转换为arraylist。

vbkedwbf

vbkedwbf3#

您的代码示例以完全相同的方式运行,无论您使用:

List<MyClass> data = new ArrayList<>();

…或您使用:

ArrayList<MyClass> data = new ArrayList<>();

在第一个版本中,通过更通用的接口(或超类)引用对象不会改变任何行为。在上面的两个示例中,您都在操作一个以数组为背景的列表 ArrayList 对象。
在选择的特定实现时 List ,例如 LinkedList 或者 ArrayList ,则必须考虑在代码中可能如何使用该列表。我们有多个实现,因为不同的程序有不同的需求。例如,如果您的程序正在按列表中的特定位置执行许多任意访问,请使用 ArrayList . 如果要在列表中插入/删除多个元素,请使用 LinkedList . 每种 List 有其独特的优势。
通过更通用的接口而不是特定的具体类引用集合的意义在于,当您决定从一种列表更改为另一种列表时,引用该列表的其他代码不会中断。如果您意识到您的代码在列表中间执行插入/删除的次数比按位置执行任意访问的次数要多,您可以更改以下内容:

List<MyClass> data = new ArrayList<>();

…对此:

List<MyClass> data = new LinkedList<>();

…不破坏任何其他涉及 data .
当然,这假设其他代码由接口上可用的方法满足。如果代码需要调用特定于 ArrayList 类,则必须将该列表作为 ArrayList 而不是作为一个 List .
你的最后一段不清楚。你提到的“随机访问太多”和“处理太慢”没有得到解释。因此,如果您的问题尚未得到解决,请编辑您的问题。
顺便说一下,请注意 Collections 班级。从中获取随机元素 List ,您可以复制列表,然后 Collections.shuffle 将元素移动到随机选择的位置。

List< String > names = List.of( "Alice" , "Bob" , "Carol" , "Duke" ) ;
List< String > namesRandom = new LinkedList<>( names ) ;  // Copy the list into a second list to leave the original intact.
Collections.shuffle( namesRandom ) ;  // Move around the element positions within this second list.

查看此代码在ideone.com上的实时运行。

names = [Alice, Bob, Carol, Duke]
namesRandom = [Bob, Carol, Alice, Duke]

相关问题