如何在 Java 中从 ArrayList 中切出 ArrayList?

Posted

技术标签:

【中文标题】如何在 Java 中从 ArrayList 中切出 ArrayList?【英文标题】:How can I slice an ArrayList out of an ArrayList in Java? 【发布时间】:2010-12-01 15:03:09 【问题描述】:

如何在 Java 中获取 ArrayList 的数组切片?具体来说,我想做这样的事情:

ArrayList<Integer> inputA = input.subList(0, input.size()/2);
// where 'input' is a prepouplated ArrayList<Integer>

所以我希望这可以工作,但 Java 返回一个 List - 所以它是不兼容的。当我尝试转换它时,Java 不会让我这样做。我需要ArrayList - 我该怎么办?

【问题讨论】:

你为什么坚持使用ArrayList?我认为您可能对接口的工作方式缺乏了解,因为ListArrayList 并非“不兼容”——ArrayList 实现了List,而List 可能包含您需要的所有必要方法。 我坚持使用ArrayList,因为它是一个带有严格方法原型的inteview问题。我显然缺乏理解,因为 subList 应该返回一个 List 类型,但我不能将返回的 List 转换为 ArrayList。所以你告诉我男人.. 他完全有可能需要一个ArrayList,因为他需要用它调用一个接受ArrayList 的方法。可以说这种方法设计得很糟糕,应该接受List,但这种情况不仅会出现在面试问题中,而且会出现在其他人编写的代码中,不能随便更改。同事和图书馆并不总是完美的。 见***.com/questions/1279476/… 【参考方案1】:

在 Java 中,使用接口类型而不是 API 中的具体类是一种很好的做法。

您的问题是您1 正在使用ArrayList(可能在很多地方)您真正应该使用List。结果,您为自己制造了一个不必要的限制,即列表是ArrayList

你的代码应该是这样的:

List input = new ArrayList(...);

public void doSomething(List input) 
   List inputA = input.subList(0, input.size()/2);
   ...


this.doSomething(input);

1 - 根据您的 cmets,“您”实际上是其他人......在面试问题中提出了这个问题。这可能实际上是一个技巧问题,旨在了解如何处理创建与 ArrayList 兼容的分配的 ArrayList 的(真实)切片。


您对问题提出的“解决方案”是/是这样的:

new ArrayList(input.subList(0, input.size()/2))

这可以通过制作子列表的副本来实现。它不是正常意义上的切片。此外,如果子列表很大,那么制作副本会很昂贵。


如果您受限于您无法更改的 API,以至于您必须inputA 声明为 ArrayList,您或许可以实现一个ArrayList 的自定义子类,其中subList 方法返回ArrayList 的子类。然而:

    设计、实施和测试工作量很大。 您现在已经在代码库中添加了重要的新类,可能依赖于 ArrayList 类的未记录方面(因此“可能发生变化”)方面。 您需要更改代码库中创建 ArrayList 实例的相关位置,以改为创建子类的实例。

“复制数组”解决方案更实用……请记住,这些不是真正的切片。

【讨论】:

其实subList不会做拷贝;它返回原始列表中的视图 (docs.oracle.com/javase/6/docs/api/java/util/…) 实际上@Matthew,我指的是他这样做的 OP 的自我回答:new ArrayList(input.subList(0, input.size()/2)) +1 表示这句话:在 Java 中,使用接口类型而不是 API 中的具体类是一种很好的做法。【参考方案2】:

如果您知道需要从 ArrayList 中删除的元素的 startIndex 和 endIndex,我已经找到了一种方法

al 是原始的ArrayList 和startIndex,endIndex 分别是要从数组中删除的开始和结束索引:

al.subList(startIndex, endIndex + 1).clear();

【讨论】:

【参考方案3】:

如果没有现有方法,那么我猜你可以从 0 迭代到 input.size()/2,获取每个连续元素并将其附加到新的 ArrayList。

编辑:实际上,我认为您可以使用该 List 并使用 one of the ArrayList constructors 实例化一个新的 ArrayList。

【讨论】:

这正是我所做的(在我阅读您的编辑之前发布了我的答案)。谢谢:) 但是 复制 List 以创建一个新的 ArrayList。 @BT - 郑重声明,这不是“切片”一词在此上下文中的通常含义。【参考方案4】:

虽然这篇文章很老了。万一有人在找这个..

Guava 有助于将 List 划分为指定大小的子列表

List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
    List<List<Integer>> subSets = Lists.partition(intList, 3);

【讨论】:

Guava Lists 文档的快速链接:google.github.io/guava/releases/19.0/api/docs/com/google/common/…【参考方案5】:

我就是这样解决的。我忘记了 sublist 是对原始列表中元素的直接引用,所以它为什么不起作用是有道理的。

ArrayList<Integer> inputA = new ArrayList<Integer>(input.subList(0, input.size()/2));

【讨论】:

以上是关于如何在 Java 中从 ArrayList 中切出 ArrayList?的主要内容,如果未能解决你的问题,请参考以下文章

Android - 从方形位图中切出一个圆圈

从背景中切出的透明文本

从背景中切出的透明文本

MATLAB / Octave:从图像中切出很多圆圈

在 Java 中从 ArrayList 中删除对象

递归学习中碰到的坑