MayNotBe
MayNotBe

Reputation: 2140

Sort a map of objects with multiple fields using a comparator

I have an Author object with name, age, and index fields. The Authors are stored in a HashMap (the key is the index).

I would like to be able to sort by name and age.

This begins a method I want to put in my Author class but clearly I am not understanding this:

public static LinkedHashMap<String, Author> sortName(Map<String, Author> unSortedMap){

    Collection<Author> list = unSortedMap.values();

    Collections.sort(list, new Comparator<Author>() {
        public int compare(Author a, Author b) {
            return a.name.compareTo(b.name);
        }
});
}

It won't compile because of this: (from Eclipse)

The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (Collection<Author>, new Comparator<Author>(){})

  1. The Collections class fields are EMPTY_LIST, EMPTY_MAP, and EMPTY_SET. Why can't the sort method pass a Map with a Comparator?

  2. I thought <T> was generic so I could pass any kind of object I wanted.

  3. Am I correct that if this worked, Collections.sort() would sort list by the Author's name? So I would end up with a LinkedList<Author> that I could turn into a LinkedHashMap<String, Author> and send on it's way?

Thank you in advance. Clearly I'm student. I've also searched for HOURS for information that could guide me toward a solution. I've read every question re: "Collections sort multiple values comparator". Nothing is working.

Upvotes: 0

Views: 4344

Answers (1)

Bohemian
Bohemian

Reputation: 424963

I won't compile because Collections.sort() only sorts Lists, not Collections.

If you want to sort the values, it's east to turn a Collection into a List by passing the collection into the constructor of the List:

List<Author> list = new ArrayList<Author>(unSortedMap.values());

Collections.sort(list, new Comparator<Author>() {
    public int compare(Author a, Author b) {
        return a.name.compareTo(b.name);
    }
});

But that won't get the job done. Instead, you need to sort the Map's Entry objects, then put them into the map:

public static LinkedHashMap<String, Author> sortName(Map<String, Author> unSortedMap) {
    List<Map.Entry<String, Author>> list = new ArrayList<Map.Entry<String, Author>>(unSortedMap.entrySet());

    Collections.sort(list, new Comparator<Map.Entry<String, Author>>() {
        public int compare(Map.Entry<String, Author> a, Map.Entry<String, Author> b) {
            return a.getValue().name.compareTo(b.getValue().name);
        }
    });

    LinkedHashMap<String, Author> result = new LinkedHashMap<String, Author>();
    for (Entry<String, Author> entry : list) {
        result.put(entry.getKey(), entry.getValue());
    }

    return result;
}

Upvotes: 3

Related Questions