web-dev-qa-db-fra.com

Collection triée en Java

Je suis débutant en Java. Veuillez suggérer quelle (s) collection (s) peut/devrait être utilisée pour maintenir une liste triée en Java. J'ai essayé Map et Set, mais ce n'était pas ce que je cherchais.

156
rohan

Cela arrive très tard, mais il existe une classe dans le JDK uniquement pour avoir une liste triée. Il est nommé (quelque peu en désordre avec les autres interfaces Sorted*) "Java.util.PriorityQueue". Il peut trier Comparable<?>s ou en utilisant un Comparator.

La différence avec un List trié à l'aide de Collections.sort(...) est que cela permet de conserver en permanence un ordre partiel, avec les performances d'insertion O(log(n)), à l'aide d'une structure de données en tas, trié ArrayList sera O(n) (c'est-à-dire, en utilisant la recherche et le déplacement binaires).

Cependant, contrairement à List, PriorityQueue ne prend pas en charge l’accès indexé (get(5)), le seul moyen d’accéder aux éléments d’un tas est de les supprimer un par un (ainsi le nom PriorityQueue).

181
Martin Probst

TreeMap et TreeSet vous donneront une itération sur le contenu dans un ordre trié. Vous pouvez également utiliser une liste de tableaux et utiliser Collections.sort () pour le trier. Toutes ces classes sont en Java.util

53
Michael Borgwardt

Si vous souhaitez conserver une liste triée que vous modifierez fréquemment (c'est-à-dire une structure qui, en plus d'être triée, permet les doublons et dont les éléments peuvent être efficacement référencés par index), utilisez ensuite ArrayList. mais lorsque vous devez insérer un élément, utilisez toujours Collections.binarySearch () pour déterminer l'index auquel vous ajoutez un élément donné. La dernière méthode vous indique l’index que vous devez insérer à pour conserver votre liste dans l’ordre trié.

32
Neil Coffey

Utilisez TreeMultiset class de Google Guava. Guava a une API de collections spectaculaire.

Un problème avec la mise en œuvre de List qui maintient l'ordre trié est la promesse faite dans les JavaDocs de la méthode add().

31
jtb

Vous voulez le SortedSet implémentations, à savoir TreeSet .

12
cletus

Il y a quelques options. Si vous ne voulez pas de doublons et si les objets que vous insérez sont comparables, je vous suggérerais TreeSet.

Vous pouvez également utiliser les méthodes statiques de la classe Collections pour ce faire.

Voir Collections # sort (Java.util.List) et TreeSet pour plus d'informations.

12
BenM

Si vous souhaitez simplement trier une liste, utilisez n’importe quel type de List et utilisez Collections.sort () . Si vous voulez vous assurer que les éléments de la liste sont uniques et toujours triés, utilisez un SortedSet .

9
Guillaume

Ce que j'ai fait est d'implémenter List en ayant une instance interne avec toutes les méthodes déléguées.

 public class ContactList implements List<Contact>, Serializable {
    private static final long serialVersionUID = -1862666454644475565L;
    private final List<Contact> list;

public ContactList() {
    super();
    this.list = new ArrayList<Contact>();
}

public ContactList(List<Contact> list) {
    super();
    //copy and order list
    List<Contact>aux= new ArrayList(list);
    Collections.sort(aux);

    this.list = aux;
}

public void clear() {
    list.clear();
}

public boolean contains(Object object) {
    return list.contains(object);
}

Après, j'ai implémenté une nouvelle méthode "putOrdered" qui insère à la bonne position si l'élément n'existe pas ou remplace juste au cas où il existe.

public void putOrdered(Contact contact) {
    int index=Collections.binarySearch(this.list,contact);
    if(index<0){
        index= -(index+1);
        list.add(index, contact);
    }else{
        list.set(index, contact);
    }
}

Si vous souhaitez autoriser les éléments répétés, implémentez plutôt addOrdered (ou les deux).

public void addOrdered(Contact contact) {
    int index=Collections.binarySearch(this.list,contact);
    if(index<0){
        index= -(index+1);
    }
    list.add(index, contact);
}

Si vous souhaitez éviter les insertions, vous pouvez également générer une exception d'opération non prise en charge sur les méthodes "add" et "set". 

public boolean add(Contact object) {
    throw new UnsupportedOperationException("Use putOrdered instead");
}

... et aussi Vous devez être prudent avec les méthodes ListIterator car elles pourraient modifier votre liste interne. Dans ce cas, vous pouvez renvoyer une copie de la liste interne ou encore lancer une exception.

public ListIterator<Contact> listIterator() {
    return (new ArrayList<Contact>(list)).listIterator();
}
5
Carlos Verdes

TreeSet ne fonctionnerait pas car ils n'autorisent pas les doublons et ne fournissent pas de méthode pour extraire un élément à une position spécifique. PriorityQueue ne fonctionnerait pas car il ne permettait pas d'extraire des éléments à une position spécifique, ce qui est une exigence de base pour une liste . Je pense que vous devez implémenter votre propre algorithme pour gérer une liste triée en Java avec O(logn) insérer du temps, sauf si vous n'avez pas besoin de doublons . Une solution pourrait peut-être utiliser une TreeMap où la clé est une sous-classe de l'élément remplaçant la méthode equals afin que les doublons soient autorisés. 

4
Giuseppe

Le moyen le plus efficace d’implémenter une liste triée comme vous le souhaitez est d’implémenter un skipliste indexable comme ici: Wikipedia: Indexable skiplist . Cela permettrait d’avoir des insertions/suppressions dans O(log(n)) et d’avoir un accès indexé en même temps. Et cela permettrait également les doublons.

Skiplist est une structure de données assez intéressante et, je dirais, sous-estimée . Malheureusement, il n'y a pas d'implémentation de skiplist indexée dans la bibliothèque de base Java, mais vous pouvez utiliser l'une des implémentations open source ou l'implémenter vous-même. Il existe des implémentations régulières de Skiplist comme ConcurrentSkipListSet et ConcurrentSkipListMap

4
vladich

Utiliser LambdaJ

Vous pouvez essayer de résoudre ces tâches avec LambdaJ si vous utilisez des versions antérieures à Java 8. Vous pouvez le trouver ici: http://code.google.com/p/lambdaj/

Ici vous avez un exemple:

Trier itératif

List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
}); 

Trier avec LambdaJ

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

Bien sûr, avoir ce genre de beauté impacte la performance (en moyenne 2 fois), mais pouvez-vous trouver un code plus lisible?

Tri avec Java 8 en utilisant l'expression lambda

Collections.sort(persons, (p1, p2) -> p1.getAge().compareTo(p2.getAge()));
//or
persons.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));
4
Federico Piazza

Le problème avec PriorityQueue est qu’il est sauvegardé par un tableau simple et que la logique qui permet de classer les éléments dans l’ordre est effectuée par les éléments "queue [2 * n + 1] et file [2 * (n + 1)]". Cela fonctionne très bien si vous tirez simplement de la tête, mais le rend inutile si vous essayez d'appeler le .toArray dessus à un moment donné. 

Je contourne ce problème en utilisant com.google.common.collect.TreeMultimap, mais je fournis un comparateur personnalisé pour les valeurs, encapsulé dans une commande, qui ne renvoie jamais 0. 

ex. pour Double:

private static final Ordering<Double> NoEqualOrder = Ordering.from(new Comparator<Double>() {

    @Override
    public int compare(Double d1, Double d2)
    {
        if (d1 < d2) {
            return -1;
        }
        else {
            return 1;
        }
    }
});

De cette façon, je reçois les valeurs dans l’ordre quand j’appelle .toArray (), et j’ai aussi des doublons.

2
Martin Klosi

Pour Set, vous pouvez utiliser TreeSet. TreeSet ordonne ses éléments sur la base d'un ordre naturel ou de tout ordre de tri transmis à Comparable pour cet objet particulier. Pour la carte, utilisez TreeMap. TreeMap fournit le tri sur les clés. Pour ajouter un objet en tant que clé à la TreeMap, cette classe doit implémenter une interface comparable qui oblige à implémenter la méthode compare to () qui contient la définition de l'ordre de tri. http://techmastertutorial.in/Java-collection-impl.html

1
Avi Tyagi

Vous pouvez utiliser Arraylist et Treemap, car vous avez également indiqué que vous souhaitiez des valeurs répétées. Vous ne pouvez donc pas utiliser TreeSet, bien qu'il soit également trié, mais vous devez définir un comparateur. 

1
user5497526

Ce que vous voulez, c'est un arbre de recherche binaire. Il maintient l'ordre trié tout en offrant un accès logarithmique pour les recherches, les suppressions et les insertions (sauf si vous avez un arbre dégénéré - il est alors linéaire). Il est assez facile à implémenter et vous pouvez même le faire implémenter l’interface List, mais l’accès à l’index devient alors compliqué.

