web-dev-qa-db-fra.com

Tri d'une valeur double d'un objet dans une liste de tableaux

J'essaie de trier mon chromosome de classe personnalisé en fonction de la valeur de leur attribut score, qui est un double. Ces chromosomes sont stockés dans une ArrayList. Je sais que je dois utiliser un comparateur, mais j’ai lu tellement d’opinions divergentes en ligne au cours de la dernière heure que je suis complètement confus.

Ci-joint mon code, si quelqu'un pouvait me diriger dans la bonne direction, je serais très apprécié.

public class Chromosome
{

    public Gene[] genes;
    public double score;

    public Chromosome(int l)
    {
        genes = new Gene[l]; 
    }

    public int getLength()
    {
        return genes.length;
    }

    public void printChromo()
    {
        for(int i=0;i<this.genes.length;i++)
        {
            System.out.println(""+this.genes[i].teacher+","+
                this.genes[i].lecture+","+
                this.genes[i].room+","+
                this.genes[i].time+"");
        }   
    }

    public void setScore(double score)
    {
        this.score=score;
    }

    public double getScore()
    {
        return this.score;
    }
}

Je ne sais pas si cela fait une différence, mais le score ne peut être qu'un double entre 0.0 et 1.0.

18
Melo1991

Pour utiliser une Comparator :

Collections.sort(myList, new Comparator<Chromosome>() {
    @Override
    public int compare(Chromosome c1, Chromosome c2) {
        return Double.compare(c1.getScore(), c2.getScore());
    }
});

Si vous envisagez de trier de nombreux Lists de cette manière, je vous suggèrerais que Chromosome implémente l'interface Comparable (dans ce cas, vous pouvez simplement appeler Collections.sort(myList), sans qu'il soit nécessaire de spécifier un Comparator explicite).

61
arshajii

Je mettrais en œuvre l'interface Comparable :

public class Chromosome implements Comparable<Chromosome>{

    private double score;

    public Chromosome(double score){
        this.score = score;
    }
    @Override
    public int compareTo(Chromosome o) {
        return new Double(score).compareTo( o.score);
    }
    @Override
    public String toString() {
        return String.valueOf(score);
    }
}

Notez que je me suis déplacé score dans la classe ..

Maintenant, vous pouvez utiliser n'importe quel Collection qui est trié (comme un TreeSet )

Si vous insistez pour utiliser l'Arraylist, vous pouvez utiliser:

ArrayList<Chromosome> out = new ArrayList<Chromosome>();
out.add(new Chromosome(20));
out.add(new Chromosome(15));
System.out.println(out);
Collections.sort(out);
System.out.println(out);

Résultat:

[0.2, 0.15]
[0.15, 0.2]
3
Frank

Pourquoi ne pas utiliser un PriorityQueue avec un Comparateur comme ceci:

// your code
PriorityQueue<Chromosome> entries = new PriorityQueue<Chromosome>(1, new Comparator<Chromosome> () {
    @Override
    public int compare(Chromosome arg0, Chromosome arg1) {
        return (Double)(arg1.getScore()).compareTo((Double)arg0.getScore());
    }
});
entries.addAll(arrayListOfChromosomes);
// your code

La file d'attente prioritaire conservera alors votre structure de données dans un ordre trié.

3
hd1

Depuis Java 8, vous pouvez trier la liste des éléments Double très simple.

list.sort(Comparator.comparingDouble(Chromosome::getScore));

ou

Collections.sort(list, omparator.comparingDouble(Chromosome::getScore));

Si vous voulez obtenir une liste triée mais que vous ne voulez pas changer votre liste de début, vous pouvez le faire comme suit:

List<Chromosome> sortedList = list.stream()
     .sorted(Comparator.comparingDouble(A::getScore))
     .collect(Collectors.toList()); 
0
Beno Arakelyan

Avec Java SE8 , vous pouvez utiliser une expression lambda comme ceci:

    list.sort((o1, o2) -> Double.compare(o2.doubleField, o1.doubleField));
0
Vania Shows