按降序对原始types的数组进行sorting

我有大量的原始types(双)。 如何按降序排列元素?

不幸的是,Java API不支持用比较器对原始types进行sorting。

一种解决方法是sorting然后反向:

double[] array = new double[1048576]; ... Arrays.sort(array); // reverse the array for(int i=0;i<array.length/2;i++) { // swap the elements double temp = array[i]; array[i] = array[array.length-(i+1)]; array[array.length-(i+1)] = temp; } 

这很慢 – 特别是如果数组已经sorting的很好。

什么是更好的select?

Java Primitive包含基于自定义比较器对原始数组进行sorting的function。 使用它和Java 8,您的示例可以写成:

 double[] array = new double[1048576]; ... Primitive.sort(array, (d1, d2) -> Double.compare(d2, d1), false); 

如果您使用的是Maven,您可以将其包含在内:

 <dependency> <groupId>net.mintern</groupId> <artifactId>primitive</artifactId> <version>1.2.1</version> </dependency> 

当您将false作为第三个参数进行sort ,它将使用不稳定的sorting方式,即对Java内置双枢轴快速sorting的简单编辑。 这意味着速度应该接近于内置分类的速度。

完全公开:我写了Java Primitive库。

我认为最好不要重新发明轮子并使用Arrays.sort()。

