繁体   English   中英

在 java 中用 null 填充 ArrayList 的最快方法是什么?

[英]What is the fastest way to fill an ArrayList with null in java?

我想要一个包含 n 组整数的列表,最初这个列表应该用 null 填充。 很多 Set 将在稍后初始化,有些将保留为 null。

我尝试了不同的方法来实现这一点,其中一些包括在这里:

List<HashSet<Integer>> List_of_Sets = Arrays.asList(new HashSet[n]);
ArrayList<HashSet<Integer>> List_of_Sets = new ArrayList<>(n);
while(n-- > 0) List_of_Sets.add(null);

有没有更快的方法来做到这一点?

为澄清起见,arrays 的示例将是Arrays.fill()曾经比:

/*
 * initialize a smaller piece of the array and use the System.arraycopy 
 * call to fill in the rest of the array in an expanding binary fashion
 */
public static void bytefill(byte[] array, byte value) {
  int len = array.length;

  if (len > 0){
    array[0] = value;
  }

  //Value of i will be [1, 2, 4, 8, 16, 32, ..., len]
  for (int i = 1; i < len; i += i) {
    System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i) : i);
  }
}

^上面的代码来自罗斯德鲁对设置数组所有值的最快方法的回答?

有没有更快的方法来做到这一点?

据我所知,没有。 当然,没有比这更快的简单方法了。

根据它的工作原理,我认为(但我没有测试过) Arrays.asList(new HashSet[n])应该是最快的解决方案。

可以实现自定义List实现,类似于ArrayList但预初始化为 N null值。 但在底层,初始化将与asList返回的List实现中发生的情况几乎相同。 所以我怀疑任何性能改进都会显着......或者值得付出努力。

如果您想确定这一点,您可以编写各种选项的基准。 但是,在这种情况下,我认为这不是正确的方法。

相反,我建议对整个应用程序进行基准测试和分析,以确定此列表上的操作是否是真正的性能热点。

  • 如果它不是热点,我的建议是只使用Arrays.asList方法并将时间花在更重要的事情上。

  • 如果是热点,则应考虑将List替换为数组。 根据您之前的描述,似乎List用作数组; 即使用位置getset操作,并且不使用更改列表大小的操作。 如果是这种情况,那么使用真正的数组应该更有效。 它节省了 memory,并避免了间接级别和(可能)一些边界检查。

    不这样做的一个原因是,如果您需要将数组传递给需要List的其他代码。

如果调整大小对您来说并不重要,那么实现您自己的列表可能会很快。 它也可能是越野车。 与 Java 的列表相比,基准测试至少会很有趣。 您可能会看到一个奇怪的效果,即标准列表可能会更快地被 JIT 优化,因为它们可以被 Java 的标准库在内部使用。

这是我的尝试,尽管我建议您不要使用它。 请改用标准列表实现。

import java.util.*;

public class FastListOfNullsDemo {
    public static void main(String[] args) {
        Set<Integer>[] arr = new Set[100_000]; // all set to null by default.
        List<Set<Integer>> myList = new ArrayBackedList<>(arr);
        
        myList.set(3, new TreeSet<Integer>());
        
        myList.get(3).add(5);
        myList.get(3).add(4);
        myList.get(3).add(3);
        myList.get(3).add(2);
        myList.get(3).add(1);
        
        // Let's just print some because 100,000 is a lot!
        for (int i = 0; i < 10; i++) {
            System.out.println(myList.get(i));
        }
    }
}

class ArrayBackedList<T> extends AbstractList<T> {
    private final T[] arr;
    
    ArrayBackedList(T[] arr) {
        this.arr = arr;
    }
    
    @Override
    public T get(int index) {
        return arr[index];
    }

    @Override
    public int size() {
        return arr.length;
    }
    
    @Override
    public T set(int index, T value) {
        T result = arr[index];
        arr[index] = value;
        return result;
    }
}

另一种可能性是实现一个始终为空的、固定大小的列表。 使用它来初始化 ArrayList。 我不会 promise 它很快但你可以试试。

import java.util.*;

public class FastListOfNullsDemo {
    public static void main(String[] args) {
        List<Set<Integer>> allNull = new NullList<>(100_000);
        List<Set<Integer>> myList = new ArrayList<>(allNull);
        
        myList.set(3, new TreeSet<Integer>());
        
        myList.get(3).add(5);
        myList.get(3).add(4);
        myList.get(3).add(3);
        myList.get(3).add(2);
        myList.get(3).add(1);
        
        System.out.println(myList.size());
        // Let's just print some because 100,000 is a lot!
        for (int i = 0; i < 10; i++) {
            System.out.println(myList.get(i));
        }
    }
}

class NullList<T> extends AbstractList<T> {
    private int count;
    
    NullList(int count) {
        this.count = count;
    }
    
    @Override
    public T get(int index) {
        return null;
    }

    @Override
    public int size() {
        return count;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM