首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Immutable.listCopyfOf抛出ArrayIndexOutOfBoundsException

Immutable.listCopyfOf抛出ArrayIndexOutOfBoundsException
EN

Stack Overflow用户
提问于 2013-08-22 15:51:43
回答 2查看 293关注 0票数 3

我使用的是google 11.0.1版本,并有以下代码:

代码语言:javascript
复制
ImmutableList.copyOf(items);

其中项目是一个ConcurrentLinkedQueue。我偶尔会看到这样的错误:

代码语言:javascript
复制
java.lang.ArrayIndexOutOfBoundsException: 10
at java.util.AbstractCollection.toArray(AbstractCollection.java:126)
at com.google.common.collect.ImmutableList.copyFromCollection(ImmutableList.java:278)
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:247)
at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:217)

既然这个问题完全在番石榴图书馆里,有谁知道原因吗?

基于以下正确答案的更新

感谢Wolf卡斯尔的帮助,我成功地在应用程序之外孤立地复制了这个问题。

代码语言:javascript
复制
final int itemsToPut = 30000;

final ConcurrentLinkedQueue<Integer> items = new ConcurrentLinkedQueue<Integer>();
new Thread(new Runnable() {
    public void run() {
       for (int i = 0; i < itemsToPut; i++) {
           items.add(i);
           }
    }
}, "putter-thread").start();
final Iterable<String> transformed = Collections2.transform(items, new Function<Integer, String>() {
    public String apply(Integer integer) {
        return "foo-" + integer;
    }
});
ImmutableList.copyOf(transformed);

每次运行此操作将产生以下结果:

代码语言:javascript
复制
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 21480
    at java.util.AbstractCollection.toArray(AbstractCollection.java:126)
    at com.google.common.collect.ImmutableList.copyFromCollection(ImmutableList.java:278)
    at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:247)
    at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:217)

为了在我的应用程序中解决问题,我找到了许多选项。

离开Collections2

通过从集合转换到Iterables.transform,问题就消失了。

脱离Java1.5

虽然在我的情况下这是不可能的,但我用Java1.6和Java1.7进行了尝试,问题就解决了。我怀疑这是由于AbstractCollection.toArray()中的实现从1.5改为:

1.5

代码语言:javascript
复制
public Object[] toArray() {
    Object[] result = new Object[size()];
    Iterator<E> e = iterator();
    for (int i=0; e.hasNext(); i++)
        result[i] = e.next();
    return result;
}

1.6

代码语言:javascript
复制
public Object[] toArray() {
    // Estimate size of array; be prepared to see more or fewer elements
    Object[] r = new Object[size()];
        Iterator<E> it = iterator();
    for (int i = 0; i < r.length; i++) {
        if (! it.hasNext()) // fewer elements than expected
        return Arrays.copyOf(r, i);
        r[i] = it.next();
    }
    return it.hasNext() ? finishToArray(r, it) : r;
}

复制ConcurrentLinkedQueue first

在非线程安全集合上执行转换显然并不理想。如果出于某种原因,我不得不继续使用collection 2. to,我可以通过首先获取items集合的副本来解决这个问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-22 15:58:52

这似乎是集合的toArray()方法的一个问题。您说您使用的是ConcurrentLinkedQueue,但是堆栈跟踪显示AbstractCollection.toArray。这看起来很可疑,因为java.util.ConcurrentLinkedQueue有自己的toArray实现。

你真正使用的是什么藏品?我怀疑那个收藏品而不是ImmutableList

票数 6
EN

Stack Overflow用户

发布于 2013-08-22 15:55:26

copyOf()执行过程中,列表的大小是否可能发生变化?

如果在方法开始时选中了大小,但是ConcurrentLinkedQueue大小增加了,则会导致ArrayIndexOutOfBoundsException

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18385310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档