是的,我看到了“降序”部分。 sorting是困难的部分,您想从Java库代码的简单性和速度中受益。 一旦完成,你只需倒转数组,这是一个相对便宜的O(n)操作。 下面是一些代码,我发现只要4行就可以做到这一点:

 for (int left=0, right=b.length-1; left<right; left++, right--) { // exchange the first and last int temp = b[left]; b[left] = b[right]; b[right] = temp; } 

Guava有将原始数组转换为包装types列表的方法。 好的部分是这些列表是实时视图,所以对它们的操作也在底层数组上工作(类似于Arrays.asList() ,但是对于基元)。

无论如何,这些列表中的每一个都可以传递给Collections.reverse()

 int[] intArr = { 1, 2, 3, 4, 5 }; float[] floatArr = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; double[] doubleArr = { 1.0d, 2.0d, 3.0d, 4.0d, 5.0d }; byte[] byteArr = { 1, 2, 3, 4, 5 }; short[] shortArr = { 1, 2, 3, 4, 5 }; Collections.reverse(Ints.asList(intArr)); Collections.reverse(Floats.asList(floatArr)); Collections.reverse(Doubles.asList(doubleArr)); Collections.reverse(Bytes.asList(byteArr)); Collections.reverse(Shorts.asList(shortArr)); System.out.println(Arrays.toString(intArr)); System.out.println(Arrays.toString(floatArr)); System.out.println(Arrays.toString(doubleArr)); System.out.println(Arrays.toString(byteArr)); System.out.println(Arrays.toString(shortArr)); 

输出:

[5,4,3,2,1]
[5.0,4.0,3.0,2.0,1.0]
[5.0,4.0,3.0,2.0,1.0]
[5,4,3,2,1]
[5,4,3,2,1]

 double[] array = new double[1048576]; 

默认顺序是升序

扭转顺序

 Arrays.sort(array,Collections.reverseOrder()); 

我认为最简单的解决scheme仍然是:

  1. 获取数组的自然顺序
  2. 在那个sorting的数组中find最大值,然后是最后一个项目
  3. 使用递减运算符的for循环

正如其他人所说的:使用toList是额外的努力,Arrays.sort(数组,Collections.reverseOrder())不能与基元一起工作,并且使用额外的框架似乎太复杂了,因为当你需要的只是已经inbuild的时候,好…

示例代码:

 import java.util.Arrays; public class SimpleDescending { public static void main(String[] args) { // unsorted array int[] integerList = {55, 44, 33, 88, 99}; // Getting the natural (ascending) order of the array Arrays.sort(integerList); // Getting the last item of the now sorted array (which represents the maximum, in other words: highest number) int max = integerList.length-1; // reversing the order with a simple for-loop System.out.println("Array in descending order:"); for(int i=max; i>=0; i--) { System.out.println(integerList[i]); } // You could make the code even shorter skipping the variable max and use // "int i=integerList.length-1" instead of int "i=max" in the parentheses of the for-loop } } 

你的实现(问题中的)比使用toList()包装和使用基于比较器的方法更快。 通过比较器方法或包装的Collections对象进行自动装箱和运行比仅反转要慢得多。

当然你可以自己写。 这可能不是你正在寻找的答案, 但是请注意,如果你对“如果数组已经sorting得相当好”的评论经常发生,你可能会很好地select一种处理这种情况的sortingalgorithm(例如插入)而不是使用Arrays.sort() (这是mergesort,或者如果元素的数量很小,则插入)。

在其他答案中, Arrays.asList有一些混淆。 如果你说

 double[] arr = new double[]{6.0, 5.0, 11.0, 7.0}; List xs = Arrays.asList(arr); System.out.println(xs.size()); // prints 1 

那么你将有一个列表与1元素。 生成的List将double []数组作为自己的元素。 你想要的是有一个List<Double>其元素是double[]的元素。

不幸的是,涉及比较器的解决scheme不适用于原始数组。 Arrays.sort在传递Object[]时只接受一个Comparator。 由于上述原因, Arrays.asList不会让你从你的数组元素中创build一个List。

所以,尽pipe我早些时候回答下面引用的评论,没有比sorting后手动颠倒数组更好的方法。 任何其他方法(例如将元素复制到Double[]并进行反向sorting并将其复制回来)将是更多的代码并且更慢。

您不能使用比较器对原始数组进行sorting。

你最好的办法是实现(或借用一个实现) 适合你的用例的sortingalgorithm来对数组进行sorting(在你的情况下是相反的顺序)。

用数字types,sorting前后的元素似乎是一种select。 速度相对于一个单一的反向sorting取决于caching,如果反转不快,任何差异可能会丢失的噪音。

我不知道Java核心API中的任何原始分类工具。

从我的D编程语言的实验(一种C类固醇)中,我发现合并sortingalgorithm可以说是最快的通用sortingalgorithm(这是D语言本身用来实现sortingfunction的) 。

  • Java中的一个实现
  • 另一个实现
  • 还有一个实现

如果性能很重要,而且列表通常已经很好地sorting。

泡沫sorting应该是最慢的sorting方法之一,但我已经看到最好的performance是一个简单的双向泡沫sorting的情况。

因此,这可能是less数情况下,你可以从自己编码的好处之一。 但是你确实需要做对(确保至less有人确认你的代码,certificate它的工作原理等)

正如其他人所指出的,从一个已sorting的数组开始,并在更改内容时对其进行sorting可能会更好。 这可能会更好。

对于小arrays这可能工作。

 int getOrder (double num, double[] array){ double[] b = new double[array.length]; for (int i = 0; i < array.length; i++){ b[i] = array[i]; } Arrays.sort(b); for (int i = 0; i < b.length; i++){ if ( num < b[i]) return i; } return b.length; } 

我很惊讶,数组b的初始加载是必要的

 double[] b = array; // makes b point to array. so beware! 

你的algorithm是正确的。 但是我们可以做如下的优化:在反转的时候,您可能会尝试保留另一个variables来减less反向计数器,因为array.length-(i + 1)的计算可能需要时间! 也可以移动临时的外部声明,以便每次不需要分配

 double temp; for(int i=0,j=array.length-1; i < (array.length/2); i++, j--) { // swap the elements temp = array[i]; array[i] = array[j]; array[j] = temp; } 
 Before sorting the given array multiply each element by -1 

然后使用Arrays.sort(arr),然后再乘以每个元素-1

 for(int i=0;i<arr.length;i++) arr[i]=-arr[i]; Arrays.sort(arr); for(int i=0;i<arr.length;i++) arr[i]=-arr[i]; 

如果使用java8,只需将数组转换为stream,然后进行sorting并转换回来。 所有的任务都可以一行完成,所以我觉得这个方法不错。

 double[] nums = Arrays.stream(nums).boxed(). .sorted((i1, i2) -> Double.compare(i2, i1)) .mapToDouble(Double::doubleValue) .toArray(); 

以下是我的解决scheme,您可以根据您的需求进行调整。

它是如何工作的? 它需要一个整数数组作为参数。 之后,它将创build一个新的数组,它将包含与参数数组相同的值。 这样做的原因是保持原始数组完好无损。

一旦新的数组包含复制的数据,我们通过交换值来对其sorting,直到条件if(newArr [i] <newArr [i + 1])的计算结果为false。 这意味着数组按降序排列。

为了彻底解释检查我的博客文章在这里 。

 public static int[] sortDescending(int[] array) { int[] newArr = new int[array.length]; for(int i = 0; i < array.length; i++) { newArr[i] = array[i]; } boolean flag = true; int tempValue; while(flag) { flag = false; for(int i = 0; i < newArr.length - 1; i++) { if(newArr[i] < newArr[i+1]) { tempValue = newArr[i]; newArr[i] = newArr[i+1]; newArr[i+1] = tempValue; flag = true; } } } return newArr; } 
 Double[] d = {5.5, 1.3, 8.8}; Arrays.sort(d, Collections.reverseOrder()); System.out.println(Arrays.toString(d)); 

Collections.reverseOrder()不适用于原语,但Double,Integer等可以与Collections.reverseOrder()