Comment trier une ArrayList?

353

J'ai une liste de doubles en java et je veux trier ArrayList dans l'ordre décroissant.

Input ArrayList est comme ci-dessous:

List<Double> testList = new ArrayList();

testList.add(0.5);
testList.add(0.2);
testList.add(0.9);
testList.add(0.1);
testList.add(0.1);
testList.add(0.1);
testList.add(0.54);
testList.add(0.71);
testList.add(0.71);
testList.add(0.71);
testList.add(0.92);
testList.add(0.12);
testList.add(0.65);
testList.add(0.34);
testList.add(0.62);

Le résultat devrait être comme ça

0.92
0.9
0.71
0.71
0.71
0.65
0.62
0.54
0.5
0.34
0.2
0.12
0.1
0.1
0.1
Himanshu
la source

Réponses:

526
Collections.sort(testList);
Collections.reverse(testList);

Cela fera ce que vous voulez. Rappelez - vous d'importer Collectionsbien!

Voici la documentation deCollections .

tckmn
la source
53
Peut-être qu'il vaut la peine de mentionner que vous pouvez définir le vôtre Comparator:)
Polygnome
1
@Polygnome L'OP trie uniquement les Doubles.
tckmn le
3
Oui, mais vous pouvez les trier de différentes manières, selon le cas d'utilisation. Parfois, vous voudrez peut-être les trier par distance à 0. Je ne connais même pas les caractéristiques d'exécution de reverse, mais le tri décroissant pourrait en fait être plus rapide que le tri ascendant puis l'inverse. De plus, l'utilisation d'une implémentation List qui prend Comparatoren charge comme argument constructeur (la gardant ainsi invariante) garantirait que la liste est triée à tout moment.
Polygnome
4
@Ayesha Oui, Collections.sortutilise compareTodans les coulisses.
tckmn
45
Il faut réellement utiliser Collections.sort(list, Collections.reverseOrder());. En plus d'être plus idiomatique (et peut-être plus efficace), l'utilisation du comparateur d'ordre inverse garantit que le tri est stable (ce qui signifie que l'ordre des éléments ne sera pas changé lorsqu'ils sont égaux selon le comparateur, alors que l'inversion changera l'ordre ).
Marco13
134

Descendant:

Collections.sort(mArrayList, new Comparator<CustomData>() {
    @Override
    public int compare(CustomData lhs, CustomData rhs) {
        // -1 - less than, 1 - greater than, 0 - equal, all inversed for descending
        return lhs.customInt > rhs.customInt ? -1 : (lhs.customInt < rhs.customInt) ? 1 : 0;
    }
});
bong jae choe
la source
1
Que dois-je faire si CustomData c'est List<AnotherModel>qui AnotherModela idet je veux trier par id? Et je viens d'accéder au CustomData modèle dans ma classe.
Dr.jacky
2
Vous devez simplement remplacer la classe CustomData par AnotherModel et avoir une ligne comme celle-ci: return lhs.id> rhs.id? -1: .. etc
user2808054
La déclaration de retour de comparaison peut être mieux écrite commeInteger.compare(rhs.customInt, lhs.customInt);
LordKiz
92

Utilisez la méthode util de la classe java.util.Collections , c.-à-d.

Collections.sort(list)

En fait, si vous souhaitez trier un objet personnalisé, vous pouvez utiliser

Collections.sort(List<T> list, Comparator<? super T> c) 

voir les collections api

M Sach
la source
90

Pour votre exemple, cela fera la magie de Java 8

List<Double> testList = new ArrayList();
testList.sort(Comparator.naturalOrder());

Mais si vous souhaitez trier par certains des champs de l'objet que vous triez, vous pouvez le faire facilement en:

testList.sort(Comparator.comparing(ClassName::getFieldName));

ou

 testList.sort(Comparator.comparing(ClassName::getFieldName).reversed());

ou

 testList.stream().sorted(Comparator.comparing(ClassName::getFieldName).reversed()).collect(Collectors.toList());

Sources: https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html

krmanish007
la source
Où se situe la méthode de «comparaison»?
lippo
1
vous devez importer: import statique java.util.Comparator.comparing;
krmanish007
1
Il est disponible avec Java 1.7?
lippo
5
Non, cela fait partie du flux et de l'interface fonctionnelle, qui fait partie de Java 8
krmanish007
1
Vous avez raison @AjahnCharles. Ils ont supprimé l'argument zéro, j'ai donc mis à jour ma réponse maintenant.
krmanish007
54

En utilisant lambdas (Java8) et en le dépouillant de la syntaxe la plus simple (la JVM en déduira beaucoup dans ce cas), vous obtenez:

Collections.sort(testList, (a, b) -> b.compareTo(a));

Une version plus verbeuse:

// Implement a reverse-order Comparator by lambda function
Comparator<Double> comp = (Double a, Double b) -> {
    return b.compareTo(a);
};

Collections.sort(testList, comp);

