简体   繁体   English

从 JAVA 中的 hashmap 中移除最小的 k 个元素

[英]remove smallest k elements from hashmap in JAVA

I have a hashmap of objects.我有一个 hashmap 的对象。 Each object has two attributes (let say int length and int weight).每个 object 都有两个属性(比如说 int 长度和 int 重量)。 I want to remove k elements with the smallest length.我想删除长度最小的 k 个元素。 What is the efficient way of doing this?这样做的有效方法是什么?

Map<K, V> map = new HashMap<>();

...

Set<K> keys = map.keySet();
TreeSet<K> smallest = new TreeSet<>(new Comparator<K>(){
    public int compare(K o1, K o2) {
        return o1.getLength() - o2.getLength();
    }
});
smallest.addAll(keys);
for(int x = 0; x < num; x++) {
    keys.remove(smallest.pollFirst());
}

Where K is your key type, V is your value type, and num is the number of elements you wish to remove.其中K是您的键类型, V是您的值类型, num是您要删除的元素数。

If you are doing this frequently, it might be a good idea to use aTreeMap in the first place.如果您经常这样做,首先使用TreeMap可能是个好主意。

The easiest, but certainly not the most efficient is to create an instance of aTreeMap with provided Comparator for your type, putAll() elements from your map to the map you just created and remove k-elements with help of keySet() .最简单但肯定不是最有效的是创建一个TreeMap的实例,其中包含为您的类型提供的Comparator ,从您的 map 到您刚刚创建的 map 的 putAll() 元素,并在keySet()的帮助下删除 k 元素。 In the end a TreeMap will not contain k-smallest elements.最终 TreeMap 将不包含最小的 k 个元素。

You didn't mention if the attribute you discriminate on is part of the key or the value, if it's the key then teh treemap discussed above is applicbale.您没有提到您区分的属性是键还是值的一部分,如果它是键,那么上面讨论的树图是适用的。

Otherwise If you need to do this often I'd be inclined to implement my own map, delegating everything in the map interface to a hashmap (or appropriate structure0. Override the add/remove and if necessary iterator, then use the add/remove to maintain a sorted list of the values.否则,如果你需要经常这样做,我会倾向于实现我自己的 map,将 map 接口中的所有内容委托给 hashmap(或适当的结构 0。覆盖添加/删除和必要时的迭代器,然后使用添加/删除来维护值的排序列表。

This obviously assumes the values don't change and is highly coupled to your problem.这显然假设值不会改变并且与您的问题高度相关。

Keep in mind that TreeMap sorts by the natural ordering of its keys.请记住,TreeMap 按其键的自然顺序排序。 Hence you can create a key with comparable based on the length of it's value.因此,您可以根据其值的长度创建具有可比性的键。 For example (Since I am on Lunch the code isn't perfect but should get you to what you need):例如(因为我在吃午餐,所以代码并不完美,但应该可以满足您的需求):

package com.trip.test;    

import java.util.SortedMap;    
import java.util.TreeMap;    

import org.slf4j.Logger;    
import org.slf4j.LoggerFactory;    

public class ComparisonTest {    

private static Logger logger = LoggerFactory.getLogger(ComparisonTest.class);    

private static String[] a = {"1","2","3","4"};    
private static String[] b = {"A","B","D"};    
private static String[] c = {"1","B","D","1","B","D"};    
/**    
 * @param args    
 */    
static SortedMap<KeyWithLength, String[]> myMap = new TreeMap<KeyWithLength, String[]>();    

static {    

        myMap.put(new KeyWithLength("a", a.length), a);    
        myMap.put(new KeyWithLength("b", b.length), b);    
        myMap.put(new KeyWithLength("c", c.length), c);             
}    

public static void main(String[] args) {    

    // print Map    
    logger.info("Original Map:");    

    int i = 0;    
    for (String[] strArray: myMap.values() ){    
        logger.info(String.format("*** Entry %s: ", i++));    
        printStrings(strArray);    
    }    

    // chop off 2 shortest    
    chopNShortest(myMap, 2);    

    // print Map    
    logger.info("ShortenedMap:");    

    i = 0;    
    for (String[] strArray: myMap.values() ){    
        logger.info(String.format("*** Entry %s: ", i++));    
        printStrings(strArray);    
    }    

}    

static void printStrings(String[] strArray){    
    StringBuffer buf = new StringBuffer();    

    for (String str: strArray){    
        buf.append(String.format("%s, ", str));    
    }    
    logger.info(buf.toString());    
}    

static void chopNShortest(SortedMap<KeyWithLength, String[]> sortedMap, int n) {    
    // Assuming map is not unmodifiable    
    if (n <= sortedMap.size()-1){    
        for (int i = 0; i< n;i++){    
            sortedMap.remove(sortedMap.firstKey());    
        }    
    }    
}    

}    

class KeyWithLength implements Comparable<KeyWithLength> {    
private String key;    
private Integer length;    

public KeyWithLength(String key, int length) {    
    super();    
    this.key = key;    
    this.length = length;    
}    

public String getKey() {    
    return key;    
}    

public int getLength() {    
    return length;    
}    

@Override    
public int hashCode() {    
    final int prime = 31;    
    int result = 1;    
    result = prime * result + ((key == null) ? 0 : key.hashCode());    
    return result;    
}    

@Override    
public boolean equals(Object obj) {    
    if (this == obj)    
        return true;    
    if (obj == null)    
        return false;    
    if (getClass() != obj.getClass())    
        return false;    
    KeyWithLength other = (KeyWithLength) obj;    
    if (key == null) {    
        if (other.key != null)    
            return false;    
    } else if (!key.equals(other.key))    
        return false;    
    return true;    
}    

@Override    
public int compareTo(KeyWithLength another) {    
    // TODO Auto-generated method stub    
    return compare(this.length, another.length);    
}    

    public static int compare(int x, int y) {    
        return (x < y) ? -1 : ((x == y) ? 0 : 1);    
    }    

}

The output: output:

Original Map:
*** Entry 0: 
A, B, D, 
*** Entry 1: 
1, 2, 3, 4, 
*** Entry 2: 
1, B, D, 1, B, D, 

ShortenedMap:
*** Entry 0: 
1, B, D, 1, B, D, 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM