98 votes

Comment trier un tableau d'entiers en utilisant un comparateur personnalisé ?

J'ai besoin de trier un tableau d'entiers en utilisant un comparateur personnalisé, mais la bibliothèque Java ne fournit pas de fonction de tri pour les entiers avec des comparateurs (les comparateurs ne peuvent être utilisés qu'avec des objets). Existe-t-il un moyen simple de le faire ?

0 votes

Voulez-vous simplement trier le tableau par ordre décroissant ou voulez-vous effectuer quelque chose de plus compliqué ?

1 votes

Quelque chose de plus compliqué. Je veux trier les int en utilisant la valeur absolue comme clé.

69voto

Jon Freedman Points 4411

Si vous ne pouvez pas changer le type de votre tableau d'entrée, la méthode suivante fonctionnera :

final int[] data = new int[] { 5, 4, 2, 1, 3 };
final Integer[] sorted = ArrayUtils.toObject(data);
Arrays.sort(sorted, new Comparator<Integer>() {
    public int compare(Integer o1, Integer o2) {
        // Intentional: Reverse order for this demo
        return o2.compareTo(o1);
    }
});
System.arraycopy(ArrayUtils.toPrimitive(sorted), 0, data, 0, sorted.length);

Cela utilise ArrayUtils du projet commons-lang pour convertir facilement entre int[] y Integer[] crée une copie du tableau, effectue le tri, puis copie les données triées sur l'original.

3 votes

Pourquoi n'utilisez-vous pas Arrays.sort au lieu de convertir tableau -> liste -> tableau ?

0 votes

Bon point, j'ai mis à jour, j'ai joué avec les primitives communes, mais je n'ai rien fait d'utile.

0 votes

Je ne savais pas pour commons-lang. Merci pour le tuyau.

43voto

user3669782 Points 697

Que diriez-vous d'utiliser des flux (Java 8) ?

int[] ia = {99, 11, 7, 21, 4, 2};
ia = Arrays.stream(ia).
    boxed().
    sorted((a, b) -> b.compareTo(a)). // sort descending
    mapToInt(i -> i).
    toArray();

Ou en place :

int[] ia = {99, 11, 7, 21, 4, 2};
System.arraycopy(
        Arrays.stream(ia).
            boxed().
            sorted((a, b) -> b.compareTo(a)). // sort descending
            mapToInt(i -> i).
            toArray(),
        0,
        ia,
        0,
        ia.length
    );

11voto

leventov Points 2552

Vous pouvez utiliser IntArrays.quickSort(array, comparator) de la bibliothèque fastutil.

8voto

user1460736 Points 89

Si vous ne voulez pas copier le tableau (disons qu'il est très grand), vous pouvez créer un wrapper List<Integer> qui peuvent être utilisés dans un tri :

final int[] elements = {1, 2, 3, 4};
List<Integer> wrapper = new AbstractList<Integer>() {

        @Override
        public Integer get(int index) {
            return elements[index];
        }

        @Override
        public int size() {
            return elements.length;
        }

        @Override
        public Integer set(int index, Integer element) {
            int v = elements[index];
            elements[index] = element;
            return v;
        }

    };

Et maintenant vous pouvez faire un tri sur cette liste enveloppante en utilisant un comparateur personnalisé.

7voto

XL Zheng Points 103

Vous n'avez pas besoin d'une bibliothèque externe :

Integer[] input = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Arrays.sort(input, (a, b) -> b - a); // reverse order
return Arrays.stream(input).mapToInt(Integer::intValue).toArray();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X