L'utilisation d'un lambda est possible car l'interface du comparateur n'a qu'une seule méthode à implémenter, de sorte que la machine virtuelle peut déduire quelle méthode implémente. Étant donné que les types de paramètres peuvent être déduits, ils n'ont pas besoin d'être indiqués (c'est- (a, b)à- dire au lieu de (Double a, Double b). Et puisque le corps lambda n'a qu'une seule ligne, et que la méthode devrait renvoyer une valeur, le returnest inféré et les accolades ne sont pas nécessaires.

cyrus
la source
C'est cool, merci! Celui-ci est un peu plus compact: Collections.sort (testList, Comparator.reverseOrder ());
kavics
Encore plus compact: testList.sort (Comparator.reverseOrder ());
jonasespelita
29

Avec Java8, il existe une méthode de tri par défaut sur l'interface List qui vous permettra de trier la collection si vous fournissez un comparateur. Vous pouvez facilement trier l'exemple de la question comme suit:

testList.sort((a, b) -> Double.compare(b, a));

Remarque: les arguments dans le lambda sont échangés lorsqu'ils sont transmis à Double.compare pour garantir que le tri est décroissant

robjwilkins
la source
Pour moi, c'est la meilleure réponse car elle fonctionne également pour le tri à l'aide d'objets ... exemple locationDetails.sort((locationDetailAsc,locationDetailsDsc) -> Long.compare(locationDetailsDsc.getSnapshot().getQuantity(), locationDetailAsc.getSnapshot().getQuantity()));
Anas
26

Vous pouvez utiliser Collections.sort(list)pour trier listsi votre listcontient des Comparableéléments. Sinon, je vous recommanderais d'implémenter cette interface comme ici:

public class Circle implements Comparable<Circle> {}

et bien sûr fournir votre propre réalisation de compareTométhode comme ici:

@Override
    public int compareTo(Circle another) {
        if (this.getD()<another.getD()){
            return -1;
        }else{
            return 1;
        }
    }

Et puis vous pouvez à nouveau utiliser Colection.sort(list)comme maintenant la liste contient des objets de type comparable et peut être triée. L'ordre dépend de la compareTométhode. Consultez ce https://docs.oracle.com/javase/tutorial/collections/interfaces/order.html pour des informations plus détaillées.

Yuriy
la source
11

Collections.sortvous permet de passer une instance de a Comparatorqui définit la logique de tri. Ainsi, au lieu de trier la liste dans l'ordre naturel puis de l'inverser, on peut simplement passer Collections.reverseOrder()à sortpour trier la liste dans l'ordre inverse:

// import java.util.Collections;
Collections.sort(testList, Collections.reverseOrder());

Comme mentionné par @ Marco13, en plus d'être plus idiomatique (et peut-être plus efficace), l'utilisation du comparateur d'ordre inverse garantit que le tri est stable (ce qui signifie que l'ordre des éléments ne sera pas modifié lorsqu'ils sont égaux selon le comparateur, alors que l'inversion changera l'ordre)

Mat
la source
9
//Here is sorted List alphabetically with syncronized

package com.mnas.technology.automation.utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * @author manoj.kumar
 */
public class SynchronizedArrayList {
    static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName());

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

        List<Employee> synchronizedList = Collections.synchronizedList(new ArrayList<Employee>());
        synchronizedList.add(new Employee("Aditya"));
        synchronizedList.add(new Employee("Siddharth"));
        synchronizedList.add(new Employee("Manoj"));
        Collections.sort(synchronizedList, new Comparator() {
            public int compare(Object synchronizedListOne, Object synchronizedListTwo) {
                //use instanceof to verify the references are indeed of the type in question
                return ((Employee) synchronizedListOne).name
                        .compareTo(((Employee) synchronizedListTwo).name);
            }
        }); 
    /*for( Employee sd : synchronizedList) {
    log.info("Sorted Synchronized Array List..."+sd.name);
    }*/

        // when iterating over a synchronized list, we need to synchronize access to the synchronized list
        synchronized (synchronizedList) {
            Iterator<Employee> iterator = synchronizedList.iterator();
            while (iterator.hasNext()) {
                log.info("Sorted Synchronized Array List Items: " + iterator.next().name);
            }
        }

    }
}

class Employee {
    String name;

    Employee(String name) {
        this.name = name;

    }
}
Hitesh sapra
la source
semble être thas est Collections.synchronizedList nous aide
vitalinvent
7

Voici un petit cheatsheet qui couvre des cas typiques:

// sort
list.sort(naturalOrder())

// sort (reversed)
list.sort(reverseOrder())

// sort by field
list.sort(comparing(Type::getField))

// sort by field (reversed)
list.sort(comparing(Type::getField).reversed())

// sort by int field
list.sort(comparingInt(Type::getIntField))

// sort by double field (reversed)
list.sort(comparingDouble(Type::getDoubleField).reversed())

// sort by nullable field (nulls last)
list.sort(comparing(Type::getNullableField, nullsLast(naturalOrder())))

