如何删除 Java TreeMap 中的条目?

How to delete entry in Java TreeMap?

我正在制作一个方法,它采用提供的 TreeMap,删除键是 keyFilter 值包含 valueFilter 字符的倍数的条目,然后 returns 生成的 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条件下,我不知道如何删除树形图中的条目。据我所知,没有现成的方法可以使用吗?

使用 Iterator。正如 Iterator.remove() Javadoc 注释

The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.

类似

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;
}

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

default boolean removeIf(Predicate<? super E> filter)
Removes all of the elements of this collection that satisfy the given predicate. Errors or runtime exceptions thrown during iteration or by the predicate are relayed to the caller.

Implementation Requirements:
The default implementation traverses all elements of the collection using its iterator(). Each matching element is removed using Iterator.remove(). If the collection's iterator does not support removal then an UnsupportedOperationException will be thrown on the first matching element.

然后方法 filterTreeMap 可能有 void return 类型,因为输入 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
    );
}

迭代一个副本,你可以add/remove就好了:

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 是为了保留迭代顺序(如果重要的话)。

地图上的键是唯一的。所以,找到那个键,然后将它们从地图中删除。

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
            }