124697
124697

Reputation: 21901

How can I sort list of object based on one of the object's variables

I need to sort an ArrayList of films best rated to worse (5 best - 1 worst). I am using Collections.sort() but the list comes out the same. what am i doing wrong

films.add(new Film().setRating(1));
films.add(new Film().setRating(2.5));
films.add(new Film().setRating(3.5));
films.add(new Film().setRating(4));
films.add(new Film().setRating(5));
films.add(new Film().setRating(1));
films.add(new Film().setRating(2));
films.add(new Film().setRating(3));
films.add(new Film().setRating(4));
Collections.sort(films, new Comparator<Film>() {
    @Override
    public int compare(Film o1, Film o2) {
        final double film1 = o1.getRating();
        final double film2 = o2.getRating();
        return film1 > film2? 1
                : film1 < film2? -1 : 0;
    }
});

Upvotes: 5

Views: 13060

Answers (4)

Roshan Halwai
Roshan Halwai

Reputation: 552

There are two ways of solving this problem

  1. Implementing compare method of comparator interface in second parameter of Collections.sort method.

  2. Ensuring your class implements Comparable interface and then implementing compareTo method.

Here is the code for both solutions.

public class ComparableTest implements Comparable < ComparableTest > {

  String name;
  int marks;

  @Override
  public int compareTo(ComparableTest o) {
    if (this.marks > o.marks)
      return 1;
    return -1;
  }

  public ComparableTest(String name, int marks) {
    this.name = name;
    this.marks = marks;
  }

  public String getName() {
    return name;
  }

  public int getMarks() {
    return marks;
  }

}

package program;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class TempList {

  public static void main(String[] args) {

    /*************************************************/
    /****************Assigning Values*****************/
    /*************************************************/
    String[] names = {
      "A",
      "B",
      "C",
      "D",
      "E"
    };
    List < ComparableTest > objects = new LinkedList < > ();

    /*************************************************/
    /****************Printing Values******************/
    /*************************************************/

    for (String name: names) {
      objects.add(new ComparableTest(name, new Random().nextInt(100)));
    }

    System.out.println("Before Sorting");

    for (ComparableTest object: objects) {
      System.out.println(object.name + " " + object.marks);
    }

    /*************************************************/
    /*************Sorting based on marks**************/
    /*************************************************/

    Collections.sort(objects);
    System.out.println("\nSorting based on Marks");

    for (ComparableTest object: objects) {
      System.out.println(object.name + " " + object.marks);
    }

    /*************************************************/
    /*************Sorting based on names**************/
    /*************************************************/

    System.out.println("\nSorting based on Names");

    Collections.sort(objects, new Comparator < ComparableTest > () {

      @Override
      public int compare(ComparableTest o1, ComparableTest o2) {
        if (o1.name.compareTo(o2.name) < 1) {
          return 1;
        }
        return -1;
      }

    });

    for (ComparableTest object: objects) {
      System.out.println(object.name + " " + object.marks);
    }
  }

}

Upvotes: 0

Tobb
Tobb

Reputation: 12225

Your code works just fine on my computer, the following:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class SortFilms {
    public static void main(final String ... args) {
        new SortFilms().sort();
    }

    public void sort() {
        final List<Film> films = new ArrayList<Film>();
        films.add(new Film(1));
        films.add(new Film(2.5));
        films.add(new Film(3.5));
        films.add(new Film(4));
        films.add(new Film(5));
        films.add(new Film(1));
        films.add(new Film(2));
        films.add(new Film(3));
        films.add(new Film(4));
        Collections.sort(films, new Comparator<Film>() {
            @Override
            public int compare(Film o1, Film o2) {
                final double film1 = o1.getRating();
                final double film2 = o2.getRating();
                return film1 > film2? 1
                        : film1 < film2? -1 : 0;
            }
        });

        System.out.println(films);
    }

    private class Film {
        private final double rating;

        public Film(double rating) {
            this.rating = rating;
        }

        public String toString() {
            return "" + rating;
        }

        public Double getRating() {
            return rating;
        }
    }
}

Procudes:

[1.0, 1.0, 2.0, 2.5, 3.0, 3.5, 4.0, 4.0, 5.0]

Upvotes: 1

Boris the Spider
Boris the Spider

Reputation: 61198

Using the Double.compare method works fine:

public static void main(String[] args) throws IOException, ClassNotFoundException {
    final List<Film> films = new ArrayList<>();
    films.add(new Film().setRating(1));
    films.add(new Film().setRating(2.5));
    films.add(new Film().setRating(3.5));
    films.add(new Film().setRating(4));
    films.add(new Film().setRating(5));
    films.add(new Film().setRating(1));
    films.add(new Film().setRating(2));
    films.add(new Film().setRating(3));
    films.add(new Film().setRating(4));
    System.out.println(films);
    Collections.sort(films, new Comparator<Film>() {
        @Override
        public int compare(Film o1, Film o2) {
            return Double.compare(o1.getRating(), o2.getRating());
        }
    });
    System.out.println(films);
}

Output:

[1.0, 2.5, 3.5, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0]
[1.0, 1.0, 2.0, 2.5, 3.0, 3.5, 4.0, 4.0, 5.0]

The Film I used:

private static final class Film {

    double rating;

    public double getRating() {
        return rating;
    }

    public Film setRating(double rating) {
        this.rating = rating;
        return this;
    }

    @Override
    public String toString() {
        return Double.toString(rating);
    }
}

I would suggest using Double.compare rather than your version, or even o1.getRating - o2.getRating.

It's either that or your Film implementation is wrong - maybe the setter in your example doesn't set anything?

Upvotes: 5

BlackJoker
BlackJoker

Reputation: 3191

Use the folowing method in Double instead:

public static int compare(double d1, double d2){}

or like this:

class Film implements Comparable<Film>{
    double rating;
    @Override
    public int compareTo(Film o) {
        return Double.compare(rating, o.rating);
    }
}

Upvotes: 2

Related Questions