为什么使用Arrays.sort()时不允许自动装箱原始数组?

时间:2013-12-11 18:25:31

标签: java sorting autoboxing

众所周知,自动装箱可能是计算密集型的,但在我看来,允许原始数组被自动装箱到它们的Object等效的排序方法是一个合适的边缘情况,特别是当基于的时候对值进行排序时一些外部计算。

我之前遇到过一个问题,其中一个给定的原始int数组需要根据索引值的计算结果进行排序。但是,java.util.Comparator不允许任何实现类和compare(T x, T y)方法的基本类型。

所以不要做像

这样的事情
public void sortRow(int row){
  Arrays.sort(this.buffer[row], new Comparator<Integer>(){  
    @Override
    public int compare(int x, int y){
      return (PhotoUtils.getBrightnessValue(x) <= PhotoUtils.getBrightnessValue(y) ? x : y;
    }
  }
}

我必须实施第二步:

public void sortRow(int row){
  Integer[] tempArray = new Integer[this.buffer[row].length];

  for (int i = 0; i < tempArray.length; i++)
    tempArray[i] = this.buffer[row][i];

  Arrays.sort(tempArray, new Comparator<Integer>(){  
    @Override
    public int compare(Integer x, Integer y){
      return (PhotoUtils.getBrightnessValue(x) <= PhotoUtils.getBrightnessValue(y) ? x : y;
    }
  }
}

3 个答案:

答案 0 :(得分:3)

根据JLS, Section 5.1.7,只有以下指定的装箱转换,并且任何数组都不涉及数组:

  

拳击转换将基本类型的表达式转换为   相应的引用类型表达式。具体来说,   以下九次转换被称为拳击转换:

     
      
  • 从类型布尔值到类型布尔

  •   
  • 从类型字节到类型字节

  •   
  • 从短类型到短类型

  •   
  • 从char类型到Character

  •   
  • 从int类型到Integer类型

  •   
  • 从long类型到Long

  •   
  • 从float类型到Float类型

  •   
  • 从类型double到类型Double

  •   
  • 从null类型到null类型

  •   

答案 1 :(得分:1)

我认为这里的问题更多的是Type参数只能是引用类型或通配符。 From the JLS Section 4.5.1

  

类型参数可以是引用类型或通配符。

Arrays.sort(E, Comparator<? super E>)方法是一种通用方法,其中类型变量E绑定到用于数组和Comparator的类型参数,即。他们必须是一样的。基元不能与泛型一起使用,因此您不能使用基本类型的数组。

  

为什么使用时不允许对原始数组进行自动装箱   Arrays.sort()?

因此Arrays.sort的问题不是自动装箱,而是泛型的限制。

为什么自动装箱不适用于原语,请参阅其他答案。基本上JLS不允许它。

答案 2 :(得分:0)

对于Autobox,单个值需要分配新的原始包装器对象。要对整个数组进行自动备份,需要为数组的每个元素分配新的primitve包装器对象,以及分配新的引用数组以保存对刚刚创建的新对象的引用。因此,对于由演员隐式完成的事情来说,这将是一个很大的开销。这意味着如果你有一个大小为1024的类型byte[]的变量,那么你必须分配一个引用数组,每个引用数为4-8个字节。并分配1024个Byte对象中的每一个以填充原始数组中的值。因此,除了最初添加到阵列的1024之外,您现在还要分配至少5120-9216个字节的数据。