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

在java中,用null填充ArrayList的最快方法是什么?,java,performance,arraylist,Java,Performance,Arraylist,我想要一个由n组整数组成的列表,最初这个列表应该用null填充。 许多集合将在稍后初始化,有些将保持为空 我尝试了不同的方法来实现这一点,其中一些方法包括: List<HashSet<Integer>> List_of_Sets = Arrays.asList(new HashSet[n]); ^以上代码来自Ross Drew对的回答,如果调整大小对您不重要,那么实现您自己的列表可能会很快。它也可能是马车。与Java的列表相比,至少基准测试是有趣的。您可能会看到一个奇怪

我想要一个由n组整数组成的列表,最初这个列表应该用null填充。 许多集合将在稍后初始化,有些将保持为空

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

List<HashSet<Integer>> List_of_Sets = Arrays.asList(new HashSet[n]);

^以上代码来自Ross Drew对

的回答,如果调整大小对您不重要,那么实现您自己的列表可能会很快。它也可能是马车。与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;
    }
}
import java.util.*;
公共类FastListOfNullsDemo{
公共静态void main(字符串[]args){
Set[]arr=new Set[100_000];//默认情况下,所有设置均为null。
列表myList=新的ArrayBackedList(arr);
myList.set(3,新树集());
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);
//让我们打印一些,因为100000是很多!
对于(int i=0;i<10;i++){
System.out.println(myList.get(i));
}
}
}
类ArrayBackedList扩展了AbstractList{
私人终审法院【】arr;
ArrayBackedList(T[]arr){
this.arr=arr;
}
@凌驾
公共T获取(整数索引){
返回arr[索引];
}
@凌驾
公共整数大小(){
返回arr.length;
}
@凌驾
公共T集(整数索引,T值){
T结果=arr[指数];
arr[指数]=数值;
返回结果;
}
}
另一种可能是实现一个总是空的、固定大小的列表。使用该选项初始化ArrayList。我不能保证它很快,但你可以试试

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;
    }
}
import java.util.*;
公共类FastListOfNullsDemo{
公共静态void main(字符串[]args){
List allNull=新的空列表(100_000);
List myList=new ArrayList(allNull);
myList.set(3,新树集());
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());
//让我们打印一些,因为100000是很多!
对于(int i=0;i<10;i++){
System.out.println(myList.get(i));
}
}
}
类NullList扩展了AbstractList{
私人整数计数;
空列表(整数计数){
this.count=计数;
}
@凌驾
公共T获取(整数索引){
返回null;
}
@凌驾
公共整数大小(){
返回计数;
}
}
有没有更快的方法

据我所知,没有。当然,没有简单的方法可以更快

基于它的工作原理,我认为(但我还没有测试过)Arrays.asList(newhashset[n])应该是最快的解决方案

可以实现一个自定义的
列表
实现,它类似于
数组列表
,但预先初始化为N
null
值。但是在引擎盖下,初始化将与
List
实现中发生的情况几乎相同,而
asList
将返回该实现。所以我怀疑任何性能改进是否会有意义。。。或者值得付出努力

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

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

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

  • >P>如果是热点,您应该考虑用数组替换<代码>列表< /代码>。从您之前的描述来看,您似乎要像使用数组一样使用
    列表
    ;i、 e.使用位置
    get
    set
    操作,不使用更改列表大小的操作。如果是这样的话,那么使用真实数组应该更有效。它节省了内存,避免了一定程度的间接寻址和(可能的)一些边界检查

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


1)答案是否定的(AFAIK)。2) 您应该能够通过基准测试(使用正确的技术!!)来检查哪种备选方案最快,但我认为
Arrays.asList
版本应该稍微快一点。3) 这是“过早优化”吗?最后,如果速度对您来说真的很重要,您可以用数组替换
ArrayList
。这将更快地创建和访问/更新。(在某些情况下只是有点不方便。)据我所知,您将不会利用
列表
API添加和删除列表元素的功能….
Collections.fill()
对空列表没有任何作用,因此如果您对它感到满意,那就有点令人费解了。有
Collections.nCopies()
可以与
null
一起使用。我只想
List\u of_set=array.asList(新的HashSet[n])
和move ony您还可以编写一个
原生方法。谢谢!我最终使用了n个哈希集的数组,因此我将按照您的建议而不使用它。为了将来读者的利益,我对这个问题进行了编辑,使之更具一般性。
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;
    }
}
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;
    }
}