【问题标题】:How can I slice an ArrayList out of an ArrayList in Java?如何在 Java 中从 ArrayList 中切出 ArrayList?
【发布时间】:2021-11-07 11:36:52
【问题描述】:

如何在 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,但这种情况不仅会出现在面试问题中,而且会出现在其他人编写的代码中,不能随便更改。同事和图书馆并不总是完美的。

标签: java arraylist


【解决方案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 的子类。然而:

  1. 设计、实施和测试工作量很大。
  2. 您现在已经在代码库中添加了重要的新类,可能依赖于 ArrayList 类的未记录方面(因此“可能发生变化”)方面。
  3. 您需要更改代码库中创建 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);
    

    【讨论】:

    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 2013-07-05
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 2012-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多