[英]How to Sort a Map<String, List<Object>> by the Key with the most values (that are not numeric) assigned to it
I have been working with Maps at present and I am baffled by how I can get my program to work effectively. 我目前一直在使用地图,我对如何让我的程序有效地工作感到困惑。 I can iterate over the map get the keys and values and sort them in alphabetical and reverse alphbetical order quite easily and have used custom comparators for this.
我可以迭代地图获取键和值,并按字母顺序和反向字母顺序对它们进行排序,并使用自定义比较器。 However, I am now trying to sort the map based on the key with the most values.
但是,我现在正在尝试根据具有最多值的键对地图进行排序。 The values are a list of objects I have created and can be thought of as this scenario.
这些值是我创建的对象列表,可以将其视为此场景。
There is an Atlas(like a catalog) that has lots of towns (the key of type string). 有一个地图集(如目录)有很多城镇(字符串类型的键)。 That contains Shops(List).
那包含商店(列表)。 I want to sort this so that the town with the most shops is displayed first and goes in descending order with the secondary sorting being based on town alphabetically and return a string representing this.
我想对此进行排序,以便首先显示具有最多商店的城镇并按降序排列,其中二级排序按字母顺序基于城镇并返回表示此字符串的字符串。
I have used the Comparator interface with seperate classes for each one alphabetically and reverse alphabetically so far and wish to follow the same pattern for learning purposes However this has me completely stumped. 我已经按字母顺序使用了Comparator接口,每个按字母顺序分开,并且按字母顺序反向排列,并希望按照相同的模式进行学习。但这让我完全难过。
Example: 例:
class Atlas {
Map<String, List<Shop> atlas = new HashMap<String, List<Shop>();
void addShop(Shop shop){
//if(Atlas already contains){
get the town and add the shop to it.
}
else{
add the town as the key and the shop as the value in the list
}
}
List<Shop> getAllShopsFromTheGivenTown(String givenTown){
//if(Atlas contains givenTown){
return the givenTown from the List.
}
else{
//Return an ArrayList emptyList
}
}
public String returnAllTownsAndShopsAlphbetically(){
String tmpString = "";
List<String> keys = new LinkedList<String>(atlas.keySet());
TownComparatorAtoZ tc = new TownComparatorAtoZ();
Collections.sort(keys, tc);
for(String town : keys){
List<Shop> shops = new LinkedList<Dealer>(atlas.get(town));
ShopComparatorAtoZ sc = new ShopComparatorAtoZ();
Collections.sort(shop, sc);
for(Shop shop : shops){
if(tmpString.isEmpty()){
tmpString = tmpString + town + ": " + shop.getName();
}
else if(tmpString.contains(town)){
tmpString = tmpString + ", " + shop.getName();
}
else{
tmpString = tmpString + " | " + town + ": " + shop.getName(); }
}
}
return tmpString;
}
}
As can be seen from above (although not the cleanest and most efficient) returns things alphabetically and will be reformatted into a string builder. 从上面可以看出(尽管不是最干净和最有效的)按字母顺序返回的东西,并将重新格式化为字符串构建器。 However, I am wondering how I can use a comparator to achieve what I am after and if someone could provide a code snippet with an explanation of what it actually does I would be grateful as its more about understanding how to do it not just getting a copy and pasted lump of code but need to see if visually in code to understand it.
但是,我想知道如何使用比较器来实现我所追求的目标,如果有人能够提供一个代码片段,并解释它实际上做了什么,我将不胜感激,因为它更多的是了解如何做到这一点而不仅仅是获得一个复制并粘贴一堆代码,但需要在代码中以可视方式查看它。
SO output I want to be something like SO输出我希望是这样的
manchester: m&s, h&m, schuch | manchester:m&s,h&m,schuch | birmingham: game, body shop |
伯明翰:游戏,车身店| liverpool: sports
利物浦:运动
You can try something like this: 你可以尝试这样的事情:
public static Map<String, List<Shop>> mySortedMap(final Map<String, List<Shop>> orig)
{
final Comparator<String> c = new Comparator<String>()
{
@Override
public int compare(final String o1, final String o2)
{
// Compare the size of the lists. If they are the same, compare
// the keys themsevles.
final int sizeCompare = orig.get(o1).size() - orig.get(o2).size();
return sizeCompare != 0 ? sizeCompare : o1.compareTo(o2);
}
}
final Map<String, List<Shop>> ret = new TreeMap<String, List<Shop>>(c);
ret.putAll(orig);
return ret;
}
Explanation: TreeMap
is the basic implementation of a SortedMap
, and it can take a comparator of key values as an argument (if no comparator is passed as an argument, natural ordering of the keys prevails). 说明:
TreeMap
是SortedMap
的基本实现,它可以将键值的比较器作为参数(如果没有比较器作为参数传递,则按键的自然排序占优势)。 Here we create an ad hoc comparator comparing the list sizes of the original map passed as an argument, and if the sizes are equal, it compares the keys themselves. 这里我们创建一个ad hoc比较器,比较作为参数传递的原始映射的列表大小,如果大小相等,则比较键本身。 Finally, we inject all elements from the origin map into it, and return it.
最后,我们将原始地图中的所有元素注入其中,并将其返回。
What if you try something like the following: 如果您尝试以下内容,该怎么办?
private static final Comparator<Map.Entry<String, List<Shop>>> CountThenAtoZ =
new Comparator<Map.Entry<String, List<Shop>>>() {
@Override
public int compare(Map.Entry<String, List<Shop>> x, Map.Entry<String, List<Shop>> y) {
// Compare shop count first. If equal, compare keys alphabetically.
int cmp = ((Integer)x.getValue().size()).compareTo(y.getValue().size());
return cmp != 0 ? cmp : x.getKey().compareTo(y.getKey());
}
};
...
public String returnAllTownsAndShopsAlphbetically() {
List<Map.Entry<String, List<Shop>>> entries = new ArrayList<>(atlas.entrySet());
Collections.sort(entries, CountThenAtoZ);
String result = "";
boolean firstTown = true;
for (Map.Entry<String, List<Shop>> entry : entries) {
if (!firstTown) result += " | "; else firstTown = false;
result += entry.getKey() + ": ";
boolean firstShop = true;
TreeSet<Shop> sortedShops = new TreeSet<>(new ShopComparatorAtoZ());
sortedShops.addAll(entry.getValue());
for (Shop shop : sortedShops) {
if (!firstShop) result += ", "; else firstShop = false;
result += shop.getName();
}
}
return result;
}
The way this works is to first create a list of the atlas entries in exactly the order we want. 这种方法的工作方式是首先按照我们想要的顺序创建一个地图集条目列表。 We need access to both the keys and their associated values to build the correct ordering, so sorting a
List
of Map.Entry
instances is the most convenient. 我们需要访问密钥及其关联建立正确的顺序值两者 ,所以分选
List
的Map.Entry
实例是最方便的。
We then walk the sorted list to build the resulting String
, making sure to sort the shops alphabetically before adding them to the String
. 然后,我们遍历排序列表以构建生成的
String
,确保在将它们添加到String
之前按字母顺序对这些商店进行排序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.