我有以下代码:
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" 只携带一个字符串和一个整数,则集合大小仅为 3,而不是预期的 4。如果我打印每个数字,"name3"不会被打印,所以我不能返回 3 个最大值,例如,只会出现"name4"、"name2"和"name1",但"name3"大于"name1">
任何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 时才从映射中删除键。
替代方案:在第三方库中有"多映射"集合,如Apache Commons(javadoc(。 或者,如@Keenle建议的那样,您可以使用一个集合,其中键是包含整数和字符串的对象。 您必须为此对象编写类,但这非常简单。
为了解决排名问题,我会写一个自定义类,如下所示:
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>
接口,使其作为真正的集合工作。