abuka123
abuka123

Reputation: 451

How to sort inner list which is a value of a map in Java?

It's more of a Java question (although I'm using Firebase). I'm trying to understand what's best way to sort a list. I'm trying to create the following map:

Map<Character,List<QueryDocumentSnapshot>> docs;

In order to build this map, I iterate over the documents in my collection, get the first letter of each one and insert the document into the list where the key is the letter. The code:

for (QueryDocumentSnapshot current_document : value) {
    char letter = getFirstLetter(current_document.getString("type"));
    List<QueryDocumentSnapshot> list = docs.get(letter);
    if (list == null) {
        list = new ArrayList<>();
        list.add(current_document);
        docs.put(letter, list);
    } else {
        list.add(current_document);
    }
}

In order to make the docs map sorted, I use TreeMap:

docs = new TreeMap<>();

But how can I make the list of documents be sorted by the field type (String)?

EDIT Sorry for not mentioning it, value is of type QuerySnapshot (firebase). Also I'm using Android's Java API 16 (which means I don't have java 8).

Upvotes: 1

Views: 132

Answers (4)

WJS
WJS

Reputation: 40024

Create a Comparator and apply it to each List in the map. Since you are not changing the actual List reference you can sort in place. Note that I presumed that "type" returned a String. This may need to be changed.

Also, TreeMap has nothing to do with sorting the values. That would only sort the keys to the map.

Comparator<QueryDocumentSnapshot> comp = new CompareByType();
for (List<QueryDocumentSnapshot> list : docs.values()) {
        Collections.sort(list,comp);
}

Here is the Comparator class

class CompareByType implements Comparator<QueryDocumentSnapshot> {
     public int compare(QueryDocumentSnapshot a, QueryDocumentSnapshot b) {
         String a = QueryDocumentSnapshot.getString("type");
         String b = QueryDocumentSnapshot.getString("type");
         return a.compareTo(b);
     }
}

And here is a slight mod to your map creation. You don't need the else clause because list will always have a valid list when it is time to add the document.

for (QueryDocumentSnapshot current_document : value) {
    char letter = getFirstLetter(current_document.getString("type"));
    List<QueryDocumentSnapshot> list = docs.get(letter);
    if (list == null) {
        list = new ArrayList<>();
        docs.put(letter, list);
    }
    // At this point you will always have a list to access.
    // you can add the current document here
    list.add(current_document);
}

Upvotes: 1

Mateusz Korwel
Mateusz Korwel

Reputation: 1148

If you can use TreeSet instead of ArrayList, it can look like this. More you can find here: https://stackoverflow.com/a/8725470/4228138

Map<Character,Set<QueryDocumentSnapshot>> docs;

...

Comparator<QueryDocumentSnapshot> comparator = new Comparator<QueryDocumentSnapshot>() {
    @Override
    public int compare(QueryDocumentSnapshot o1, QueryDocumentSnapshot o2) {
        return o1.getString("type").compareTo(o2.getString("type"));
    }
};

for (QueryDocumentSnapshot currentDocument : value) {
    char letter = getFirstLetter(currentDocument.getString("type"));
    Set<QueryDocumentSnapshot> documents = docs.get(letter);
    if (documents == null) {
        documents = new TreeSet<>(comparator);
        documents.add(currentDocument);
        docs.put(letter, documents);
    } else {
        documents.add(currentDocument);
    }
}

Upvotes: 1

The simplest way is to sort all QueryDocumentSnapshots before they are classified by first key. If the collection is sorted before, then each particular list will be sorted as well.

Hence, add

Collections.sort(value, Comparator.comparing(q -> q.getString("type")));

before the code you posted (I assume value a List, for general collection change it to stream sorting).

Upvotes: 0

Tobse
Tobse

Reputation: 1416

You can

  1. Let the QueryDocumentSnapshot implement Compareableable<QueryDocumentSnapshot>. So it will use your implementation to sort the entries.
  2. Provide a Comparator to the TreeMap constructor: TreeMap(Comparator<? super K> comparator)
    The comparator can look like this:
(o1, o2) -> o1.getString("type").compareTo(o2.getString("type"))

Upvotes: -1

Related Questions