【问题标题】:Most efficient way to create an array of counting numbers创建计数数组的最有效方法
【发布时间】:2012-06-08 23:28:13
【问题描述】:

创建一个给定长度的数组最有效的方法是什么,每个元素都包含它的下标?

我的虚拟代码的可能描述:

/**
 * The IndGen function returns an integer array with the specified dimensions.
 *  
 *  Each element of the returned integer array is set to the value of its 
 *  one-dimensional subscript.
 *  
 *  @see Modeled on IDL's INDGEN function: 
 *      http://idlastro.gsfc.nasa.gov/idl_html_help/INDGEN.html 
 *  
 *  @params size
 *  @return int[size], each element set to value of its subscript
 *  @author you
 *  
 *  */

public int[] IndGen(int size) {
    int[] result = new int[size];
    for (int i = 0; i < size; i++) result[i] = i;
    return result;
}

其他提示,例如文档样式,欢迎使用。

编辑

我在其他地方读到过 for 循环与其他方法相比效率低下,例如在 Copying an Array 中:

使用克隆:93 毫秒

使用 System.arraycopy:110 毫秒

使用 Arrays.copyOf:187 毫秒

使用 for 循环:422 毫秒

我对这个网站上一些问题的富有想象力的回答印象深刻,例如,Display numbers from 1 to 100 without loops or conditions。这是一个可能建议一些方法的答案:

public class To100 {
public static void main(String[] args) {
        String set = new java.util.BitSet() {{ set(1, 100+1); }}.toString();
        System.out.append(set, 1, set.length()-1);
    }
}

如果您无法解决这个具有挑战性的问题,无需发泄:只需继续下一个未回答的问题,您可以处理。

【问题讨论】:

  • 这似乎行得通。请不要微优化。
  • 谁要求你优化这段代码?
  • 这个数组有多大?我们在这里谈论的是兆字节还是千兆字节的数据?
  • @sarnold,目前还不清楚。它可能是 10^12 个元素,或者更多。要求很高的应用程序。
  • 所以你需要 3.6 TB 的整数。元素2147483648 会发生什么?整数应该回绕到0-2147483647,还是要将它们存储在 64 位整数字段中? (这需要 7 TB 的数据。)

标签: java arrays performance


【解决方案1】:

由于一次使用 TB 的内存是不可行的,尤其是同时使用它们进行任何计算,您可能会考虑使用生成器。 (您可能打算循环遍历数组,对吗?)使用生成器,您不需要初始化数组(因此您可以立即开始使用它)并且几乎不使用内存(O(1))。

我在下面包含了一个示例实现。它受到long 原语的限制。

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Counter implements Iterator<Long> {
    private long count;
    private final long max;

    public Counter(long start, long endInclusive) {
        this.count = start;
        this.max = endInclusive;
    }

    @Override
    public boolean hasNext() {
        return count <= max;
    }

    @Override
    public Long next() {
        if (this.hasNext())
            return count++;
        else
            throw new NoSuchElementException();

    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

在下面找到一个使用演示。

Iterator<Long> i = new Counter(0, 50);
while (i.hasNext()) {
    System.out.println(i.next());  // Prints 0 to 50
}

【讨论】:

  • 这不是我想要的,但它很有教育意义。非常感谢!
【解决方案2】:

我唯一想到的是使用“++i”而不是“i++”,但我认为java编译器已经有了这个优化。

除此之外,这几乎是最好的算法。

你可以创建一个类,它的行为就像它有一个数组但它没有,它只会返回它得到的相同数字(也就是身份函数),但这不是你所要求的.

【讨论】:

  • 这只对 c++ 和复杂对象有影响。对于其他任何事情,任何编译器都会为单个表达式生成相同的代码。除了您提出的懒惰课程之外,我们真的无能为力。好吧,可以使用 SSE(不是在 java 中..),但是代码的内存明显有限,我看不出它有什么真正的帮助。
  • 这里有一些相关的 stackoverflow.com/questions/6676836/java-7-sorting-optimisation/… 就像 Voo 所说的,没有真正的区别
【解决方案3】:

正如其他人在他们的回答中所说,您的代码已经接近我能想到的最有效的,至少对于小型数组而言。如果您需要多次创建这些数组并且它们非常大,那么您可以一次创建所有数组,然后复制它们,而不是在 for 循环中不断迭代。如果数组非常大,复制操作将比遍历数组更快。它会是这样的(在这个例子中最多有 1000 个元素):

public static int[][] cache = {{0},{0,1},{0,1,2},{0,1,2,3},{0,1,2,3,4}, ..., {0,1,2,...,998,999}};

然后,在您需要多次创建这些数组的代码中,您将使用如下代码:

int[] arrayOf50Elements = Arrays.copyOf(cache[49], 50);

请注意,这种方式会使用大量内存来提高速度。我想强调的是,只有当您需要多次创建这些数组,数组非常大,并且最大速度是您的要求之一时,这才值得复杂化。在我能想到的大多数情况下,您提出的解决方案都是最好的。

编辑:我刚刚看到您需要大量的数据和内存。我提出的方法需要 n^2 级的内存,其中 n 是您期望拥有的最大整数。在这种情况下,这是不切实际的,因为您需要大量的内存。忘记这个吧。我离开这个帖子是因为它可能对其他人有用。

【讨论】:

  • 虽然这绝不是对您的原始响应的敲门声,但我发现描绘一行初始化 3.6TB 整数的代码很有趣。 :)
猜你喜欢
  • 2014-07-19
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-16
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多