【问题标题】:Efficient way to delete values from hashmap object从 hashmap 对象中删除值的有效方法
【发布时间】:2011-06-09 17:01:00
【问题描述】:

我的 HashMap 对象包含一个键 x-y-z 和对应的值 test-test1-test2

Map<String,String> map = new HashMap<String,String>(); 
map.put("x-y-z","test-test1-test2");
map.put("x1-y1-z1","test-test2-test3"); 

现在我有一个输入字符串数组,其中包含一些键:

String[] rem={"x","x1"}

基于这个字符串数组,我想删除 HashMap 值。

谁能给出一个有效的方法来做这个操作?

【问题讨论】:

  • 我很难准确地理解你在做什么以及你在问什么。也许是我,但你能澄清一下这个问题吗?
  • Map map=new HashMap(); map.put("x-y-z","test-test1-test2");map.put("x1-y1-z1","test-test2-test3");现在我有 Input string array contains String[] rem={"x","x1"}.based on this String array.I want to remove hashmap values.
  • 您对其他数据结构持开放态度吗?如果您有很多条目,那么还有其他结构(例如嵌套映射)可以大大加快此操作。
  • 恢复了问题 :-) 您的评论使问题更加清晰 - 但是您是否希望将哈希映射键的 开始 与字符串的每个元素进行比较,并相应地删除地图值?

标签: java hashmap


【解决方案1】:

您可以执行以下操作:

Map<String,String> map = new HashMap<String,String>(); 
map.put("x-y-z","test-test1-test2");
map.put("x1-y1-z1","test-test2-test3"); 

String[] rem={"x","x1"};

for (String s : rem) {
    map.keySet().removeIf(key -> key.contains(s));
}

这段代码将删除映射键中所有带有“x”或“x1”的条目。

【讨论】:

    【解决方案2】:
    List remList = Arrays.asList(rem);
    for (Iterator it = map.keySet().iterator(); it.hasNext();) {
        String key = (String) it.next();
        String[] tokens = key.split("-");
        for (int i = 0; i < tokens.length; i++) {
            String token = tokens[i];
            if (remList.contains(token)) {
                it.remove();
                break;
            }
         }
    }
    

    以及根据您对此答案的最新评论添加功能的更新版本:

    private static Map getMapWithDeletions(Map map, String[] rem) {
        Map pairs = new HashMap();
        for (int i = 0; i < rem.length; i++) {
            String keyValue = rem[i];
            String[] pair = keyValue.split("@", 2);
            if (pair.length == 2) {
                pairs.put(pair[0], pair[1]);
            }
        }
        Set remList = pairs.keySet();
        for (Iterator it = map.keySet().iterator(); it.hasNext();) {
            String key = (String) it.next();
            String[] tokens = key.split("-");
            for (int i = 0; i < tokens.length; i++) {
                String token = tokens[i];
                if (remList.contains(token)) {
                    it.remove();
                    pairs.remove(token);
                    break;
                }
            }
        }
        map.putAll(pairs);
        return map;
    }
    

    【讨论】:

    • 谢谢玛丽亚,如果没有键匹配,我该怎么做才能添加。
    • 你能再解释一下吗?你的意思是以下吗?如果 rem 包含一个值,例如x2,比在映射键标记中不存在的任何位置,以 x2 作为键向映射添加条目?如果有,有什么价值?
    • 是的,我忘了提,最初这个字符串数组我将作为输入字符串 a[]={4-A06-19@A06-test-test1,2-B30-19@B30 -test3-test4}。这个字符串数组是key@value。对于删除我有HashMap,如果我使用上面的代码它会起作用,但是对于我来说添加HashMap不可用。我必须根据字符串在Hashmap中构造键和值数组输入。
    • 玛丽亚:感谢代码,我正在考虑错误情况,如果对 [1] 有 B-30 而不是 B30,则会错误地导致 ArrayIndexOutofBoundsException 。无论如何要避免此错误。
    • String[] 对 = keyValue.split("@", 2); if (pair.length == 2) { pairs.put(pair[0], pair[1]); } 我也适当地更新了我的答案。
    【解决方案3】:

    假设我对您的理解正确,并且您想从地图中删除以“x-”和“x1-”开头的所有内容(但不是“x1111-”,即使“x1”是“x1111”的前缀) ,而效率很重要,您可能想查看NavigableMap 的实现之一,例如(例如)TreeMap

    NavigableMaps 保持它们的条目有序(默认情况下按自然键顺序),并且可以非常有效地迭代和搜索。

    他们还提供了像subMap 这样的方法,它可以生成另一个包含指定范围内的键的 Map。重要的是,这个返回的地图是一个实时视图,这意味着在这个地图上的操作也会影响到原始地图。

    所以:

    NavigableMap<String,String> map = new TreeMap<String,String>(); 
    // populate data
    for (String prefixToDelete : rem) {
        // e.g. prefixToDelete = "x"
        String startOfRange = prefixToDelete + "-"; // e.g. x-
        String endOfRange = prefixToDelete + "`"; // e.g. x`; ` comes after - in sort order
        map.subMap(startOfRange, endOfRange).clear(); // MAGIC!
    }
    

    假设您的地图很大,.subMap() 应该比遍历每个地图条目要快得多(因为 TreeMap 使用 red-black tree 进行快速搜索)。

    【讨论】:

    • 考恩:没有x应该是任何东西,它是1或y或z,我不与x-比较,我只与x比较。
    • 好的,知道了。你的例子不是很清楚,对不起。因此,使用上面的示例 (4-A06-19@A06-test-test1,2-B30-19@B30-test3-test4) 然后 rem = {"B"} 将删除第二个,或者 rem = {"0 "} 会删除两者吗?在这种情况下,我的解决方案将无济于事,您需要按照 Maria 的答案进行迭代。这不是特别有效,但只要这是您的问题范围,我认为您会陷入低效状态。
    【解决方案4】:

    根据已编辑的问题进行编辑。

    循环遍历 hashmap 的 keySet。当您找到以 x 开头的键时,您正在寻找将其从地图中删除。

    类似:

    for(String[] key: map.keySet()){
       if(key.length>0 && x.equals(key[0])){
          map.remove(key);
        }
    }
    

    【讨论】:

    • 对于大型地图,这不会特别有效,并且如果部分键是y,它也不会泛化。
    • @Mark E 是的,但在理想情况下,数据甚至不会存储在这种结构中。
    • 根据 OP 的限制,这是一个更好的答案。也不清楚键是数组。
    • 我只给了测试数据键可以是任何东西让我们说 y。
    • 如果您希望匹配键的任何值以导致删除,您必须检查当前设置中的每个值。
    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 2019-10-12
    • 2021-10-13
    相关资源
    最近更新 更多