【问题标题】:Error finding largest randomly generated double in ArrayList Java在 ArrayList Java 中查找最大随机生成的双精度时出错
【发布时间】:2016-10-11 16:35:08
【问题描述】:

我正在尝试让一个程序运行,我生成 0 到 1 之间的 1,000,000 个随机数,然后找到并打印最大的数字。

我已经让生成器工作并设法将生成的每个双精度数插入到 ArrayList 中,但我似乎无法弄清楚如何在列表中找到最大的数字。目前当前代码抛出错误“java.lang.IndexOutOfBoundsException”。

这可能是因为我是 ArrayList 的新手,不熟悉它的命令和它的工作原理,但是我真的很感谢我在这里做错的一些帮助,因为我已经被困了一段时间.

import java.util.ArrayList;
import java.util.Random;
public class milran {
    public static void main(String[] args) {
        Random r = new Random();
        ArrayList<Double> myList = new ArrayList<Double>();
        for (int i = 1; i<=1000000; i++){
            double randomValue = 0.0+(1.0-0.0)*r.nextDouble();
            myList.add(randomValue);

        }
        double max = myList.get(1);
        for (int z=2; z<=myList.size(); z++){
            double test = myList.get(z);
            if (test>max){
                max = test;
            }
        }
        System.out.println(max);
    }
}

【问题讨论】:

    标签: java sorting arraylist random double


    【解决方案1】:

    首先查看java.util.Collectionsjava.util.ArrayList 的文档。 其次,ArrayIndexOutOfBoundsException 是由这个触发的......

    for (int z=2; z<=myList.size(); z++){
            double test = myList.get(z);
            ...
    }
    

    这是因为数组索引从 0 开始,因此最后一个元素是 myList.size() - 1。也就是说,当z = myList.size() 时,就是越界了。

    另外,在您的第一个for 循环中,您使用的是i = 1; 1 &lt;= 1000000。使用i = 0; i &lt; 1000000 更有意义,因为您可以使用i 来触摸数组(或列表)中的每个元素。

    for( i = 0; i < 1000000; i++ )
    {
        // do something with myArray[i]
    } 
    

    这是插入值后我要执行的操作...

    1. 对数组排序: Collections.sort(myList);
    2. 检索最后一个元素: System.out.println( myList.get( myList.size() - 1 ) );

    ...就是这样。

    如果您需要自己实现实际排序,那么我会考虑使用原始双精度数组 (double[]) 而不是集合。

    否则,如果您使用的是集合,则可以使用 foreach 循环。

    for( Double d : myList ) // for each Double 'd' in myList
    {
        // do something with d
    }
    

    注意第二个循环中这条线的另一个潜在问题

    double test = myList.get(z);
    

    这种从Double(对象)到double(原始)的自动转换称为unboxing会有性能成本,尤其是在重复一百万次时。在第一个循环中,您正在转换另一种方式(自动装箱)——也是一百万次。

    【讨论】:

    • 为什么推荐排序,而不是只扫描一次列表找到最大的元素?
    • @PatriciaShanahan – 用于重复使用。随着时间的推移,未排序的数组往往会减慢速度。当您需要第二大元素时会发生什么?那么第三个呢?继续扫描阵列?那是O(n ^ 2)。你可以只使用 Collections.sort(List list)
    • ^^使用合并排序 (timsort) 的变体实现,它是 O(nlogn) 和 O(n) 的最佳情况
    • ...在这种特殊情况下,如果您只需要遍历数组一次,我会问自己为什么要存储所有值,将它们放在一个大小为百万双精度数(+ ArrayList 类本身的大小)
    【解决方案2】:

    ArrayList0 开始计算其元素。您需要将myList.get(1) 替换为myList.get(0),将int z=2 替换为int z=1z&lt;=myList.size() 替换为z&lt;myList.size()

    【讨论】:

      【解决方案3】:

      这一行:for (int z=2; z&lt;=myList.size(); z++) { 是错误的。应该是for (int z=1; z&lt;myList.size(); z++) {

      这是因为数组和列表都是从 0 开始的,所以大小为 2 的列表有 2 个元素 - 索引 0 和索引 1。目前您尝试索引到与大小相等的元素编号,但不存在。

      在同一行中,myList.get(1); 应该是 myList.get(0);

      这与您的问题无关,但0.0+(1.0-0.0)*r.nextDouble(); 这一行可以更容易地写成r.nextDouble();。我不确定您通过 0 + 1 - 0 尝试做什么。

      【讨论】:

        【解决方案4】:

        正如其他人已经指出的那样,您的 for 循环条件中有一个错误,导致索引超出范围。

        将来避免这种情况的一种方法是使用 Java 的 for-each 循环语法,而不是尝试自己管理索引。

        for (Double test : myList) {
            if (test>max){
                max = test;
            }
        }
        

        与传统的索引 for 语法相比,此语法使您的意图更加清晰,并从您手中消除了潜在的错误点(管理索引和列表的边界)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-16
          • 2016-02-14
          • 2011-02-11
          • 1970-01-01
          • 2017-09-07
          • 2013-08-10
          • 2016-12-10
          • 1970-01-01
          相关资源
          最近更新 更多