0

So I have a HashMap looking like this :

HashMap<Movie, Float> movies;

It contains some movies with their global ratings as floats, and I want to sort the movies from the best to the worst.

I had a look in Collections.sort() but have no idea if I can do something with it...

Rob
  • 15,732
  • 22
  • 69
  • 107

6 Answers6

3

It is not possible to sort a HashMap. If you need a sorted map take a look at TreeMap.

What about adding the rating value to the Movie class and let it implement Comparable?

public class Movie implements Comparable<Movie> {

    private Float rating;

    public Movie(Float rating) {
        this.rating = rating;
    }

    public Float getRating() {
        return rating;
    }

    public int compareTo(Movie param) {
        return param.getRating().compareTo(rating);
    }

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

Then you can use your Movie class like this:

public static void main(String[] args) {

    Set<Movie> movies = new HashSet<Movie>();
    movies.add(new Movie(0.6f));
    movies.add(new Movie(0.5f));
    movies.add(new Movie(0.7f));
    movies.add(new Movie(0.2f));

    // Movie.class has to implement Comparable
    System.out.println("First option:");
    List<Movie> list = new ArrayList<Movie>(movies);
    Collections.sort(list);
    printMovies(list);

    // Works without implementing Comparable in Movie.class
    System.out.println("\nSecond option:");
    List<Movie> secondList = new ArrayList<Movie>(movies);
    Collections.sort(secondList, new Comparator<Movie>() {
        public int compare(Movie movie1, Movie movie2) {
            return movie2.getRating().compareTo(movie1.getRating());
        }
    });
    printMovies(secondList);

}

private static void printMovies(List<Movie> list) {
    for (Movie movie : list) {
        System.out.println(movie);
    }
}

Output:

First option:
0.7
0.6
0.5
0.2

Second option:
0.7
0.6
0.5
0.2

If you always want to sort the movies in the same way (from best to worse), I would choose the first option. If you always need different sort algorithms I would choose the second option, but even if your Movie class implements Comparable you can always provide a different Comparator as shown in the example.

Matthias Herlitzius
  • 3,365
  • 2
  • 20
  • 20
  • 1
    While this is an ok solution, I think it makes the code easier to read if you use Comperator rather than Compareable in situations like this. When I read Collections.sort(list) I will often assume its sorted on title or similar, not on rating, but if I instead read Collections.sort(list, new Movie.RatingComperator()) I can see right away that it will be sorted by rating and not something else. – Vegard May 04 '13 at 18:42
2

HashMap is not the datastructure for what you want to achieve. you can read more about HashMap here for exmaple: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/HashMap.html

what I suggest for you is to include your rating within your Movie object and make a Comperator that can compare your Movie objects based on rating. place the Movie's in a ArrayList, then you can sort it with the comperator and Collections.sort

Honza Brabec
  • 37,388
  • 4
  • 22
  • 30
Vegard
  • 1,802
  • 2
  • 21
  • 34
2

use TreeMap. From this so answer

public class Testing {

    public static void main(String[] args) {

        HashMap<String,Double> map = new HashMap<String,Double>();
        ValueComparator bvc =  new ValueComparator(map);
        TreeMap<String,Double> sorted_map = new TreeMap<String,Double>(bvc);

        map.put("A",99.5);
        map.put("B",67.4);
        map.put("C",67.4);
        map.put("D",67.3);

        System.out.println("unsorted map: "+map);

        sorted_map.putAll(map);

        System.out.println("results: "+sorted_map);
    }
}

class ValueComparator implements Comparator<String> {

    Map<String, Double> base;
    public ValueComparator(Map<String, Double> base) {
        this.base = base;
    }

    // Note: this comparator imposes orderings that are inconsistent with equals.    
    public int compare(String a, String b) {
        if (base.get(a) >= base.get(b)) {
            return -1;
        } else {
            return 1;
        } // returning 0 would merge keys
    }
}
Community
  • 1
  • 1
stinepike
  • 54,068
  • 14
  • 92
  • 112
2

You can use the Guava library to do this - there is already an excellent answer on here explaining how to do this.

Community
  • 1
  • 1
seedhead
  • 3,655
  • 4
  • 32
  • 38
2

You could just use a TreeMap from the start. It is a sorted map, you just have to define a Comparator (in this case, use your floats)

If you want to stick to HashMaps, yes you can use Collections.sort. But again, you still have to learn how to use a Comparator.

renz
  • 1,072
  • 3
  • 11
  • 21
1

HashMaps are unsorted by default. If you need ordering either use a TreeMap or simply sort into a List<Movie>

List<Movie> movies = new ArrayList<Movie>(); 
Collections.sort(movies, new Comparator<Movie>() {

        public int compare(Movie m1, Movie m2) {
            return m1.getRating() - m2.getRating();
        }
});
flavian
  • 28,161
  • 11
  • 65
  • 105