// two-level sort
list.sort(comparing(Type::getField1).thenComparing(Type::getField2))
ZhekaKozlov
la source
5

si vous utilisez Java SE 8, cela peut être utile.

//create a comparator object using a Lambda expression
Comparator<Double> compareDouble = (d1, d2) -> d1.compareTo(d2);

//Sort the Collection in this case 'testList' in reverse order
Collections.sort(testList, Collections.reverseOrder(compareDouble));

//print the sorted list using method reference only applicable in SE 8
testList.forEach(System.out::println);
Franklin Okeme
la source
6
Il y a aussi Collections.reverseOrder()sans aucun argument, ce qui rend votre implémentation de compareDoublesuperflu (c'est équivalent à l'ordre naturel de Doubles). La réponse ici devrait êtreCollections.sort(testList, Collections.reverseOrder());
Matt
5

| * | Tri d'une liste:

import java.util.Collections;

| => Ordre de tri asc:

Collections.sort(NamAryVar);

| => Trier l'ordre Dsc:

Collections.sort(NamAryVar, Collections.reverseOrder());

| * | Inversez l'ordre de la liste:

Collections.reverse(NamAryVar);
Sujay UN
la source
4

Vous pouvez faire comme ça:

List<String> yourList = new ArrayList<String>();
Collections.sort(yourList, Collections.reverseOrder());

La collection a un comparateur par défaut qui peut vous aider avec cela.

De plus, si vous souhaitez utiliser certaines nouvelles fonctionnalités de Java 8, vous pouvez faire comme ça:

List<String> yourList = new ArrayList<String>();
yourList = yourList.stream().sorted(Collections.reverseOrder()).collect(Collectors.toList());
Thiago
la source
3

Par exemple, j'ai une classe Person: String name, int age ==> Constructor new Person (name, age)

import java.util.Collections;
import java.util.ArrayList;
import java.util.Arrays;


public void main(String[] args){
    Person ibrahima=new Person("Timera",40);
    Person toto=new Person("Toto",35);
    Person alex=new Person("Alex",50);
    ArrayList<Person> myList=new ArrayList<Person>
    Collections.sort(myList, new Comparator<Person>() {
        @Override
        public int compare(Person p1, Person p2) {
            // return p1.age+"".compareTo(p2.age+""); //sort by age
            return p1.name.compareTo(p2.name); // if you want to short by name
        }
    });
    System.out.println(myList.toString());
    //[Person [name=Alex, age=50], Person [name=Timera, age=40], Person [name=Toto, age=35]]
    Collections.reverse(myList);
    System.out.println(myList.toString());
    //[Person [name=Toto, age=35], Person [name=Timera, age=40], Person [name=Alex, age=50]]

}
Ibrahima Timera
la source
if you want to short by name->if you want to sort by name
linrongbin
3

Dans JAVA 8, c'est beaucoup plus facile maintenant.

List<String> alphaNumbers = Arrays.asList("one", "two", "three", "four");
List<String> alphaNumbersUpperCase = alphaNumbers.stream()
    .map(String::toUpperCase)
    .sorted()
    .collect(Collectors.toList());
System.out.println(alphaNumbersUpperCase); // [FOUR, ONE, THREE, TWO]

- Pour une utilisation inverse,

.sorted(Comparator.reverseOrder())
Appesh
la source
3

Vous pouvez utiliser comme ça

ArrayList<Group> groupList = new ArrayList<>();
Collections.sort(groupList, Collections.reverseOrder());
Collections.reverse(groupList);
manikant gautam
la source
1

Avec Eclipse Collections, vous pouvez créer une double liste primitive, la trier puis l'inverser pour la mettre dans l'ordre décroissant. Cette approche éviterait de boxer les doubles.

MutableDoubleList doubleList =
    DoubleLists.mutable.with(
        0.5, 0.2, 0.9, 0.1, 0.1, 0.1, 0.54, 0.71,
        0.71, 0.71, 0.92, 0.12, 0.65, 0.34, 0.62)
        .sortThis().reverseThis();
doubleList.each(System.out::println);

Si vous voulez un List<Double>, alors ce qui suit fonctionnerait.

List<Double> objectList =
    Lists.mutable.with(
        0.5, 0.2, 0.9, 0.1, 0.1, 0.1, 0.54, 0.71,
        0.71, 0.71, 0.92, 0.12, 0.65, 0.34, 0.62)
        .sortThis(Collections.reverseOrder());
objectList.forEach(System.out::println);

Si vous souhaitez conserver le type sous ArrayList<Double>, vous pouvez initialiser et trier la liste à l'aide de la ArrayListIterateclasse utilitaire comme suit:

ArrayList<Double> arrayList =
    ArrayListIterate.sortThis(
            new ArrayList<>(objectList), Collections.reverseOrder());
arrayList.forEach(System.out::println);

Remarque: je suis un committer pour les collections Eclipse .

Donald Raab
la source
1

La ligne suivante devrait faire l'épaisseur

testList.sort(Collections.reverseOrder());
Ivan Kovtun
la source