2

E.g

Map<Home, List<People>> ihm = new TreeMap<Home, List<People>>();

and data goes like:

ihm.put(new Home(...), Arrays.asList(new People(...),
new People(...),
new People(...));
ihm.put(new Home(...), Arrays.asList(new People(...),
new People(...));

I want to sort it by the no. of people living in the house.

How can i achieve this using comparator or comparable?

  • 3
    Does this answer your question? [Sort a Map by values](https://stackoverflow.com/questions/109383/sort-a-mapkey-value-by-values) – JonK Jan 27 '20 at 12:12
  • 1
    From Javadocs for `HashMap` "This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time." - if you want to order it you can't use `HashMap` – Amongalen Jan 27 '20 at 12:19
  • `Hashmap` is an unordered collection, if you want a sorted map, then use `SortedMap` and implement `Comparable` for your value type in the map – Thomas Cook Jan 27 '20 at 12:19
  • I have changed to TreeMap/SortedMap but counting the values of the list on the comparator/ble still seems complex... – GodFather XVII Jan 27 '20 at 12:26
  • 1
    Why do you even need a map? You could just have a House and it would have People associated to it. – matt Jan 27 '20 at 12:47

4 Answers4

1

It should not be done as property of the map's key Home, as you might want to add/remove people to a Home, corrupting the map.

Instead sort it dynamically:

ihm.entrySet().stream()
   .sort(Comparator.comparingInt(es -> -es.getValue().size())) // Decreasing; neg. sizes.
   .forEach(es -> System.out.printf("...%n", ...));
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • can you really implement comparator by just running the size of the list? I thought comparator used positive or negative returns to determine ordering... – Adam Jan 27 '20 at 12:38
  • @Adam right, I took a shortcut too much. There is style `(o1, o2) -> ...` and [`Comparator.comparing o -> property of o)`](https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#comparingInt-java.util.function.ToIntFunction-). – Joop Eggen Jan 27 '20 at 12:41
0

Can you try below code ?

public class HomeMain {

public static List<Map.Entry<String, Integer>> sortByValue(Map<String, Integer> wordMap){

    Set<Map.Entry<String, Integer>> set = wordMap.entrySet();
    List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(set);
    Collections.sort( list, new Comparator<Map.Entry<String, Integer>>()
    {
        public int compare( Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 )
        {
            return (o2.getValue()).compareTo( o1.getValue() );
        }
    } );
    return list;
}

public static void main(String[] args) {
    Map<Home, List<People>> ihm = new HashMap<Home, List<People>>();
    ihm.put(new Home("Home"), Arrays.asList(new People(4),
            new People(5),
            new People(6)));

    ihm.put(new Home("Home1"), Arrays.asList(new People(2),
            new People(1),
            new People(9)));

    ihm.put(new Home("Home2"), Arrays.asList(new People(3),
            new People(6),
            new People(2)));

    ihm.put(new Home("Home3"), Arrays.asList(new People(1),
            new People(7),
            new People(6)));
    Map<String, Integer> newMap = new HashMap<String, Integer>();

    Iterator<Map.Entry<Home, List<People>>> itr = ihm.entrySet().iterator();

    while (itr.hasNext()) {
        Map.Entry<Home, List<People>> entry = itr.next();
        List<People> p = entry.getValue();
        int totalPeople = 0;
        for (People people : p) {
            totalPeople += people.getNumberOfPeople();
        }
        newMap.put(entry.getKey().getName(), totalPeople);
    }


    Iterator<Map.Entry<String, Integer>> it1 = newMap.entrySet().iterator();
    System.out.println("UnSorted map:");
    while (it1.hasNext()) {
        Map.Entry<String, Integer> entry = it1.next();
        System.out.println("Key = " + entry.getKey() +
                ", Value = " + entry.getValue());
    }
    List<Map.Entry<String, Integer>> sortedList = sortByValue(newMap);
    System.out.println("Sorted map:");
    for (Map.Entry<String, Integer> entry : sortedList) {
        System.out.println(entry.getKey() + " ====" + entry.getValue());
    }
}} 

public class Home {
  String name;
public Home(String homename){
    this.name=homename;
}}

public class People {
 public int getNumberOfPeople() {
    return numberOfPeople;
}
int numberOfPeople;
    public People(int numOfPeople){
        this.numberOfPeople=numOfPeople;
    }}
  • Output:UnSorted map: Key = Java.Home@6d6f6e28, Value = 15 Key = Java.Home@45ee12a7, Value = 11 Key = Java.Home@135fbaa4, Value = 12 Key = Java.Home@330bedb4, Value = 14 Sorted map: Java.Home@6d6f6e28 ====15 Java.Home@330bedb4 ====14 Java.Home@135fbaa4 ====12 Java.Home@45ee12a7 ====11 you can print home name instead of home object. – Avvappa Hegadyal Jan 27 '20 at 13:14
0

An Example of how this could be done.

public static void main(String[] args){
    Map<Home, List<People>> ihm = new HashMap<Home, List<People>>();
    ihm.put(new Home(3), Arrays.asList(new People(1), new People(2),new People(3)));
    ihm.put(new Home(2), Arrays.asList(new People(1), new People(4)));
    ihm.put(new Home(4), Arrays.asList(new People(5), new People(4),new People(2),new People(3)));
    ihm.put(new Home(1), Collections.singletonList(new People(5)));

    System.out.println("\nUnSorted Map :");
    for (Map.Entry<Home, List<People>> entry:ihm.entrySet()) {
        System.out.println(entry.getKey());
    }

    Map<Home,List<People>> result = sortByValueCount(ihm);
    System.out.println("\nSorted Map :");
    for (Map.Entry<Home, List<People>> entry:result.entrySet()) {
        System.out.println(entry.getKey());
    }


}

public static Map<Home, List<People>> sortByValueCount(final Map<Home,List<People>> homeListMap) {
    return homeListMap.entrySet()
            .stream()
            .sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}

static class Home{
    int size;

    public Home(int size) {
        this.size = size;
    }



    @Override
    public String toString() {
        return "Home{" +
                "size=" + size +
                '}';
    }
}

static class People{
    int peopleNumber;

    public People(int peopleNumber) {
        this.peopleNumber = peopleNumber;
    }
}

I have set the Home size to be equivalent to the size of elements within it for better understanding.

Mohit Hurkat
  • 406
  • 2
  • 8
0
static <K,V extends Collection> Map<K,V> sortMap(Map<K,V> map){
    return map.entrySet().stream()
            .sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
DD.
  • 21,498
  • 52
  • 157
  • 246