从列表中删除不相关的项目与构建包含相关项目的新列表

时间:2013-10-02 12:02:15

标签: java list arraylist

我正逐像素地检测位图中的数字。每个数字都以一个像素的大小开始。大多数数据都在增长,但有些数字还很小。

我在ArrayList中按顺序收集数字。在下一步中,我想减少列表删除小数字。

第一步收集大约1500个数字。第二步删除了约1/3。

表现更好:

  1. 从列表中删除项目
    由于使用LinkedList删除项目效果更佳:
    • 我可以在第一步中使用LinkedList但是然后构建此列表比使用ArrayList表现更差(因为创建LinkedList项目的成本比将对象添加到ArrayList
      因此
    • 我仍然使用每次都有的ArrayList将删除的项目后的项目复制到已删除项目的位置。为了减少要复制的项目数量,我可以从最后一个索引开始遍历列表。
  2. 建立一个只有更大数字的新列表
    • 我创建了一个新的ArrayList,用3/4大小的原始数据列表初始化它,然后只将更大的数字添加到新列表中。
  3. 我想,使用这么几个项目,没有一个选项会带来可衡量的性能提升。但是对于更多的物品来说效果更好?

4 个答案:

答案 0 :(得分:2)

使用以下测试程序,我找到了

的ArrayList

1000个对象引用,25%要从arrayList中删除;

  • 从现有的arraylist中删除; 0.565ms
  • 重新创建一个新的arrayList; 0.573ms

100000个对象引用,25%要从arrayList中删除;

  • 从现有的arraylist中删除; 1028ms
  • 重新创建一个新的arraylist; 8.66ms
  • 重新创建新的arraylist(预设); 2ms的

在小规模上,它并不重要,在大规模上创建新列表是关键,最好是预先设定

HashSet的

1000个对象引用,25%要从arrayList中删除;

  • 从现有的hashset中删除; 0.602ms
  • 重新创建新的哈希集; 2.64ms

100000个对象引用,25%要从arrayList中删除;

  • 从现有的hashset中删除; 28ms
  • 重新创建新的哈希集;仅为37微秒

在小尺度上从现有的集合中移除似乎更快,但两者都可以在重要的尺度上进行比较。

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import javax.vecmath.Vector3d;

public class Test {

        public static void main(String[] args){
            voidTestArrayList(100000);
            voidTestHashSet(100000);


        }



        public static void voidTestArrayList(int samples){
            {
                Collection<Vector3d> collectionArrayList=new ArrayList<Vector3d>();
                 preamble(collectionArrayList,samples);
                 testRemoveQuarter(collectionArrayList);
            }
            {
                Collection<Vector3d> collectionArrayList2=new ArrayList<Vector3d>();
                Collection<Vector3d> collectionArrayListDestination=new ArrayList<Vector3d>();
                preamble(collectionArrayList2,samples);

                testRetain3Quarter(collectionArrayList2,collectionArrayListDestination);
            }
            {
                Collection<Vector3d> collectionArrayList3=new ArrayList<Vector3d>();
                preamble(collectionArrayList3,samples);
                Collection<Vector3d> collectionArrayListDestination3=new ArrayList<Vector3d>(collectionArrayList3.size());
                testRetain3QuarterPresized(collectionArrayList3,collectionArrayListDestination3);
            }
        }

        public static void voidTestHashSet(int samples){
             Collection<Vector3d> collectionHashSet=new HashSet<Vector3d>();
             preamble(collectionHashSet,samples);
             testRemoveQuarter(collectionHashSet);

             Collection<Vector3d> collectionHashSet2=new HashSet<Vector3d>();
             Collection<Vector3d> collectionHashSetDestination=new HashSet<Vector3d>();
             preamble(collectionHashSet2,samples);

             testRetain3Quarter(collectionHashSet2,collectionHashSetDestination);

        }

        public static void voidTestRemoveFromArrayList(){
             Collection<Vector3d> collectionArrayList=new ArrayList<Vector3d>();
             preamble(collectionArrayList,1000);
             testRemoveQuarter(collectionArrayList);
        }


        public static void preamble(Collection<Vector3d> collection, int numberToAdd){
            //not part of timed test
            for(int i=0;i<numberToAdd;i++){
                collection.add(new Vector3d(Math.random(),Math.random(),Math.random()));
            }
        }

        public static void testRemoveQuarter(Collection<Vector3d> collection){
            Iterator<Vector3d> iterator=collection.iterator();

            int counter=0;
            while(iterator.hasNext()){
                counter++;
                iterator.next();
                if ((counter%4)==0){
                    counter=0;
                    iterator.remove();
                }
            }
        }

        public static void testRetain3QuarterPresized(Collection<Vector3d> collection, Collection<Vector3d> destinationCollection){
            testRetain3Quarter(collection, destinationCollection);
        }
        public static void testRetain3Quarter(Collection<Vector3d> collection, Collection<Vector3d> destinationCollection){
            Iterator<Vector3d> iterator=collection.iterator();

            int counter=0;
            while(iterator.hasNext()){
                counter++;
                Vector3d processing=iterator.next();
                if ((counter%4)!=0){
                    counter=0;
                    destinationCollection.add(processing);
                }
            }
        }

}

N.B。重要的是要注意,就集合而言,它包含对象的引用,因此我对特定类对象的选择是无关紧要的

答案 1 :(得分:0)

您应该对不同的java.util.List实现进行基准测试,重点关注添加和删除元素。

答案 2 :(得分:0)

如果坚持ArrayList我会说第二种选择更快。但你应该自己对它进行基准测试,并尝试LinkedList变体。据我所知,由于Java LinkedList是双链表,因此最后添加元素往往比使用ArrayList更快。特别是如果你不知道初始尺寸。

答案 3 :(得分:0)

我建议像这样的基准:

List<Object> arrayRemove = new ArrayList<Object>(initialMax);
List<Object> arrayCopy = new ArrayList<Object>((int) (initialMax * (1+retain)/2));
List<Object> linkedRemove = new LinkedList<Object>();
List<Object> linkedCopy = new LinkedList<Object>();

for (int i = 0; i < initialMax; i++) {
    arrayRemove.add(new Object());
    linkedRemove.add(new Object());
}

Random rnd = new Random();
//Begin benchmarking
for (int i = 0; i < initialMax; i++) {
    if (rnd.nextDouble() < retain) {
        linkedCopy.add(arrayRemove.get(i)); //1.
        // arrayCopy.add(arrayRemove.get(i)); //2. (same code but...)
    } else {
        // linkedRemove.remove(0); //3.
        // arrayRemove.remove(0); //4.
    }
}
// End benchmarking

其中initialMax = 1500; retain = 2/3并且您分别测试所有四种方法 此外,当您的“数字”可以按随机顺序排列时,请考虑使用HashSet


修改

(基本)测试表明方法4没用,其他方法速度大致相同:

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;


public class Test {
private static final int initialMax = 150000;
private static final double retain = 2/3;

public static void main(String[] args) {
    List<Object> arrayRemove = new ArrayList<Object>(initialMax);
    List<Object> arrayCopy = new ArrayList<Object>((int) (initialMax * (1+retain)/2));
    List<Object> linkedRemove = new LinkedList<Object>();
    List<Object> linkedCopy = new LinkedList<Object>();

    for (int i = 0; i < initialMax; i++) {
        arrayRemove.add(new Object());
        linkedRemove.add(new Object());
    }

    Random rnd = new Random();
    //Begin benchmarking
    Date[] ds = new Date[5];
    ds[0] = new Date();
    for (int i = 0; i < initialMax; i++) {
        if (rnd.nextDouble() < retain) {
            linkedCopy.add(arrayRemove.get(i)); //1.
            // arrayCopy.add(arrayRemove.get(i)); //2. (same code but...)
        } else {
            // linkedRemove.remove(i); //3.
            // arrayRemove.remove(i); //4.
        }
    }
    ds[1] = new Date();
    for (int i = 0; i < initialMax; i++) {
        if (rnd.nextDouble() < retain) {
            // linkedCopy.add(arrayRemove.get(i)); //1.
            arrayCopy.add(arrayRemove.get(i)); //2. (same code but...)
        } else {
            // linkedRemove.remove(i); //3.
            // arrayRemove.remove(i); //4.
        }
    }
    ds[2] = new Date();
    for (int i = 0; i < initialMax; i++) {
        if (rnd.nextDouble() < retain) {
            // linkedCopy.add(arrayRemove.get(i)); //1.
            // arrayCopy.add(arrayRemove.get(i)); //2. (same code but...)
        } else {
            linkedRemove.remove(0); //3.
            // arrayRemove.remove(0); //4.
        }
    }
    ds[3] = new Date();
    for (int i = 0; i < initialMax; i++) {
        if (rnd.nextDouble() < retain) {
            // linkedCopy.add(arrayRemove.get(i)); //1.
            // arrayCopy.add(arrayRemove.get(i)); //2. (same code but...)
        } else {
            // linkedRemove.remove(0); //3.
            arrayRemove.remove(0); //4.
        }
    }
    ds[4] = new Date();
    // End benchmarking
    long[] diff = new long[4];
    System.out.println("Results:");
    for (int i = 0; i < 4; i++) {
        diff[i] = (ds[i + 1].getTime() - ds[i].getTime());
        System.out.println((i+1) + ".: " + diff[i]);
    }
}
}

结果

  

结果:
  1:0-15
  2:0
  3:0-15
  4:6895