【问题标题】:sorting hash map based on interger基于整数对哈希图进行排序
【发布时间】:2023-04-07 01:57:01
【问题描述】:

尝试按降序对列表进行排序,因此最长的时间在前。这是我的方法,我从这里使用了几页来使其正确,但是我的代码中的某些内容是错误的,它返回的列表不太正确。

public static ArrayList<String> winnerIs(List<HP> hp){
        //System.out.println("1");
        int size = hp.size();
        //System.out.println(size);
        ArrayList<HP> listofWinner = new ArrayList<HP>();
        Map<String, Integer> map = new HashMap<String, Integer>();

        for(int i = 0; i < size; i++){
            listofWinner.add(hp.get(i));
            map.put(hp.get(i).getName(), hp.get(i).TD1());
            //System.out.println(hp.get(i).getName()+" "+hp.get(i).TD1());
        }
        //sort based on time
        ArrayList<String> keys = new ArrayList<String>(map.keySet());
        //System.out.println("---------------");
        /*for(int i = 0; i < keys.size(); i++){ 
            //wn.add(keys.get(i));
            System.out.println("here "+keys.get(i));
        }*/
        //System.out.println("---------------");


        ArrayList<String> wn = new ArrayList<String>();

        //System.out.println("---------------");
        for(int i = keys.size()-1; i >= 0; i--){    
            wn.add(keys.get(i));

        }
        return wn;
    }

这是它的重复:

[team2, team1, team4, team3]

但应该是这样的:

[team4, team3, team2, team1]

时间是否相等没关系,我们只需要更好的时间,我不确定代码的哪一部分是错误的。

即使我使用这个

ArrayList<Integer> s = new ArrayList<Integer>(map.values());
        Collections.sort(keys);
        //System.out.println("---------------");
        for(int i = 0; i < s.size(); i++){  
            //wn.add(keys.get(i));
            System.out.println("here "+s.get(i));
        }

结果仍然不正确,这是它返回的内容:

here 2
here 9
here 0
here 0

所以我使用了 stackoverflouw 的其中一个页面并找到了这个解决方案:

public static ArrayList<String> winnerIs(List<HumanPlayer> hp){
        //System.out.println("1");
        int size = hp.size();
        //System.out.println(size);
        ArrayList<HumanPlayer> listofWinner = new ArrayList<HumanPlayer>();
        Map<String, Integer> map = new HashMap<String, Integer>();

        for(int i = 0; i < size; i++){
            listofWinner.add(hp.get(i));
            map.put(hp.get(i).getName(), hp.get(i).getTimeDriver1());
            //System.out.println(hp.get(i).getName()+" "+hp.get(i).getTimeDriver1());
        }
        map.entrySet().stream()
        .sorted(Map.Entry.<String, Integer>comparingByValue().reversed()) 
        .limit(1000) 
        .forEach(System.out::println);

        return null;
    }

这将返回正确的列表,但我不确定这是什么:.limit(1000) 以及如何将其等同于列表,以便我可以返回它。

【问题讨论】:

  • 您实际上是在重新排序,而不是排序。 HashMap 是一个无序映射。请改用LinkedHashMap,或使用Collections.sort 对结果列表进行排序。
  • 您将 name 作为键并对稍后获得的 keyset() 进行排序。我不知道 TD1() 是什么,但如果是你想要排序的时间,那么你应该在 Map 中排序值而不是键。
  • @Amit 如果是 valueSet() 而不是 keySet(),我该怎么做??
  • 如果你在你的 HP 类中实现 Comparable,那么你可以只对输入 List 进行排序然后颠倒顺序,不需要 Map
  • 这个很不清楚,你能清理一下你的代码,还有标题,wn是一个列表而不是地图

标签: java sorting hashmap


【解决方案1】:

您可以使用 Java 8 按地图的值进行漂亮的排序:

Map<String, Integer> sorted = /* your map */.entrySet().stream()
        .sorted(Entry.comparingByValue()) //comparator for value, can reverse or use other
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue,
                (e1, e2) -> { throw new IllegalArgumentException("Duplicate Key: " + e1.getKey()); },
                LinkedHashMap::new));

我选择为重复键(合并函数,Collectors#toMap 的第三个参数)抛出异常,但您也可以只返回找到的第一个键:

.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));

要记住的是各个地图所遵循的合同。 HashMap 是未排序的映射,不会保证迭代顺序(因此排序将是徒劳的努力),TreeMapSortedMap,但这在合同上意味着它是按键排序的,而不是值。 LinkedHashMap 将保留迭代顺序,通常基于插入(很像 List),因此通常是您需要排序映射输出时想要的。

【讨论】:

    【解决方案2】:

    假设您的 HP 类中的 TD1() 方法是您想要排序的值,并且您确实想使用 Map 来帮助您排序。我想你想要这样的东西

    Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
    for (HP h : hp) {
        if (map.get(h.TD1() != null) {
            map.get(h.TD1()).add(h.getName());
        }
        else {
          List temp = new ArrayList<String>();
          temp.add(h.getName());
          map.put(h.TD1(), temp);
        }
    }
    ArrayList keys = Arrays.asList(map.getKeyset().toArray());
    Collections.sort(keys);
    
    for ( int i = keys.length() - 1; i >= 0; i--) {
        List<String> names = map.get(i);
        // print names
    }
    

    【讨论】:

    • 不,这不好,因为方法 getName 不是这里的列表,使用 h.getName() 它说 get 方法也应该更改顺便说一句,我使用您的解决方案遇到了很多类型转换错误。
    【解决方案3】:

    检查这个伪代码,我相信你会了解这个。

    Map<Integer,List<String> map = new HashMap<Integer,List<String>>();
    for(HP hpObject:hp) {
     if(map.containsKey(hpObject.TD1())) {
        map.get(hpObject.TD1()).add(hpObject.getName());
     } else {
        List<String> names = new ArrayList<String>();
        names.add(hpObject.getName());
        map.put(hpObject.TD1(),names);
     }
    }
    
        // To sort by keys
        TreeMap sortedByTD = new TreeMap(map);
    
        // Iterate over TreeMap and create the list of winners you need
        return result;enter code here
    

    【讨论】:

    • TreeMap 是一个 SortedMap,它被约定按键(而不是值)排序。使用LinkedHashMap 会更好,但我没有看到您在答案中对任何内容进行排序。
    • 正如您提到的,TreeMap 是排序的,因此当我们从上面的 HashMap 创建 TreeMap 时,它自然会按整数键(即 Timings)对其进行排序。您需要做的就是迭代它并创建要返回的最终名称列表。
    • 是的,但是操作没有使用整数键,他使用的是整数值。
    • 是的,这就是我在之前对 OP 帖子的评论中提到的。他应该使用在他的情况下由 Integer 表示的 Time 作为键。
    • 如果两个人有相同的时间呢?永远只有一个人?这种方法不仅会破坏某些设计方面,而且答案本身会使事情变得过于复杂(并且会暂时错过第一个条目,因此大量只是空列表)。
    猜你喜欢
    • 2016-03-26
    • 2015-01-01
    • 1970-01-01
    • 2014-01-30
    • 2019-04-25
    • 2011-10-25
    • 2015-10-06
    • 2012-07-15
    • 2013-06-16
    相关资源
    最近更新 更多