[英]How can I sort a Map<String, List<CustomObject>>?
我對這個問題做了很多研究,但我還沒有找到一種方法來對自定義 object 列表( Map<String, List<CustomObj>>
)的 map 進行排序,基於CustomObj
屬性(如SORT_BY_NAME
, SORT_BY_DATE
ETC)。
我的問題的一個激勵例子是:
Person
(屬性為Name
, DateOfBith
等...);Person
Map
的 Map List
為: Map<String, List<Person>>
。 map 密鑰是用於其他目的的String
;Person
object 的屬性(名稱、日期等)之間的比較,按升序對 map 進行排序。 為簡單起見,我報告了真實代碼,但適用於Person
object 的簡化案例,因為它已經代表了實體的概念。
Person.java
-> 自定義 object
public class Person {
private String name;
private Date dateOfBirth;
...
// Empty and Full attrs Constructors
...
// Getter and Setter
...
// Comparator by name
public static Comparator<Person> COMPARE_BY_NAME = Comparator.comparing(one -> one.name);
// Comparator by date
public static Comparator<Person> COMPARE_BY_DATE = Comparator.comparing(one -> one.dateOfBirth);
}
分揀機Sorter.java
-> 分揀機 object
public class Sorter {
// List Comparator of Person by Date
public static final Comparator<? super List<Person>> COMPARATOR_BY_DATE = (Comparator<List<Person>>) (p1, p2) -> {
for (Persontab person1: p1) {
for (Person person2: p2) {
return Person.COMPARE_BY_DATE.compare(person1, person2);
}
}
return 0;
};
// List Comparator of Person by Name
public static final Comparator<? super List<Person>> COMPARATOR_BY_NAME = (Comparator<List<Person>>) (p1, p2) -> {
for (Persontab person1: p1) {
for (Person person2: p2) {
return Person.COMPARE_BY_NAME.compare(person1, person2);
}
}
return 0;
};
// Sorting method
public Map<String, List<Person>> sort(Map<String, List<Person>> map, Comparator<? super List<Person>> comparator) {
return map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(comparator))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new));
}
}
Main.java
-> 起始碼
public class MainApp {
public static void main(String[] args) {
Map<String, List<Person>> exampleMap = new HashMap<>();
List<Person> personList = new ArrayList<>();
personList.add(new Person("name1", new Date("2022-01-01")));
personList.add(new Person("name12", new Date("2022-01-05")));
personList.add(new Person("name13", new Date("2022-01-03")));
map.put("2022-01", personList);
personList.clear();
personList.add(new Person("name14", new Date("2021-02-01")));
personList.add(new Person("name3", new Date("2021-02-05")));
personList.add(new Person("name4", new Date("2021-02-03")));
map.put("2021-02", personList);
Sorter sorter = new Sorter();
// Example of sorting by date
map = sorter.sort(exampleMap, Sorter.COMPARATOR_BY_DATE);
// In this case the sorting works correctly, or rather it sorts the items by date as I expect
// Example of sorting by name
map = sorter.sort(exampleMap, Sorter.COMPARATOR_BY_NAME);
// In this case, I don't think sorting works correctly. Sort each list of elements for each key in ascending order. But it doesn't sort the map elements.
/* I expect to have the following map when sort by date:
"2021-02": [
Person("name14", new Date("2021-02-01")),
Person("name4", new Date("2021-02-03")),
Person("name3", new Date("2021-02-05"))
],
"2022-01": [
Person("name14", new Date("2021-02-01")),
Person("name13", new Date("2022-01-03")),
Person("name12", new Date("2022-01-05"))
]
}
}
首先,讓我們重申一下: HashMap
是無序的,所以你需要別的東西。 您的Sorter.sort()
方法實際上將值收集到LinkedHashMap
中,它提供了基於插入順序的迭代順序,並且適用於您的用例。 只是要清楚(也為了其他人):這不會對 map 本身進行排序,而是創建一個新的LinkedHashMap
。
現在到你的比較器:如果你想比較 2 個列表,你可能想比較相同索引的元素。 因此,您的比較器需要是這樣的:
Comparator<List<Person>> = (l1, l2) -> {
Iterator<Person> itr1 = l1.iterator();
Iterator<Person> itr2 = l2.iterator();
while( itr1.hasNext() && itr2.hasNext() ) {
Person p1 = itr1.next();
Person p2 = itr1.next();
int result = Person.COMPARE_BY_DATE.compare(p1, p2);
if( result != 0 ) {
return result;
}
}
return 0;
};
但是,列表也可能具有不同的長度,因此您可能也想處理它:
Comparator<List<Person>> = (l1, l2) -> {
//iterators and loop here
//after the loop it seems all elements at equal indices are equal too
//now compare the sizes
return Integer.compare(l1.size(), l2.size());
}
通過更改上面代碼中使用的Map
的類型,正如@Thomas 所建議的那樣,在TreeMap<>
中,我找到了問題的解決方案如下:
Person
object 列表合並到一個列表中。 然后按所選標准對其進行排序,例如Person.COMPARE_BY_NAME
;Person
object 的月 + 年的串聯。 算法在評論底部報告;Sorter.COMPARATOR_BY_NAME
;Di seguito il codice è come segue:
在創建 Map 之前將所有List<Person>
合並到一個 -> main 或某處
...
//
List<Person> newPersonList = new ArrayList<>();
newPersonList.addAll(oldPersonList1);
newPersonList.addAll(oldPersonList2);
...
創建 Map 之前的主要或某處
...
groupList(Person.COMPARE_BY_NAME, Sorter.COMPARATOR_BY_NAME);
...
GroupPerson -> 將合並的List<Person>
分組到TreeMap<String, List<Person>>
的方法
public Map<String, List<Person>> groupList(final Comparator<? super Person> itemComparator, final Comparator<? super List<Person>> listComparator)
// Sort Person list by comparator before create TreeSet
newPersonList.sort(itemComparator);
Map<String, List<Person>> personMapGrouped = new TreeMap<>();
// Here, create a Map of list
for (Person person: newPersonList) {
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM", Locale.getDefault());
final String groupKey = dateFormat.format(person.getDateOfBirth());
if (personMapGrouped.containsKey(groupKey)) {
// The key is already in the TreeMap; add the Person object against the existing key.
final List<Person> personListGrouped = personMapGrouped.get(groupKey);
if (personListGrouped!= null) {
personListGrouped.add(person);
}
} else {
// The key is not there in the TreeMap; create a new key-value pair
final List<Person> personListGrouped = new ArrayList<>();
personListGrouped.add(person);
personMapGrouped.put(groupKey, personListGrouped);
}
}
// Here sort the Map by params passed
final TabPersonSorter sorter = new TabPersonSorter();
personMapGrouped = sorter.sort(personMapGrouped, listComparator);
}
在這種情況下,使用上面 main 中創建的列表,獲得的結果是:
"List<Person> mergedList": [
Person("name1", new Date("2022-01-01")),
Person("name3", new Date("2021-02-05")),
Person("name4", new Date("2021-02-03")),
Person("name12", new Date("2022-01-05")),
Person("name13", new Date("2022-01-03")),
Person("name14", new Date("2021-02-01"))
]
"Map<String, List<Person>> mergedMap": {
"2022-01": [
Person("name1", new Date("2022-01-01")),
Person("name12", new Date("2022-01-05")),
Person("name13", new Date("2022-01-03"))
],
"2021-02": [
Person("name3", new Date("2021-02-05")),
Person("name4", new Date("2021-02-03"))
],
"2022-02": [
Person("name14", new Date("2021-02-01"))
]
}
顯然,如果 map 中的分組不受諸如只有年 + 月這樣的限制性日期的約束,那么排序將在不同的組中產生預期的效果。 事實上,在按日期排序的情況下,這一點得到了很好的尊重。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.