简体   繁体   English

如何排序地图 <String, List<Object> &gt;通过分配给它的最多值(不是数字)的键

[英]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). 说明: TreeMapSortedMap的基本实现,它可以将键值的比较器作为参数(如果没有比较器作为参数传递,则按键的自然排序占优势)。 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. 我们需要访问密钥及其关联建立正确的顺序值两者 ,所以分选ListMap.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.

相关问题 如何通过Java的键对映射进行排序,但是如果键是(字符串+数字)的组合 - How to sort a Map in Java by its key but if the Key is combination of (String + numeric) 如何排序列表<Map<String,String> &gt; 如果 key1 具有相同的值,则按 key1 降序和 key2 升序 - How to sort List<Map<String,String>> by key1 descending order and key2 ascending order if key1 has same values 如何创建具有多个值映射到列表中相同键的映射 <Map<String,Object> ? - How to create a map having multiple values mapped to same key out of List<Map<String,Object>? 如何迭代一个列表<Map<String,String> &gt; 并将其键值添加到 Java 对象中 - How to iterate a List<Map<String,String>> and add its key,values in a Java Object 如何使用 Map 键作为列表 object 和值作为顺序对 ArrayList 进行排序? - How to sort an ArrayList using a Map key as list object and value as the order? 如何排序 java 列表<map<string, object> &gt; 按字符串升序? </map<string,> - How to sort java List<Map<String, Object>> by String asc? 我们如何从地图上显示一个键及其值 <String, List<Object> &gt;一次在JSP页面上? - How Can we show One Key and its Values from Map<String, List<Object>> at a time on a JSP page? 如何对列表进行排序<Map<String,Object> &gt; 在 Java 中 - How to i sort a List<Map<String,Object>> in java 获取 Map 中最内层的值作为 `Map 中的列表<string, list<map<string,map<string,string> &gt;&gt;&gt;` Java</string,> - Get inner most values in the Map as a List in `Map<String, List<Map<String,Map<String,String>>>>` Java 将值列表转换为地图<key, List<Object> &gt; - Convert a list of values to a map<key, List<Object>>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM