我正逐像素地检测位图中的数字。每个数字都以一个像素的大小开始。大多数数据都在增长,但有些数字还很小。
我在ArrayList
中按顺序收集数字。在下一步中,我想减少列表删除小数字。
第一步收集大约1500个数字。第二步删除了约1/3。
表现更好:
LinkedList
删除项目效果更佳:
LinkedList
但是然后构建此列表比使用ArrayList
表现更差(因为创建LinkedList
项目的成本比将对象添加到ArrayList
)ArrayList
将删除的项目后的项目复制到已删除项目的位置。为了减少要复制的项目数量,我可以从最后一个索引开始遍历列表。ArrayList
,用3/4大小的原始数据列表初始化它,然后只将更大的数字添加到新列表中。我想,使用这么几个项目,没有一个选项会带来可衡量的性能提升。但是对于更多的物品来说效果更好?
答案 0 :(得分:2)
使用以下测试程序,我找到了
1000个对象引用,25%要从arrayList中删除;
100000个对象引用,25%要从arrayList中删除;
在小规模上,它并不重要,在大规模上创建新列表是关键,最好是预先设定
1000个对象引用,25%要从arrayList中删除;
100000个对象引用,25%要从arrayList中删除;
在小尺度上从现有的集合中移除似乎更快,但两者都可以在重要的尺度上进行比较。
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