Tri des tableaux de types primitifs en ordre décroissant

J’ai un grand nombre de types primitifs (double). Comment est-ce que je sortinge les éléments dans l’ordre décroissant ?

Malheureusement, l’API Java ne prend pas en charge le sorting des types primitifs avec un comparateur.

Une solution de contournement serait de sortinger puis de revenir en arrière:

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; } 

C’est lent – particulièrement si le tableau est déjà bien sortingé.

Quelle est une meilleure alternative?

Java Primitive inclut des fonctionnalités pour sortinger les tableaux primitifs basés sur un comparateur personnalisé. En l’utilisant, ainsi que Java 8, votre exemple pourrait être écrit comme suit:

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

Si vous utilisez Maven, vous pouvez l’inclure avec:

  net.mintern primitive 1.2.1  

Lorsque vous transmettez false tant que troisième argument à sort , il utilise un sorting instable, une simple modification du sorting rapide à double pivot intégré à Java. Cela signifie que la vitesse doit être proche de celle du sorting intégré.

Divulgation complète: j’ai écrit la bibliothèque Java Primitive.

Je pense qu’il serait préférable de ne pas réinventer la roue et d’utiliser Arrays.sort ().

Oui, j’ai vu la partie “décroissante”. Le sorting est la partie la plus difficile et vous souhaitez bénéficier de la simplicité et de la rapidité du code de la bibliothèque Java. Une fois cela fait, vous inversez simplement le tableau, ce qui est une opération O (n) relativement peu coûteuse. Voici un code que j’ai trouvé en 4 lignes:

 for (int left=0, right=b.length-1; left 

Guava a des méthodes pour convertir des tableaux primitifs en listes de types de wrapper. La partie intéressante est que ces listes sont des vues en direct, de sorte que leurs opérations fonctionnent également sur les tableaux sous-jacents (similaire à Arrays.asList() , mais pour les primitives).

Quoi qu’il en soit, chacune de ces listes peut être transmise à 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.toSsortingng(intArr)); System.out.println(Arrays.toSsortingng(floatArr)); System.out.println(Arrays.toSsortingng(doubleArr)); System.out.println(Arrays.toSsortingng(byteArr)); System.out.println(Arrays.toSsortingng(shortArr)); 

Sortie:

[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]; 

Par défaut, l’ordre est croissant

Inverser la commande

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

Je pense que la solution la plus simple est toujours la suivante:

  1. Obtenir l’ordre naturel du tableau
  2. Trouver le maximum dans ce tableau sortingé qui est alors le dernier élément
  3. Utiliser un for-loop avec un opérateur de décrémentation

Comme d’autres l’ont déjà dit: l’utilisation de toList est un effort supplémentaire, Arrays.sort (array, Collections.reverseOrder ()) ne fonctionne pas avec les primitives et l’utilisation d’un framework supplémentaire semble trop compliquée lorsque tout ce dont vous avez besoin est déjà bien…

Exemple de code:

 import java.util.Arrays; public class SimpleDescending { public static void main(Ssortingng[] 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 } } 

Votre implémentation (celle de la question) est plus rapide que, par exemple, l’emballage avec toList() et une méthode basée sur un comparateur. La mise en boîte automatique et l’exécution de méthodes de comparaison ou d’objects Collections enveloppés sont beaucoup plus lentes que la simple inversion.

Bien sûr, vous pourriez écrire votre propre sorte. Ce n’est peut-être pas la réponse que vous recherchez, mais notez que si votre commentaire sur “si le tableau est déjà bien sortingé” se produit fréquemment, vous feriez bien de choisir un algorithme de sorting qui gère bien ce cas (par exemple, insertion) plutôt que d’utiliser Arrays.sort() (qui est un fusion ou une insertion si le nombre d’éléments est petit).

Il y a eu une certaine confusion concernant Arrays.asList dans les autres réponses. Si tu le dis

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

alors vous aurez une liste avec 1 élément. La liste résultante a le tableau double [] comme son propre élément. Ce que vous voulez, c’est avoir une List dont les éléments sont les éléments du double[] .

Malheureusement, aucune solution impliquant des comparateurs ne fonctionnera pour un tableau primitif. Arrays.sort accepte uniquement un comparateur lorsqu’il Arrays.sort un Object[] . Et pour les raisons décrites ci-dessus, Arrays.asList ne vous laissera pas créer une liste des éléments de votre tableau.

