如何对地图进行排序<string,list <object =“”>&gt;通过分配给它的最多值(不是数字)的键</string,>

时间:2012-12-21 16:10:20

标签: java collections hashmap generic-collections

我目前一直在使用地图,我对如何让我的计划有效运作感到困惑。我可以迭代地图获取键和值,并按字母顺序和反向字母顺序对它们进行排序,并使用自定义比较器。但是,我现在正在尝试根据具有最多值的键对地图进行排序。这些值是我创建的对象列表,可以将其视为此场景。

有一个地图集(如目录),有很多城镇(字符串类型的键)。那包含商店(列表)。我想对此进行排序,以便首先显示具有最多商店的城镇并按降序排列,其中二级排序按字母顺序基于城镇并返回表示此字符串的字符串。

我已经按字母顺序使用了Comparator接口和每个字母的单独类,并且按字母顺序反向到目前为止,并且希望遵循相同的模式用于学习目的但是这让我完全难过。

示例:

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;   
    }
}

从上面可以看出(虽然不是最干净,最有效的)按字母顺序返回的东西,并将重新格式化为字符串构建器。但是,我想知道如何使用比较器来实现我所追求的目标,如果有人能够提供一个代码片段,并解释它实际上做了什么,我将不胜感激,因为它更多的是了解如何做到这一点而不仅仅是获得一个复制并粘贴一堆代码,但需要在代码中以可视方式查看它。

SO输出我想要像

manchester:m&amp; s,h&amp; m,schuch |伯明翰:游戏,车身店|利物浦:体育

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

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;
}

说明:TreeMapSortedMap的基本实现,它可以将键值的比较器作为参数(如果没有比较器作为参数传递,则按键的自然顺序占优势)。这里我们创建一个ad hoc比较器,比较作为参数传递的原始映射的列表大小,如果大小相等,则比较键本身。最后,我们将原始地图中的所有元素注入其中,并将其返回。

答案 1 :(得分:0)

如果您尝试以下内容会怎样:

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;
}

这种方法的工作方式是首先按照我们想要的顺序创建一个地图集条目列表。我们需要访问两个密钥及其关联值以构建正确的排序,因此排序List Map.Entry个实例是最方便的。

然后我们遍历排序列表以构建生成的String,确保在将商店添加到String之前按字母顺序对商店进行排序。