divadneb nahtan
divadneb nahtan

Reputation: 23

Java sort HashMap by highest value, then lowest key

Lets say I have a HashMap<Recipe, Integer> where Recipe is a class with 2 integer parameters. We can call them lemons and sugar. I want to get the key (which is a Recipe) in the HashMap that has the highest corresponding value. As a secondary sorting method, in case it contains multiple Recipes with the same value. It should return the Recipe with the sum of sugar and lemons that is the lowest.

eg.

HashMap<Recipe, Integer> recipes = new HashMap<>();
recipes.put(new Recipe(5, 3), 10); // 5 is lemons, 3 is sugar
recipes.put(new Recipe(8, 8), 15);
recipes.put(new Recipe(1, 2), 15);
Recipe bestRecipe - recipes.getBestRecipe();
// bestRecipe.getLemons() would be 1
// bestRecipe.getSugar() would be 2
// because it has the highest value (15) with the lowest sum of sugar and lemons (1+2=3)

How would I go about doing that? I know I can get the largest value with Collections.max(recipes.values()) but how would I find the largest value with the lowest sum of lemons and sugar?

Upvotes: 2

Views: 1218

Answers (2)

Eklavya
Eklavya

Reputation: 18450

You can stream the map and write your comparator for sorting then get the first element

recipes.entrySet().stream()
        .sorted((e1, e2) -> {
             int v = e2.getValue().compareTo(e1.getValue());
             if(v!=0) return v;
             Integer a = (e1.getKey().getLemons() + e1.getKey().getSuger());
             Integer b = (e2.getKey().getLemons() + e2.getKey().getSuger());
             return Integer.compare(a,b);
         })
        .map(Map.Entry::getKey)
        .findFirst().get();

Upvotes: 1

Thiyagu
Thiyagu

Reputation: 17900

You can create a stream of the map entries and use the max method to get the max element sorted by a comparator.

The comparator logic is as follows:

  1. It sorts by the map's value.
  2. In case of a tie, it reverse sorts by the sum of lemons and sugars of a recipe. This means that the values would be sorted from greatest to lowest.

Optional<Recipe> bestRecipe = recipes.entrySet()
                .stream()
                .max(Comparator.comparingInt((Map.Entry<Recipe, Integer> e) -> e.getValue())
                        .thenComparing(e -> e.getKey().getSugar() + e.getKey().getLemons(), 
                            Comparator.reverseOrder()))
                .map(Map.Entry::getKey);

Upvotes: 2

Related Questions