【问题标题】:I'm trying to create a new array given min and max values from another array我正在尝试创建一个给定另一个数组的最小值和最大值的新数组
【发布时间】:2019-06-15 23:49:46
【问题描述】:

给定一个数组 data[]、一个 minValue 和 maxValue,创建一个方法,该方法返回一个数组,该数组仅由 data[] 中的 minValue(包括和 maxValue(不包括)之间的值)组成。

我确实做了这个问题,但我想知道是否有一种更清洁(更少新手)的方法来做到这一点。为了获得我的 temp[] 的大小,我实际上做了完整的循环,它有效但看起来很笨重。

public static int[] superSweetFilterMethod(int[] data, int minValue, int maxValue) {
    int j = 0;
    for (int i =0; i < data.length ; i++) {
      if (data[i] >= minValue && data[i] < maxValue) {
        j++;
      }
    }
    int k = 0;
    int[] temp = new int[j];
    for (int i =0; i < data.length ; i++){
      if(data[i] >= minValue&& data[i] < maxValue){
        temp[k] = data[i];
        k++;
      }
    }
    return temp;
  }

就像我说的,这行得通,我只想 git gud。谢谢你的课,聪明的人。

【问题讨论】:

  • 您的代码是最优的。鉴于您要返回一个数组,因此无法避免 2 次传递。链表只需要 1 次通过,但性能可能会更差。
  • 您可以使用Arraylist 并将data[i] 动态推入其中,而无需知道temp[] 的大小。如果调用者方法不能修改为接受ArrayList,则在返回之前将ArrayList转换为Array(tempList.toArray())
  • 谢谢老兄!将阅读 ArrayList 并使用它。

标签: java


【解决方案1】:

您可以通过以与原始数组相同的大小初始化临时数组来避免使用相同的 if 子句循环两次,并使用计数器 int 来跟踪临时数组中的元素数。

但是,在返回临时数组之前,您仍然需要减小它的大小。这可以通过使用实用方法 Arrays.copyOfRange 来完成。 (这仍然是内部的第二个循环,但没有重复你的 if 子句)

我更喜欢@Sagar Ch 的解决方案(评论)(ArrayList),因为它更具可读性,并且它会为您跟踪元素的数量。

【讨论】:

  • 谢谢老兄!我曾尝试以相同的大小初始化并得到额外的零。可以完成 copyOfRange 将其拉出。少林弓。回到它。
【解决方案2】:

正如其他人所说,考虑到使用数组和原语的限制,您的代码看起来不错、高效,但需要两次通过。如果你可以选择使用对象和集合,你的代码可以被重写得更短更简单。

Java 集合框架

Java 中的array 有意限制其功能。 array 的主要原因是为了更容易地从其他语言(例如 C)移植代码。当 (a) 使用原语 (b) 紧凑地使用内存时,数组也很有用优先级——在面向业务的应用程序中通常不是这种情况。

对于 Java 中的日常工作,我们使用与 Java 捆绑在一起的功能丰富的 Java collections framework 或来自第三方的类似框架,例如 Google Guava

在 Java 中,array 的常见替代品是 ArrayList 类。此类掩盖了下面数组的使用,以给出数组根据需要增长或缩小的错觉。对于小型列表,您可以简单地依靠这种自动调整大小。

集合框架只处理对象,而不是基元。但是Java 将使用其auto-boxing 特性自动将您的int 原始值提升为Integer 对象。对象占用更多内存,速度稍慢,但更灵活。

Java 具有循环数组或集合的 for-each 功能,以简化 for 循环的语法。

请注意“不小于最小值”是“大于或等于最小值”的另一种说法。相同的效果,根据风格使用。

ArrayList< Integer > numbers = new ArrayList<>() ;
for( int i : data ) {                               // for-each syntax, to loop an array.
    if ( !( i < min ) && ( i < max ) ) {            // Half-Open `[)`, beginning/lower is inclusive while the ending/higher is exclusive.
        numbers.add( i ) ;                          // Auto-boxing converts your `int` primitive to an `Integer` object.
    }                                               // Else discard this number, and move on to the next.
}

只需要一个循环。更短的代码,更容易阅读。

您可能希望将结果返回为更通用的List 而不是ArrayList。如果您研究过 OOP 概念,这就是多态性。

public static List< Integer > filterOutTooLowAndTooHigh( int[] ints , int min , int max )
{
    ArrayList< Integer > numbers = new ArrayList<>() ;
    for( int i : ints ) {
        if ( !( i < min ) && ( i < max ) ) { 
            numbers.add( i ) ;
        }
    }
    return numbers ;
}

您可能希望对返回的数字进行排序。 Collections 类(注意复数 s)具有用于排序的实用方法。

Collections.sort( numbers ) ;

ArrayList 实际上是通过分配一个新数组并从旧数组复制过来的。因此,新数组的大小可能比您实际需要的大。因此,当您完成向ArrayList 添加元素后,您可能希望将底层数组修剪到所需的最小大小。

Collections.trimToSize( numbers ) ;

最后,如果您有非常大的数组,您可能需要设置ArrayList 的初始大小。这避免了分配新数组和复制、起泡、冲洗、重复的增长过程。同样不要担心数十、数百或数千大小的数组,除非您的应用程序执行此工作很多次

int initialCapacity = 100_000 ;
ArrayList< Integer > numbers = new ArrayList<>( initialCapacity ) ;

把这些放在一起。

public static List< Integer > filterOutTooLowAndTooHigh( int[] ints , int min , int max )
{
    int initialCapacity = 100_000 ;
    ArrayList< Integer > numbers = new ArrayList<>( initialCapacity ) ;
    for( int i : ints ) {
        if ( !( i < min ) && ( i < max ) ) {  // Half-Open `[)`, beginning/lower is inclusive while the ending/higher is exclusive.
            numbers.add( i ) ;
        }
    }
    Collections.sort( numbers ) ;
    Collections.trimToSize() ;
    return numbers ;
}

我没有测试过该代码,但应该能让你朝着正确的方向前进。

您可能可以通过使用 Java Streams 以更少的代码完成此操作。但作为初学者,你不应该在以后使用流。首先熟悉这里讨论的手动处理数组和集合。

顺便说一句,这可能会对你有所帮助:Resize an Array while keeping current elements in Java?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 2017-07-02
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    相关资源
    最近更新 更多