排序哈希映射的关键是另一个哈希映射

时间:2017-05-11 21:32:37

标签: java sorting dictionary arraylist hashmap

所以这是我的hashmap

   public HashMap<Integer, HashMap<String, Integer>> girls =  
          new HashMap<Integer, HashMap<String, **Integer**>>();;

我想按值加粗排序。为了澄清,外部hashMaps键代表女孩出生一年,内部hashmap代表映射到名称的受欢迎程度排名的名称。

所以,让我们说在2015年,阿比盖尔这个名字给了47373个婴儿,这是当年最受欢迎的名字,我想要回复它的第1个字母。头号名称。有没有办法以这种方式对hashmap进行排序?

我如何将内部哈希映射值转换为可以轻松排序的arraylist?有帮助吗?

2 个答案:

答案 0 :(得分:0)

在数据结构中按值对Map进行排序没有简单/优雅的方法。

  • HashMap按定义未分类。
  • LinkedHashMap按插入顺序排序。
  • TreeMap按键排序。

如果你真的需要,你可以编写一个算法,使用LinkedHashMap作为&#34;内部&#34;来构建你的数据结构。结构并确保首先插入最大值。

或者,你可以写一个小班

class NameFrequency
{
  String name;
  int frequency;
}

并使您的数据结构成为HashMap<Integer, TreeSet<NameFrequency>>并为TreeSet定义比较器,以您喜欢的方式对这些对象进行排序。

或者,最后,您可以保留您的数据结构,并且只能在访问时对其进行排序:

girls.get(2015).entrySet().stream()
  .sorted((entry1, entry2) -> entry2.getValue() - entry1.getValue())
  .forEachOrdered(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));

答案 1 :(得分:0)

您最好只为名称和出现次数创建一个类。

import java.util.Objects;

public class NameCount implements Comparable<NameCount> {

    private final String name;
    private int count;

    public NameCount(String name) {
        this.name = name;
        count = 0;
    }

    public NameCount(String name, int count) {
        this.name = name;
        this.count = count;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public void incrementCount() {
        count++;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(this.name);
    }

    @Override
    public boolean equals(Object obj) {
        if(obj == null) return false;
        if(getClass() != obj.getClass()) return false;
        final NameCount other = (NameCount)obj;
        if(!Objects.equals(this.name, other.name)) return false;
        return true;
    }

    @Override
    public int compareTo(NameCount o) {
        return o.count - count;
    }

}

然后,您可以将地图定义为Map<Integer, List<NameCount>>。请注意上面的类如何仅基于名称定义相等和哈希代码,因此如果您想查看名称是否在列表中,您只需为其创建NameCount并使用containscompareTo实施顺序从较高的数量到较低的数量,因此在获得给定年份的List<NameCount>时,您可以在其上使用Collections.sort(list)并请求{{1}的索引同名。

NameCount

使用public void test(Map<Integer, List<NameCount>> map) { int year = 2017; List<NameCount> list = map.get(year); // Do null-check on list first when using this... Collections.sort(list); NameCount check = new NameCount("Abigail"); int rank = list.indexOf(check) + 1; } 地图值来保证唯一名称条目始终对它们进行排序似乎更有意义,但请注意TreeSet defines equality based on comparison, not equals,以及它不会让你获得索引。