如何从Java中的哈希映射获取所有最小值

时间:2013-04-18 09:33:12

标签: java hashmap

我有一个哈希映射,其中包含Request类型的Keys对象和Integer类型的值。我使用以下代码迭代地图并获取所有最小值,然后将其键添加到列表中。我强调所有因为键是唯一的但值可以是重复的,因此可能有多个具有最小值的地图元素。

然而,这段代码只给了我一个这样的元素,也就是它通过迭代找到的第一个元素,即使我知道还有更多。例如,让我们说地图有以下请求 - 即密钥(我给出请求ID):3 | 5 | 2和它们各自的值是:8 | 4 |因此,在这个例子中,我们有两个最小元素,即两个共享最小值的元素,ID 5和ID 2,两者都是值4.代码将只向我的列表中添加ID为5的元素,即是,他们中的第一个。

我必须注意有一个类似的线程(Key for maximum value in Hashtable),但提供的解决方案在我的情况下不起作用。

以下是代码:

 Entry<Request, Integer> min = null;

 List<Request> minKeyList = new ArrayList<Request>();

 for(Entry<Request, Integer> entry : this.map.entrySet()) {

      if (min == null || min.getValue() > map.getValue()) {

           min = entry;
           minKeyList.add(entry.getKey());

      }

任何建议或解释为什么会发生这种情况将不胜感激。

编辑:新方法

好吧,我找到了解决方案。它不优雅,但它的工作原理。这是代码。

    // list for finding the min value
    List<Integer> minValList = new ArrayList<Integer>();

    // List for keeping the keys of the elements with the min value
    List<Request> minKeyList = new ArrayList<Request>();

    // scan the map and put the values to the value list
    for(Entry<Request, Integer> entry : this.map.entrySet()) {

        minValList.add(entry.getValue());

    }

    // scan the map   
    for(Entry<Request, Integer> entry: this.map.entrySet()) {

        // find the min value
        if(entry.getValue() == Collections.min(minValList)) {

            // add the keys of the elements with the min value at the keyList
            minKeyList.add(entry.getKey());

       }

    }

3 个答案:

答案 0 :(得分:4)

我建议您进行两步流程

  1. 找到最小值,存储在min
  2. 查找值等于min
  3. 的所有元素

    以下是代码示例:

    // find minimum first
    int min = Integer.MIN_VALUE;
    for(Entry<Request, Integer> entry : this.map.entrySet()) {
        min = Math.min(min, map.getValue())
    }
    
    // add all elements that have a value equal to min
    List<Request> minKeyList = new ArrayList<Request>();
    for(Entry<Request, Integer> entry : this.map.entrySet()) {
        if(min.getValue() == min) {
            minKeyList.add(entry.getKey());
        }
    }
    

答案 1 :(得分:1)

Matthias Meid说,你必须使用>=代替>

另外,如果认为你应该有这样的东西,或者你的minKeyList将包含min已经拥有的所有值。

if(min == null || min.getValue() >= map.getValue()) {
    if(min == null || min.getValue() > map.getValue()){
        min = entry;
        minKeyList.clear();
    }
    minKeyList.add(entry.getKey());
}

修改:经过测试的代码

我用一些示例代码测试了这个方法,它似乎正常工作。

以下是我用来测试它的代码:

public static void main(String[] args) {

    HashMap<Integer, Integer> map = new HashMap<>();
    map.put(7, 12);
    map.put(3, 3);
    map.put(1, 10);
    map.put(4, 12);
    map.put(6, 3);
    map.put(8, 3);
    map.put(9, 13);
    Entry<Integer, Integer> min = null;
    List<Integer> minKeyList = new ArrayList<Integer>();

    for(Entry<Integer, Integer> entry : map.entrySet()) {

        if (min == null || min.getValue() >= entry.getValue()) {
            if(min == null || min.getValue() > entry.getValue()){
                min = entry;
                minKeyList.clear();
            }
            minKeyList.add(entry.getKey());
        }
    }

    for (Integer integer : minKeyList) {
        System.out.println(integer);
    }
}

为了简化我的测试,键和值都是整数,但它不应该改变任何东西。

这不是我的输出:

3
6
8

对我来说似乎是对的。 如果这没有帮助,请尝试发布更多代码。

答案 2 :(得分:1)

您可以使用2个列表/集来避免多个循环,例如

在循环开始之前

    Set setExisting = new HashSet();
    Map keyMap = new HashMap();
    // find minimum first
    int min = Integer.MIN_VALUE;`enter code here`
    for(Entry<Request, Integer> entry : this.map.entrySet()) {
    Set newSet= new HashSet<String>();
        min = Math.min(min, map.getValue());
        newSet.add(map.getValue(min));
        keyMap.put(min,newSet);
        if (min==map.getValue()){
           setExisting = (Set) keyMap.get(newSet);
           setExisting.add(map.getValue(min));
           keyMap.put(min,setExisting);
         }
  }

  // We will NOT need the below loop in that case
  // add all elements that have a value equal to min
  List<Request> minKeyList = new ArrayList<Request>();
  for(Entry<Request, Integer> entry : this.map.entrySet()) {
    if(min.getValue() == min) {
        minKeyList.add(entry.getKey());
    }
}