Java 什么';初始化大整数列表的最快方法是什么?

Java 什么';初始化大整数列表的最快方法是什么?,java,Java,我需要用大量整数值预先填充一个列表 除了迭代,还有其他更快的方法吗 当前代码: class VlanManager { Queue<Integer> queue = Lists.newLinkedList(); public VlanManager(){ for (int i = 1; i < 4094; i++) { queue.add(i); } } 类VLAN管理器{ Queue Queue=Lists.newLinke

我需要用大量整数值预先填充一个列表

除了迭代,还有其他更快的方法吗

当前代码:

class VlanManager {
    Queue<Integer> queue = Lists.newLinkedList();

    public VlanManager(){
    for (int i = 1; i < 4094; i++) {
        queue.add(i);
    }
}
类VLAN管理器{
Queue Queue=Lists.newLinkedList();
公共事务经理(){
对于(int i=1;i<4094;i++){
加入(i);
}
}

这段代码位于一个类的构造函数中,该类创建得非常频繁,因此我希望它尽可能高效(读:性能而不是代码行)

4094不是要循环很多项,但如果它被频繁调用,您可能会考虑使用静态变量执行某些操作

private static Integer[] theList;

static {
    theList = new Integer[4094];
    for (int i = 1; i < 4094; i++) {
        theList[i-1] = i;
    }
}

如果您有一个可变对象列表,则使用此方法存在危险。下面是一个可能发生的情况的示例。整数是不可变的,因此这实际上不适用于您的问题


最快的方法是创建一个引用列表(使用实例块初始化-将其整齐地包装在一条语句中):

private static final List=new ArrayList(4094){{
对于(int i=1;i<4094;i++)
列表.添加(i);
}};
然后在构造函数中,使用复制构造函数初始化队列:

Queue<Integer> queue;

public VlanManager(){
    queue = new LinkedList<Integer>(LIST);
}
队列;
公共事务经理(){
队列=新链接列表(列表);
}

您不会编写比JDK更快的实现。

我意识到这个问题已经得到了回答。但我认为缺少一个重要的答案:初始化值为0..4093的LinkedList的最快方法是..根本不要这样做。。特别是如果速度是个问题的话

基本上,您要做的是创建一个由4093个
节点
元素组成的结构,每个元素包含两个指向上一个/下一个元素的指针和一个指向整数对象的指针。必须创建(并释放)每个
节点。此外,几乎必须创建(并释放)每个包含的整数“几乎”是因为Java对整数使用缓存,但通常(可以使用系统属性更改)在-127..127范围内

为了得到一个简单的整数列表,这有很多工作要做,如果大量使用,那么GC以后就有很多工作要做

也就是说,有很多可能更有效地实现这一点的方法。但它们取决于您的具体使用模式。仅举几个例子:

  • 使用数组:
    boolean[]inUse',并将获取的vlan id设置为
    true`如果已获取
  • 最好使用位集而不是数组
  • 不要存储哪个vlan是免费的,而是存储哪个vlan是被占用的。我认为它们往往是免费的,所以空闲的要比占用的多得多。(这意味着要跟踪的要少得多)
  • 如果你坚持使用LinkedList,不要用你的类初始化它,而是让它已经初始化。这取决于你需要多少LinkedList。你可以保留一个LinkedList池。或者你的代码允许重用旧列表。(是的,你可以在使用后对它们进行排序。)
  • 当然还有更多

    所有这些方法都要求您构建自己的“队列”接口。但是,这可能没有Java的那么丰富。而且这真的没有那么困难。如果您真的大量使用这些方法,您可以达到性能改进系数10x-1000x++

    使用
    位集
    ,实例化成本几乎为零的可能实现可能是:

    import java.util.BitSet;
    
    import org.testng.annotations.Test;
    
    
    public class BitSetQueue {
    
        // Represents the values 0..size-1
        private final BitSet bitset;
        private final int size;
        private int current = 0;
        private int taken = 0;
    
        public BitSetQueue( int size ){
    
            this.bitset = new BitSet( size );
            this.size = size;
            this.current = size-1;
        }
    
        public int poll(){
    
            // prevent endless loop
            if( taken == size ) return -1;
    
            // seek for next free value.
            // can be changed according to policy
            while( true ){
    
                current = (current+1)%size;
    
                if( ! bitset.get( current ) ){
                    bitset.set( current );
                    taken++;
                    return current;
                }
            }
        }
    
        public boolean free( int num ){
    
            if( bitset.get( num ) ){
                bitset.clear( num );
                taken--;
                return true;
            }
            return false;
        }
    
    
        @Test
        public static void usage(){
    
            BitSetQueue q = new BitSetQueue( 4094 );
    
            for( int i = 0; i < 4094; i++ ){
                assertEquals( q.poll(), i );
            }
            assertEquals( q.poll(), -1 ); // No more available
    
            assertTrue( q.free( 20 ) );
            assertTrue( q.free( 51 ) );
    
            assertEquals( q.poll(), 20 );
            assertEquals( q.poll(), 51 );
        }
    
    }
    
    import java.util.BitSet;
    导入org.testng.annotations.Test;
    公共类BitSetQueue{
    //表示值0..size-1
    专用最终位集位集;
    私人最终整数大小;
    专用int电流=0;
    私有int=0;
    公共比特集队列(整数大小){
    this.bitset=新的位集(大小);
    这个。大小=大小;
    该电流=尺寸-1;
    }
    公共投票{
    //防止无止境循环
    if(take==size)返回-1;
    //寻找下一个自由值。
    //可以根据政策进行更改
    while(true){
    电流=(电流+1)%size;
    如果(!bitset.get(当前)){
    位集.set(当前);
    take++;
    回流;
    }
    }
    }
    公共布尔自由值(int num){
    if(bit set.get(num)){
    位集清除(num);
    采取--;
    返回true;
    }
    返回false;
    }
    @试验
    公共静态无效用法(){
    BitSetQueue q=新的BitSetQueue(4094);
    对于(int i=0;i<4094;i++){
    assertEquals(q.poll(),i);
    }
    assertEquals(q.poll(),-1);//不再提供
    资产真实性(q.free(20));
    资产真实性(q.free(51));
    assertEquals(q.poll(),20);
    assertEquals(q.poll(),51);
    }
    }
    
    我认为没有其他方法可以尝试创建即时数组并使用asList,但我会根据您需要的实际情况对其进行分析。我会以编程方式生成数组代码,除非您真的喜欢键入。4094?别担心,您会很好的…使用
    ArrayList
    而不是您应该更清楚地描述至少,你要处理这些数字,以及(潜在的)性能关键部分是什么。这就是我刚刚要做的。这比我确定的要好!但我需要一个可变对象,所以我认为这对我的用例不起作用。@DaveTucker那么你不使用整数了吗?@DaveTucker这是不明确的,但是“不可变对象”我相信ug_uu是指列表中的那些(整数),而不是包含列表/队列/对象的对象,它当然可以是可变的。因此,此代码可以很好地工作。@Boann您的权利我在awnser中提到的可变对象是模糊的、更新的。这里的一个很好的优点是避免每次创建对象时将所有4094个值的
    int
    更改为
    Integer
    。这是基本的凯莉和@ug_u给出的答案一样,
    private static List<Integer> theList;
    
    static {
        theList = new ArrayList(4094);
        for (Integer i = 0; i < 4094; i++) {
            theList.add(i+1);
        }
    }
    
    private static final List<Integer> LIST = new ArrayList<Integer>(4094) {{
        for (int i = 1; i < 4094; i++)
           LIST.add(i);
    }};
    
    Queue<Integer> queue;
    
    public VlanManager(){
        queue = new LinkedList<Integer>(LIST);
    }
    
    import java.util.BitSet;
    
    import org.testng.annotations.Test;
    
    
    public class BitSetQueue {
    
        // Represents the values 0..size-1
        private final BitSet bitset;
        private final int size;
        private int current = 0;
        private int taken = 0;
    
        public BitSetQueue( int size ){
    
            this.bitset = new BitSet( size );
            this.size = size;
            this.current = size-1;
        }
    
        public int poll(){
    
            // prevent endless loop
            if( taken == size ) return -1;
    
            // seek for next free value.
            // can be changed according to policy
            while( true ){
    
                current = (current+1)%size;
    
                if( ! bitset.get( current ) ){
                    bitset.set( current );
                    taken++;
                    return current;
                }
            }
        }
    
        public boolean free( int num ){
    
            if( bitset.get( num ) ){
                bitset.clear( num );
                taken--;
                return true;
            }
            return false;
        }
    
    
        @Test
        public static void usage(){
    
            BitSetQueue q = new BitSetQueue( 4094 );
    
            for( int i = 0; i < 4094; i++ ){
                assertEquals( q.poll(), i );
            }
            assertEquals( q.poll(), -1 ); // No more available
    
            assertTrue( q.free( 20 ) );
            assertTrue( q.free( 51 ) );
    
            assertEquals( q.poll(), 20 );
            assertEquals( q.poll(), 51 );
        }
    
    }