如何获取HashMap中的两个最高值<integer,string>,使得排名</integer,string>

时间:2014-12-18 01:20:13

标签: java

我有以下代码:

public class Tester {

    public static void main(String[] args) {
        HashMap<Integer,String> map = new HashMap<Integer,String>();

        map.put(1, "one");
        map.put(2, "twp");
        map.put(2, "two2");

        int highest = Integer.MIN_VALUE;
        String highestString = null;
        int secondHighest = Integer.MIN_VALUE;
        String secondHighestString = null;

        if (highest == Integer.MIN_VALUE){
            highest = Collections.max(map.keySet() );
            highestString = map.get(highest);
            map.remove(highest);
        }
        if (secondHighest == Integer.MIN_VALUE ){
            secondHighest = Collections.max(map.keySet() );
            secondHighestString = map.get(secondHighest);
            map.remove(secondHighest);
        }

        System.out.println(highest + highestString);
        System.out.println(secondHighest + secondHighestString);


    }

}

我无法返回两个最高值,正如我尝试的那样,因为似乎无法仅使用相同的键删除一个值,我也尝试交换它们(使HashMap也不是最佳选择) )。我应该尝试使用任何其他类型的收藏吗?

我也尝试过:

TreeSet<Tete> set = new TreeSet<Tete>();

    set.add(new Tete("name1", 1));
    set.add(new Tete("name2",4));
    set.add(new Tete("name3",4));
    set.add(new Tete("name4",12));

    System.out.println(set.size());

假设类“Tete”只携带一个String和一个Integer,设置大小只有3,而不是4,正如预期的那样。如果我打印每个数字,“name3”将不会打印,所以我不能返回3个最大值,例如,只会出现“name4”,“name2”和“name1”,但“name3”大于“name1” “

2 个答案:

答案 0 :(得分:2)

任何Map(包括HashMap)只能为任何密钥存储一个值。因此,在您的三次map.put来电之后,地图中只会有两个元素:[1,"Um"][2,"dois2"]。地图中将不再存在值"dois"

如果确实需要为每个键存储多个值,那么使用Java运行时执行此操作的方法是将每个键映射到值列表。

HashMap<Integer,ArrayList<String>> map = new HashMap<Integer,ArrayList<String>>();

这确实意味着向地图添加值以及删除值的代码更复杂。要添加值,需要使用以下代码:

ArrayList<String> list = map.get(key);
if (list == null) {
    list = new ArrayList<String>();
    map.put(key, list);
}
list.add(newValue);

删除值类似:您需要获取列表,然后从ArrayList中删除值,并仅在ArrayList的大小为{0}}时从地图中删除密钥现在0。

替代品:有&#34;多地图&#34;第三方库中的集合,例如Apache Commons(javadoc)。或者,正如@Keenle建议的那样,您可以使用一个集合,其中键是一个包含两者整数和字符串的对象。您必须为此对象编写类,但这将非常简单。

答案 1 :(得分:1)

要解决排名问题,我会编写一个自定义类,如下所示:

public class TopsCollection<D> {

    private final TreeMap<Integer, List<D>> map 
        = new TreeMap<>((lhv, rhv) -> rhv.compareTo(lhv));

    public TopsCollection() {}

    public void add(Integer score, D name) {
        List<D> vals = map.get(score);
        if (vals == null) {
            vals = new ArrayList<>();
            map.put(score, vals);
        }
        vals.add(name);
    }

    public List<D> getTops(int n) {
        return map.
            values().
            stream().
            limit(n).
            reduce(new ArrayList<D>(), (lhv, rhv) -> {
                lhv.addAll(rhv);
                return lhv;
            });
    }
}

用法:

TopsCollection<String> tc = new TopsCollection<>();
tc.add(12, "nome4");
tc.add(1, "nome1");
tc.add(4, "nome3");
tc.add(4, "nome2");

List<String> tops = tc.getTops(2); // contains 3 elements: nome4, nome3, nome2

<强>说明:

此特定实施可以返回任意数量的最高等级相关条目。

还应注意add(...)方法需要的时间与log(n)成比例,因为TopsCollection由TreeMap类支持。

如果需要,TopCollection可以实现Collection<T>界面,使其成为真正的集合。