Reputation: 451
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
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
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
Reputation: 12000
The simplest way is to sort all QueryDocumentSnapshot
s 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
Reputation: 1416
You can
QueryDocumentSnapshot
implement Compareableable<QueryDocumentSnapshot>
. So it will use your implementation to sort the entries.Comparator
to the TreeMap constructor: TreeMap(Comparator<? super K> comparator)
(o1, o2) -> o1.getString("type").compareTo(o2.getString("type"))
Upvotes: -1