【问题标题】:How to use compareTo within a Generic array in java?java - 如何在Java的通用数组中使用compareTo?
【发布时间】:2011-10-17 15:13:09
【问题描述】:

我想弄清楚如何比较 T[] 数组中的两个项目,这就是我所拥有的:

public static <T extends Comparable< ? super T>> T getLargest(T [] a, int low, 
               int high){
    if(low>high)
            throw new IllegalArgumentException();
    T[] arrCopy = (T[]) new Object[high-low];
    for(int i=low;i<high;i++){
        if(a[i].compareTo(a[i-1])>0)
            arrCopy[i]=a[i];
        else
            arrCopy[i]=a[i+1];
    }
    return arrCopy[0];
}

然后我得到错误:Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;

关于如何解决这个问题的任何想法?

【问题讨论】:

  • 您的方法标头中缺少“throws”子句,特别是“throws IllegalArgumentException”。
  • @0xCAFEBABE IllegalArgumentException 是运行时异常,不需要声明
  • 那一定是实现 max() 方法的最迂回版本了 xX 你这里显然不需要任何数组。
  • @Voo:我不认为它实现了最大值
  • @newacct 好吧,它不起作用有几个原因,我很难理解为什么有人会编写这样的函数。但我通过简单的推论:一个名为getLargest() 的函数应该返回最大值;)

标签: java arrays generics compareto


【解决方案1】:

你可以这样分配数组:

@SuppressWarnings("unchecked")
T[] arrCopy = (T[]) Array.newInstance(a.getClass().getComponentType(), high-low);

虽然未经检查的警告是必要的,但这实际上应该是安全的。

顺便说一句,如果你想在数组中找到最大的元素,这里有一个 oneliner:

public static <T extends Comparable<T>> T max(final T[] data) {
    return Collections.max(Arrays.asList(data));
}

对于完整的问题,您可以使用以下两者之一(它们是等效的):

public static <T extends Comparable<T>> T maxA(final T[] data,int from, int to) {
    return Collections.max(Arrays.asList(Arrays.copyOfRange(data, from, to)));
}
public static <T extends Comparable<T>> T maxB(final T[] data,int from, int to) {
    return Collections.max(Arrays.asList(data).subList(from, to));
}

【讨论】:

  • 谢谢,这会很完美,但我需要在数组中给出我想要查看最大数字的切片,int low 和 int high。
  • @fgualda87 好的,将我的 oneliner 与 Arrays.copyOfRange() 结合起来,查看我的更新
  • 我认为 List.subList 更可取,因为它不会复制任何数据——它只是一个视图。
  • @Puce 原则上是的,但是 Arrays.copyOfRange() 使用 System.arrayCopy() 使用本机系统例程并且非常快
  • @Sean Patrick Floyd:与根本不复制的视图相比,快速复制实现仍然较慢并且占用更多内存。
【解决方案2】:

当您只关心 1 个对象时,不确定为什么要创建一个全新的数组,但这个问题与泛型无关。你不能将Object[] 转换为更具体的类型,比如String[],就像你不能写String s = new Object()一样。

由于您只关心最大值,因此只跟踪 1 个值(迄今为止看到的最大值)而不是整个数组会更有意义。

【讨论】:

    【解决方案3】:

    你在这里得到错误:

    T[] arrCopy = (T[]) new Object[high-low];
    

    您不能将所有对象 (java.lang.object) 的母对象强制转换为任何以 java.lang.comparable 作为最低公分母的对象,因此会引发异常。一个对象(如在 java.lang.object 中)没有实现 java.lang.comparable。

    在您的具体示例中,您需要创建一个 T 数组(或至少 java.lang.comparable)。

    【讨论】:

    • 你实际上不能构造T类型的数组。例如,看看java.util.ArrayList 是如何实现的。
    • @DilumRanatunga true,但是给定一个现有数组,您可以访问它的组件类型(请参阅我的答案)
    【解决方案4】:

    没有理由假设Object 实例数组适合作为Comparable 实例数组处理。您将Object 强制转换为T,我们希望它扩展Comparable,但这里甚至不需要未经检查的分配。

    相反,考虑一个不复制任何数组的实现:

    public static <T extends Comparable<? super T>>
    T getLargest(T[] a, int first, int last)
    {
      // Don't tolerate an empty range:
      if (first >= last)
        throw new IllegalArgumentException();
      // Eventually checked by subsequent use of array index operator:
      if (first < 0 || first >= a.length ||
          last < 0 || last >= a.length)
        throw new IndexOutOfBoundsException();
    
      T largest = a[first];
      while (++first != last)
      {
        final T candidate = a[first];
        if (candidate.compareTo(largest) > 0)
          largest = candidate;
      }
      return largest;
    }
    

    或者,使用Collections#max(),在将数组传递给Arrays#asList() 后,将其提供为List

    【讨论】:

      【解决方案5】:

      用途:

      public static <T extends Comparable<? super T>> T max(final T[] data, int fromIndex, 
                     int toIndex) {
          return Collections.max(Arrays.asList(data).subList(fromIndex, toIndex));
      }
      

      【讨论】:

        【解决方案6】:

        只需将new Object[high-low]; 更改为new Comparable[high-low];。泛型被擦除到它们的下限,所以 T 被擦除到 Comparable。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-27
          • 1970-01-01
          • 2012-08-07
          相关资源
          最近更新 更多