Donc, malgré ma réponse antérieure que les commentaires ci-dessous font référence, il n’y a pas de meilleur moyen que d’inverser manuellement le tableau après le sorting. Toute autre approche (telle que la copie des éléments dans un Double[] et leur sorting inverse et copie) serait plus lente et plus codée.

Vous ne pouvez pas utiliser les comparateurs pour sortinger les tableaux primitifs.

Votre meilleur pari est d’implémenter (ou d’emprunter une implémentation) un algorithme de sorting adapté à votre cas d’utilisation pour sortinger le tableau (dans l’ordre inverse dans votre cas).

Avec les types numériques, la négation des éléments avant et après le sorting semble une option. La vitesse par rapport à un seul retour après sorting dépend de la mémoire cache, et si l’inverse n’est pas plus rapide, toute différence peut être perdue dans le bruit.

Je ne connais pas d’installations de sorting primitives au sein de l’API Java Core.

De mes expérimentations avec le langage de programmation D (une sorte de C sur les stéroïdes), j’ai trouvé que l’algorithme de sorting de fusion est sans doute l’algorithme de sorting polyvalent le plus rapide (c’est ce que le langage D lui-même utilise pour implémenter sa fonction de sorting) .

  • Une implémentation en Java
  • Une autre implémentation
  • Une mise en œuvre supplémentaire

Si la performance est importante et que la liste est généralement déjà bien classée.

Le sorting à bulles devrait être l’un des moyens les plus lents de sorting, mais j’ai vu des cas où la meilleure performance était un simple sorting à bulles bidirectionnel.

Donc, cela peut être l’un des rares cas où vous pouvez bénéficier d’un codage vous-même. Mais vous devez vraiment le faire correctement (assurez-vous qu’au moins quelqu’un d’autre confirme votre code, prouve qu’il fonctionne, etc.)

Comme quelqu’un d’autre l’a souligné, il peut être préférable de commencer avec un tableau sortingé et de le conserver pendant que vous modifiez le contenu. Cela peut encore mieux fonctionner.

pour les petites masortingces, cela peut fonctionner.

 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; } 

J'ai été surpris que le chargement initial du tableau b était nécessaire

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

Votre algorithme est correct. Mais nous pouvons faire de l’optimisation comme suit: Lors de l’inversion, vous pouvez essayer de garder une autre variable pour réduire le compteur puisque le calcul de array.length- (i + 1) peut prendre du temps! Et aussi déplacer la déclaration de temp dehors afin que chaque fois il ne doit pas être alloué

 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 

puis utilisez Arrays.sort (arr) puis multipliez chaque élément par -1

 for(int i=0;i 

Si vous utilisez java8, convertissez simplement le tableau en stream, sortingez et reconvertissez. Toutes les tâches peuvent être effectuées en une seule ligne, donc je pense que ce n’est pas trop mal.

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

Voici ma solution, vous pouvez l’adapter à vos besoins.

Comment ça marche? Il prend un tableau d’entiers comme arguments. Après cela, il créera un nouveau tableau qui contiendra les mêmes valeurs que le tableau des arguments. La raison de cela est de laisser le tableau d’origine intact.

Une fois que le nouveau tableau contient les données copiées, nous les sortingons en échangeant les valeurs jusqu’à la condition si (newArr [i] évalué à false. Cela signifie que le tableau est sortingé par ordre décroissant.

Pour une explication approfondie, consultez mon blog ici .

 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.toSsortingng(d)); 

Collections.reverseOrder () ne fonctionne pas sur les primitives, mais Double, Integer etc. fonctionne avec Collections.reverseOrder ()

Dans Java 8, une approche meilleure et plus concise pourrait être:

 double[] arr = {13.6, 7.2, 6.02, 45.8, 21.09, 9.12, 2.53, 100.4}; Double[] boxedarr = Arrays.stream( arr ).boxed().toArray( Double[]::new ); Arrays.sort(boxedarr, Collections.reverseOrder()); System.out.println(Arrays.toSsortingng(boxedarr)); 

Cela donnerait le tableau inversé et est plus présentable.

Entrée: [13.6, 7.2, 6.02, 45.8, 21.09, 9.12, 2.53, 100.4]

Sortie: [100.4, 45.8, 21.09, 13.6, 9.12, 7.2, 6.02, 2.53]