【问题标题】:Elegant way to find min of an array using method parameters?使用方法参数查找数组最小值的优雅方法?
【发布时间】:2017-12-21 07:59:17
【问题描述】:

我正在寻找一种优雅的方式来表达这个伪代码。对于我的分配,我无法更改方法签名或参数类型。

    private static int smallest(int... nums)
    {
        return Arrays.stream(nums).min().getAsInt();
    }

我要做的就是从方法调用中获取一个巨大的可变 ints 列表作为参数,并返回所有 中最小的 int int 参数。我试图用谷歌搜索并阅读 API 以了解如何正确实现这一点,但我只做到了这一点。有人可以帮我在语法上更正它以正确编译和输出吗?

我无法正确发布带有格式的控制台错误,因此我将其发布为对我的 OP 的更新。为了回答@Marvin,我的编译器出现了这个错误......

Methods1.java:25: error: cannot find symbol
  int small = Arrays.stream(nums).min().getAsInt();
              ^
symbol:   variable Arrays
location: class Methods1
1 error

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误必要的最短代码 重现它在问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example
  • 如果我们第一眼看到编译器错误中的代码与您发布的不一样,我们应该怎么想?它只是min(),就像您发布的那样,而不是min(Integer::min),就像您传递给编译器一样。除此之外,你知道你必须import java.util.Arrays;,不是吗?
  • marvin @Holger 谢谢你们两个,在你们两个之间我能够弄清楚。我需要添加 .getAsInt() 并导入我的数组类。该死的,数小时试图弄清楚它为什么不起作用,而我一直忘记导入我的怪异数组类。十分感谢大家。使用那一行代码,我现在可以执行 Karkan 下面演示的操作。漂亮!
  • 我的意思是,该错误确实可以准确地告诉您问题所在,如果您使用的是 IDE,它应该会提示您导入...
  • 是的,哈哈,当我阅读上面的@Holger 评论时,我就像....该死的,不敢相信我忘记了这一点。我正在使用一个非常基本的 IDE,jGrasp。如果我当时使用的是 intelliJ,它可能会警告我。

标签: java arrays parameters java-stream min


【解决方案1】:

你几乎拥有它,它是 getAsInt() 而不是 get()

private static int smallest(int... nums) {
    return Arrays.stream(nums).min().getAsInt();
}

完成working sample on ideone.com:

import java.util.Arrays;

class Ideone {
    public static void main (String[] args) {
        int[] nums = new int[] { 7, -2, 5, 12 };
        System.out.println(smallest(nums));
    }

    private static int smallest(int... nums) {
        return Arrays.stream(nums).min().getAsInt();
    }
}

打印:

-2

【讨论】:

  • 检查更新的 OP,我无法在此处添加以正确间距格式化的编译器错误作为注释,所以您能诊断出我的错误吗?我是不是用错了数组?
【解决方案2】:

你可以像这样遍历整个数组

private static int smallest(int[] array)
{
    //check if the array is empty
    if(array.length == 0)
    {
        //handle, whatever happens if the array is empty
        return -1; //maybe you should throw an exception here 
    }

    //storing the smallest found value, start with the first int in the array
    int smallest = array[0];

    //the iteration
    for(int i : array)
    {
        //check if the current checked value is smaller than the smallest found...
        if(i < smallest)
        {
            //...and if it is, set it as the smallest found value
            smallest = i;
        }
    }
    //finally, return the smallest value
    return smallest;
}

这应该可以解决您当前的问题,但在大多数情况下,我宁愿建议使用预先排序的数组或列表。如果其中的数据已经按升序存储,则第一个元素总是最低的,最后一个元素总是最高的。

【讨论】:

  • 我想我可以在这里做一个简单的 foreach 循环,在我的原始代码中我这样做了,但我想知道是否有更优雅的方式使用流媒体和 lambda?但是,感谢您通过@Karkan 提供的帮助!
【解决方案3】:

这个方法通过使用 varargs 作为它的参数来获取无限的未知变量数量的参数。将从 main 调用中添加的所有参数组合到相同类型的数组中。这是为了解释 main 中原始方法调用的可变性。最后,返回所有参数中最小的整数。

我是一个相当新的程序员,第二年进入计算机科学专业,我不确定这是否对任何人有用,但我希望它有所帮助。感谢这里的每个人都提供了很棒的提示和错误捕获。我的问题是我忘记导入我的 Array 类,并且我从流类调用的方法之一被错误地命名。

最后,对于任何经验丰富的程序员来说,除了看起来简洁优雅之外,这条语句的执行速度是否比执行简单的 foreach 循环并将 num 与最后一个最小的循环比较快?

   import java.util.Arrays;

   public class Test
   {
       public static void main(String[] args)
       {
           // Enter as many as you want here, can be more or less than three
           int num1 = 23;
           int num2 = 89;
           int num3 = 9;

           // Apply each variable as an argument for the method call
           int smallestNumber = smallest(num1, num2, num3);
           // Print out variable value to prove it works
           System.out.print(smallestNumber);
       }

       private static Integer smallest(int... nums)
       {
           // Found an elegant way to do the stubbed out block of code
           // I left the code down there to show what is going on here
           try
           {
               return Arrays.stream(nums).min().getAsInt();
           }
           catch (Exception e)
           {
               return null;
           }


           // The above code is essentially doing the below code
           /*try
           {
               // Initialize Variable to start of array
               int smallest = nums[0];

               // For:Each Loop: go through each parameter and assign it a local variable to compare with
               for(int i : nums)
               {
                   // compare if smaller
                   if(i < smallest)
                   {
                       // If true, set as smallest
                       smallest = i;
                   }
               }
               return smallest;
           }
           catch (Exception e)
           {
               return null;
           }*/
       }
    }

【讨论】:

  • 不要捕获将异常转换为null 结果的异常。在不太可能的异常情况下,您将在调用者的代码中得到一个NullPointerException,您尝试将Integer 转换为int,而没有任何关于正在发生的事情的提示。这有什么比让最初的异常引发更好的呢?只需使用问题中显示的代码,无需任何异常处理和int 结果类型而不是Integer
  • 好的,有道理,我会做这些调整。你有一个很好的观点,我知道发生了什么,但对于用户来说,崩溃没有留下任何提示。我最初设计这个方法是为了返回 Object,并且在 catch 块中,我有一条错误消息,说明出了什么问题。我决定将此方法更改为 Integer 以允许除“-1”或任何其他类型的 int 之外的其他内容来表示错误。然后,可以将此 Integer 类型返回值分配给方法外部的 int 。但是,我明白你的意思,如果它返回 null,它会在尝试将 null 分配给 int 时直接崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-04
  • 2015-05-22
  • 1970-01-01
相关资源
最近更新 更多