只是好奇...更好的方式复制/克隆ArrayList的一部分?

时间:2011-08-11 15:31:12

标签: java collections

复制部分ArrayList比我正在做的更有效/更快/更敏感吗?

 public ArrayList<FooObject> getListOfFlagged() {    
        for(FooObject fooObject: foos) {
            //for each item in the original array, where the item isFlagged...
            if(fooObject.isFlagged) {
                someOtherArray.add(fooObject);
            }
        }    
        return someOtherArray;
    }

4 个答案:

答案 0 :(得分:3)

您可以使用Collections2.filter()中的guava方法。它看起来更具功能性:

    Collections2.filter(foos, new Predicate<FooObject>() {
        @Override
        public boolean apply(FooObject input) {
            return fooObject.isFlagged();
        }
    })

结果由原始foos集合支持,因此如果您需要副本,则必须使用new ArrayList<FooObject>(filteredCollection)制作防御性副本。

答案 1 :(得分:1)

使用番石榴:

    class FooObject{boolean isFlagged(){return true;}}      
    List<FooObject> foos = Lists.newArrayList();
    Lists.newArrayList(
        Iterables.filter(foos, new Predicate<FooObject>(){
            @Override public boolean apply(FooObject input) {
                return input.isFlagged();
            };
        })
    );

答案 2 :(得分:0)

否则没有,除非您对需要复制的元素的位置有所了解。

说,您需要复制50个元素数组的元素10-19,然后分配10个元素的数组,使用System.arrayCopy()会更快。

答案 3 :(得分:0)

一个重要的优化是预先分配“someOtherArray”中的元素数量,因为否则它会进行许多重新分配 - 当然,这取决于您要处理的项目数量。由于我们事先并不知道结果大小,最简单的方法是使用

someOtherArray的容量设置为foos的大小
someOtherArray.ensureCapacity(foos.size());

当然,如果foos很大并且通常只会标记一些项目,那么这是没有意义的。

另请注意,您的方法应该首先清除()someOtherArray。

我能想到的另一个优化是如何访问foos的元素。您可以尝试使用典型的for (int i = 0; i < size; i++)循环,并使用fooObject初始化foos.get(i)。如果通过获取数组中元素的副本来实现“extended for”,或者也可能获得迭代器,那么这种方式可能会更快。但我认为迭代ArrayList会在编译器中获得特殊优化......也许其他人在该领域有经验。