【问题标题】:How to delete entry in Java TreeMap?如何删除 Java TreeMap 中的条目?
【发布时间】:2021-08-29 10:40:00
【问题描述】:

我正在制作一个方法,它采用提供的 TreeMap,删除键是 keyFilter 的倍数 并且 值包含 valueFilter 字符的条目,然后返回生成的 TreeMap。

这是我目前所拥有的:

public static TreeMap<Integer, String> filterTreeMap(
        TreeMap<Integer, String> map, int keyFilter, char valueFilter) {
    for (Map.Entry<Integer, String> entry : map.entrySet()) {
        int mapKey = entry.getKey();
        String mapValue = entry.getValue();
        if (mapKey%keyFilter == 0 && mapValue.indexOf(valueFilter) != -1) {
            map.remove(mapKey);
        }
    }
    return map;
}

但是,在我想删除条目的 if 条件下,我不知道如何删除树形图中的条目。据我所知,目前没有可以使用的方法吗?

【问题讨论】:

  • 您不应该隐式迭代地图并同时使用remove,因为这可能会导致ConcurrentModificationException。在条目集上使用显式迭代器并调用该迭代器的remove 方法。

标签: java treemap


【解决方案1】:

使用Iterator。正如Iterator.remove() Javadoc 所指出的那样

如果在迭代过程中以任何方式而不是通过调用此方法来修改底层集合,则迭代器的行为是未指定的。

类似

public static TreeMap<Integer, String> filterTreeMap(TreeMap<Integer, String> map,
        int keyFilter, char valueFilter) {
    Iterator<Map.Entry<Integer, String>> iter = map.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry<Integer, String> entry = iter.next();
        int mapKey = entry.getKey();
        String mapValue = entry.getValue();
        if (mapKey % keyFilter == 0 && mapValue.indexOf(valueFilter) != -1) {
            iter.remove();
        }
    }
    return map;
}

【讨论】:

    【解决方案2】:

    可以将方法removeIf应用于条目集。

    default boolean removeIf(Predicate&lt;? super E&gt; filter)
    删除此集合中满足给定谓词的所有元素。迭代期间或谓词引发的错误或运行时异常将转发给调用者。

    实施要求:
    默认实现使用其iterator() 遍历集合的所有元素。使用Iterator.remove() 删除每个匹配元素。如果集合的迭代器不支持删除,则将在第一个匹配元素上抛出 UnsupportedOperationException

    那么filterTreeMap方法可能有void返回类型,因为输入map被修改了,这个改变在这个方法之外是“可见的”。

    public static void filterTreeMap(
            TreeMap<Integer, String> map, int keyFilter, char valueFilter) {
        map.entrySet().removeIf(e -> 
            e.getKey() % keyFilter == 0
            && e.getValue().indexOf(valueFilter) != -1
        );
    }
    

    【讨论】:

      【解决方案3】:

      地图上的键是唯一的。因此,找到这些键,然后将它们从地图中移除。

      public static TreeMap<Integer, String> filterTreeMap(TreeMap<Integer, String> map,
                      int keyFilter, char valueFilter) {
                      
                      Set<Integer> keysToRemove = map.entrySet().stream()
                          .filter(kv -> kv.getKey() % keyFilter == 0 && kv.getValue().indexOf(valueFilter) != -1) // can be Predicate parameter
                          .map(Map.Entry::getKey)
                          .collect(Collectors.toSet());
              
                      keysToRemove.forEach(map::remove);
                      
                      return map; // keep in mind, map is modified here. You might want to return a new map instead
                  }
      

      【讨论】:

        【解决方案4】:

        迭代一个副本,你可以添加/删除就好了:

        for (Map.Entry<Integer, String> entry : new LinkedHashMap<Integer,String> (map).entrySet()) {
            int mapKey = entry.getKey();
            String mapValue = entry.getValue();
            if (mapKey%keyFilter == 0 && mapValue.indexOf(valueFilter) != -1) {
                map.remove(mapKey);
            }
        }
        

        它甚至不再是代码行,因为副本是通过复制构造函数内联生成的。选择LinkedHashMap 是为了保留迭代顺序(如果重要的话)。

        【讨论】:

          猜你喜欢
          • 2014-07-19
          • 1970-01-01
          • 2016-11-06
          • 2013-01-15
          • 1970-01-01
          • 2014-07-23
          • 1970-01-01
          • 1970-01-01
          • 2017-05-26
          相关资源
          最近更新 更多