36 votes

Comment puis-je trier ce ArrayList comme je le souhaite?

Voici un programme de tri simple d'une ArrayList:

 ArrayList<String> list = new ArrayList<String>();

list.add("1_Update");
list.add("11_Add");
list.add("12_Delete");
list.add("2_Create");

Collections.sort(list);
for (String str : list) {
  System.out.println(str.toString());
}
 

Je m'attendais à la sortie de ce programme en tant que:

 1_Update
2_Create
11_Add
12_Delete
 

Mais quand je lance ce programme, je reçois une sortie en tant que:

 11_Add
12_Delete
1_Update
2_Create
 

Pourquoi est-ce et comment puis-je obtenir le ArrayList pour trier comme indiqué dans la sortie attendue?

70voto

nsayer Points 5594

Vous pouvez écrire un comparateur personnalisé:

 Collections.sort(list, new Comparator<String>() {
    public int compare(String a, String b) {
        return Integer.signum(fixString(a) - fixString(b));
    }
    private int fixString(String in) {
        return Integer.parseInt(in.substring(0, in.indexOf('_')));
    }
});
 

8voto

Jim Blake Points 707

Lorsque vous triez les données de ce type comme une chaîne de caractères, c'est de comparer les personnages eux-mêmes, y compris les chiffres. L'ensemble de la chaîne de caractères qui commence par "1", par exemple, vont finir ensemble. Si la commande se termine comme cela...

1 10 100 2 20 200

À aucun moment, ne le tri "réaliser" que vous êtes attribuer une signification à des sous-ensembles de la chaîne, telles que la longueur variable des numéros à l'avant de la chaîne. Lors du tri des numéros de chaînes, la marge intérieure à gauche avec des zéros autant que nécessaire pour couvrir le plus grand nombre peut aider, mais il ne résout pas vraiment le problème lorsque vous n'avez pas de contrôle sur les données, comme dans votre exemple. Dans ce cas, le tri serait...

001 002 010 020 100 200

6voto

Halvard Points 1219

Il est trié sous forme de texte (par ordre alphabétique) et non sous forme de nombre. Pour contourner ce problème, vous pouvez implémenter un comparateur personnalisé comme suggéré dans la réponse de nsayer.

3voto

QSmienk Points 95

Il est en train de faire une comparaison lexicographique. Il compare le premier caractère de chaque chaîne de tri. Il compare ensuite la deuxième chaîne de ceux avec le même personnage. Quand il compare le caractère '_' pour un certain nombre, c'est plus de valeur que n'importe quel nombre de caractères comme 8 > 7 > 9. Rappelez-vous qu'il est en train de faire une comparaison de caractères et non pas une comparaison numérique.

Il existe des moyens pour mettre en œuvre votre propre personnalisé de tri routage qui peut être mieux que de renommer vos noms de script.

Si renommer vos noms de script est une option, cela peut permettre à d'autres outils de script à utiliser. Un format peut être

01_create_table.sql
02_create_index.sql
11_assign_privileges.sql

En gardant vos deux premiers chiffres à deux personnages, la comparaison lexicographique fonctionne.

2voto

Vincent Ramdhanie Points 46265

La documentation de la méthode Collections.sort () indique:

Trie la liste spécifiée en ordre croissant, en fonction de l'ordre naturel de ses éléments.

Ce qui signifie pour les chaînes que vous allez obtenir la liste par ordre alphabétique. String 11_assign_privileges.sql vient avant les chaînes 1_create_table.sql et 12_07_insert_static_data.sql vient avant 1_create_table.sql, etc. Ainsi, le programme fonctionne comme prévu.

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