3

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

然而,这段代码只给了我一个这样的元素,即它通过迭代找到的第一个元素,即使我知道还有更多。例如,假设地图有以下请求 - 即键(我给出请求 ID): 3 | 5 | 2 及其各自的值是: 8 | 4 | 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());

       }

    }
4

3 回答 3

5

我建议您分两步进行

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

这是一个代码示例:

// 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());
    }
}
于 2013-04-18T09:38:58.183 回答
1

正如 Matthias Meid 所说,您必须使用 a>=而不是 a >

此外,如果认为你应该有这样的东西,或者你的 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

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

于 2013-04-18T09:48:21.367 回答
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());
    }
}
于 2016-05-04T14:24:50.617 回答