Java ArrayList toArray 避免复制

3

有没有一种方法可以在不复制的情况下获取ArrayList的内部数组?

我有一个函数,它以普通Java数组作为输入,我想用ArrayList的内容调用它。问题是我会经常调用它,每次都进行复制将导致性能问题。


2
@HotLicks:链表会使O(1)的随机访问变得棘手... - Oliver Charlesworth
3
真的吗?ArrayList 这个名称暗示了什么意思? - Henry
2
暗示和保证是不同的事情。是的,ArrayList通常是在数组上实现的 - 但它可能不是单个数组;它可以是多个数组,采用模地址选择哪个数组被访问。抽象意味着只要行为符合定义,您就不知道,也不需要知道。 - keshlam
@Henry - "ArrayList"这个名称意味着它可以像数组一样被访问,与内部结构无关。 - Hot Licks
今天,使用特定的JVM内部使用数组。 - Hot Licks
显示剩余4条评论
3个回答

3
static Object[] getBackingArray(ArrayList<?> arrayList) {
    try {
        Field elementData = ArrayList.class.getDeclaredField("elementData");
        elementData.setAccessible(true);
        return (Object[]) elementData.get(arrayList);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

请注意,每次数组列表重新调整大小时都需要再次执行此操作。但是这种方法很脆弱且糟糕,你应该从一开始就不要这样做。
如果在处理数据时需要随机访问,但元素数量可能增加且无法设置上限,则概念上 ArrayList 是完成工作的正确工具。在这种情况下,你应该重构处理代码以使用 Lists。像 ArrayList 这样的随机访问实现可以提供与数组相同的所有功能,因此我认为原则上没有任何问题。

1
脆弱而糟糕,可能在Java的任何其他版本中都无法正常工作...是的。提问者确实说了“任何方式”,这可能是一种方式,因此它是一个正确的答案。我仍然没有决定是否可以放心地点赞它。 - keshlam
在这种情况下,这是独特的解决方案,即使他打破了“失能”也是如此。所以+1。 - Ashot Karakhanyan
请注意,这种(可怕的)方案不会返回数组的大小。 - Hot Licks
1
@HotLicks,你是什么意思?它返回数组本身。您可以像通常一样通过length字段获取其大小。如果您需要ArrayList中实际元素的数量,只需调用size()即可。 - gdejohn

2
使用公共访问支持数组的方式编写自己的数组列表实现,或者使用任何现有的Java集合库中的实现,例如fastutil中的ObjectArrayList<E>具有方法E[] elements()。是的,为了一个单一的类而携带依赖关系可能有点奇怪,但是如果您注意性能,那么您可能会发现集合的基元特殊化很有用。

1
我不知道有没有这样的功能。但是,并没有说你不能创建自己的List实现,它可以包装一个公开的数组。线程安全和可变性 - 如果进一步的附加导致List重新分配数组,则关联将丢失 - 这些都是你必须处理的问题,但是没有理由不能使其工作。
这就是接口的好处 - 如果一个实现没有你需要的特性,你可以创建另一个实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接