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 );
}
}