La deuxième approche consiste à avoir une liste de tableaux, puis une implémentation de type bulle. Étant donné que vous insérez ou supprimez un élément à la fois, les temps d'accès pour les insertions et les suppressions sont linéaires. Les recherches sont logarithmiques et constantes (les temps peuvent être différents pour LinkedList). Le seul code dont vous avez besoin est 5, peut-être 6 lignes de type bulle.

1
Jakub Zaverka

Utilisez la méthode sort () pour trier la liste comme ci-dessous:

List list = new ArrayList();

//add elements to the list

Comparator comparator = new SomeComparator();

Collections.sort(list, comparator);

Pour référence, voir le lien: http://tutorials.jenkov.com/Java-collections/sorting.html

0
import Java.util.TreeSet;

public class Ass3 {
    TreeSet<String>str=new TreeSet<String>();
    str.add("dog");
    str.add("doonkey");
    str.add("rat");
    str.add("rabbit");
    str.add("elephant");
    System.out.println(str);    
}
0
Deepica M Y

Tri d'une liste de tableaux en fonction de critères définis par l'utilisateur.

Classe de modèle

 class Student 
 { 
     int rollno; 
     String name, address; 

     public Student(int rollno, String name, String address) 
     { 
         this.rollno = rollno; 
         this.name = name; 
         this.address = address; 
     }   

     public String toString() 
     { 
         return this.rollno + " " + this.name + " " + this.address; 
     } 
 } 

Classe de tri

 class Sortbyroll implements Comparator<Student> 
 {         
     public int compare(Student a, Student b) 
     { 
         return a.rollno - b.rollno; 
     } 
 } 

Classe principale

 class Main 
 { 
     public static void main (String[] args) 
     { 
         ArrayList<Student> ar = new ArrayList<Student>(); 
         ar.add(new Student(111, "bbbb", "london")); 
         ar.add(new Student(131, "aaaa", "nyc")); 
         ar.add(new Student(121, "cccc", "jaipur")); 

         System.out.println("Unsorted"); 
         for (int i=0; i<ar.size(); i++) 
             System.out.println(ar.get(i)); 

         Collections.sort(ar, new Sortbyroll()); 

         System.out.println("\nSorted by rollno"); 
         for (int i=0; i<ar.size(); i++) 
             System.out.println(ar.get(i)); 
     } 
 } 

Sortie

 Unsorted
 111 bbbb london
 131 aaaa nyc
 121 cccc jaipur

 Sorted by rollno
 111 bbbb london
 121 cccc jaipur
 131 aaaa nyc
0
skpaik

Utilisez TreeSet qui donne les éléments dans l’ordre trié. OR utilisez Collection.sort() pour le tri externe avec Comparator().

0
Hari

avec Java 8 Comparator, si nous voulons trier la liste, alors voici les 10 villes les plus peuplées du monde et nous voulons trier par nom, comme indiqué par Time. Osaka, Japon. ... Mexico, Mexique. ... Pékin, Chine. ... São Paulo, Brésil. ... Mumbai, Inde. ... Shanghai, Chine. ... Delhi, Inde. ... Tokyo, Japon.

 import Java.util.Arrays;
 import Java.util.Comparator;
 import Java.util.List;

public class SortCityList {

    /*
     * Here are the 10 most populated cities in the world and we want to sort it by
     * name, as reported by Time. Osaka, Japan. ... Mexico City, Mexico. ...
     * Beijing, China. ... São Paulo, Brazil. ... Mumbai, India. ... Shanghai,
     * China. ... Delhi, India. ... Tokyo, Japan.
     */
    public static void main(String[] args) {
        List<String> cities = Arrays.asList("Osaka", "Mexico City", "São Paulo", "Mumbai", "Shanghai", "Delhi",
                "Tokyo");
        System.out.println("Before Sorting List is:-");
        System.out.println(cities);
        System.out.println("--------------------------------");

        System.out.println("After Use of List sort(String.CASE_INSENSITIVE_ORDER) & Sorting List is:-");
        cities.sort(String.CASE_INSENSITIVE_ORDER);
        System.out.println(cities);
        System.out.println("--------------------------------");
        System.out.println("After Use of List sort(Comparator.naturalOrder()) & Sorting List is:-");
        cities.sort(Comparator.naturalOrder());
        System.out.println(cities);

    }

}
0
vipul gulhane