【问题标题】:Java hashmap iteratorJava hashmap 迭代器
【发布时间】:2015-09-19 22:38:33
【问题描述】:

我想做removeValue( "a", "x")的方法。
它必须删除字母之间的所有键和值。例如:

{1=a,2=b,3=c,5=x}  ->> {1=a,5=x}

我尝试过使用 equals 和迭代器,但我不知道如何编写它。

public class CleanMapVal {

    public static void main(String[] args) throws Exception {


        Map<String, String> map = new HashMap<String, String>();
        map.put("1", "a");
        map.put("2", "b");
        map.put("3", "c");
        map.put("4", "w");
        map.put("5", "x");

         System.out.println( map );

        for (Iterator<String> it = map.keySet().iterator(); it.hasNext();)
            if ("2".equals(it.next()))
                it.remove();

        System.out.println(map);

    }

    public static <K, V> void removeValue(Map<K, V> map) throws Exception {
        Map<K, V> tmp = new HashMap<K, V>();
        for (Iterator<K> it = map.keySet().iterator(); it.hasNext();) {
            K key = it.next();
            V val = map.get(key);
            if (!tmp.containsValue(val)) {
                tmp.put(key, val);
            }
        }
        map.clear();
        for (Iterator<K> it = tmp.keySet().iterator(); it.hasNext();) {
            K key = it.next();
            map.put((K) tmp.get(key), (V) key);
        }
    }
}

【问题讨论】:

  • 你已经有问题了,Map 不能保证其条目的顺序;所以一开始就没有“a和x之间的键”这样的东西。当然,您也可以使用LinkedHashMap,但我怀疑这是一个 XY 问题。
  • 我不确定您要做什么。正如@fge 提到的 HashMap 没有保证顺序。 LinkedHashMap 也像 List 一样对其元素进行排序,新元素放在最后,所以你仍然不能通过它们的值(或键)得到保证的元素顺序。因此,假设您有映射{a=1, b=2, c=3, d=2, e=1} 并且您调用removeValue( "1", "3")。结果应该是{a=1, c=3, d=2, e=1}{a=1, c=3, e=1} 还是其他?

标签: java hashmap iterator key key-value


【解决方案1】:

试试下面的代码。我使用树形图来维护顺序,然后迭代删除元素。

 Map<Integer, String> map = new TreeMap<Integer, String>();
    map.put(1, "a");
    map.put(2, "b");
    map.put(3, "c");
    map.put(4, "w");
    map.put(5, "x");
    ArrayList<Integer> intList = new ArrayList<Integer>();
    for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext();) {
        int key = 0;
        if (it.next() == 1) {
            while(true) {
                key = it.next();
                if(key==5)break;
                intList.add(key);

            }
        }

    }
   //removing from the map in separate loop to avoid concurrent modification exception

    for (int i : intList) {
        map.remove(i);
    }

    System.out.println(map.size()); //2

【讨论】:

    【解决方案2】:

    首先,HashMap 永远不会保留放入其中的Object 的订单。所以你需要使用LinkedHashMap 来维护它的插入顺序。 要删除Object,您需要使用Iterator

    Map testMap = new LinkedHashMap&lt;Integer, String&gt;(); 如果您的key 是除Integer 之外的任何其他类型,请相应更改。

    因此,根据您的要求,您可以使用以下代码:-

     public static void testKey(Map<Integer, String> testMap, String startValue,
                String endValue) {
     if(!testMap.containsValue(startValue) || !testMap.containsValue(endValue))
                return; // if start/end value is not present in Map then no change at all
            Iterator<Map.Entry<Integer, String>> iter = testMap.entrySet()
                    .iterator();
            boolean deleteFlag = false;
            while (iter.hasNext()) {
                Map.Entry<Integer, String> entry = iter.next();
                if (endValue.equalsIgnoreCase(entry.getValue())) {
                    deleteFlag = false;
                }
                if (deleteFlag)
                    iter.remove();
                if (startValue.equalsIgnoreCase(entry.getValue())) {
                    deleteFlag = true;
                }
    
            }
        }
    
    public static void main(String[] args) {
            Map m = new LinkedHashMap<Integer, String>();
            m.put(1, "a");
            m.put(2, "b");
            m.put(3, "c");
            m.put(5, "x");
            System.out.println("before : "+m);
            removeValue(m, "a", "x");
            System.out.println("after : "+m);
        }
    

    输出

    before : {1=a, 2=b, 3=c, 5=x}
    after : {1=a, 5=x}
    

    【讨论】:

    • 很高兴它有帮助。如果对您有用,您可以将其标记为正确
    【解决方案3】:

    使用Iterator 允许您即时删除条目。

    public void removeRange(Map<Integer, String> map, String from, String to) {
        // Walk each entry.
        for (Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator(); it.hasNext();) {
            // What is the value?
            String v = it.next().getValue();
            if (v.compareTo(from) > 0 && v.compareTo(to) < 0) {
                // In the specified range! Remove it.
                it.remove();
            }
        }
    
    }
    
    public void test() {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "a");
        map.put(2, "b");
        map.put(3, "c");
        map.put(4, "w");
        map.put(5, "x");
        System.out.println("Before:" + map);
        removeRange(map, "a", "x");
        System.out.println("After:" + map);
    }
    

    打印

    之前:{1=a, 2=b, 3=c, 4=w, 5=x}

    之后:{1=a, 5=x}

    如果您使用的是 Java 8,您还可以流式传输和过滤 Map。

    public <K, V> Map<K, V> filter(Map<K, V> map, Predicate<Map.Entry<K, V>> filter) {
        return map.entrySet()
                .stream()
                // Filter out the unwanted ones.
                .filter(filter)
                // Fold back into a new Map.
                .collect(Collectors.toMap(
                                (Map.Entry<K, V> e) -> e.getKey(),
                                (Map.Entry<K, V> e) -> e.getValue()));
    }
    
    public Map<Integer, String> removeRangeWithStream(Map<Integer, String> map, String from, String to) {
        return filter(map,
                (Map.Entry<Integer, String> e) -> e.getValue().compareTo(from) <= 0 || e.getValue().compareTo(to) >= 0);
    }
    

    【讨论】:

    • v.compareTo(from) &gt; 0 &amp;&amp; v.compareTo(to) &lt; 0 如果在地图中我们有map.put(1, "a"); map.put(2, "x"); map.put(3, "w"); map.put(4, "c"); 表示键的顺序已更改,这将失败
    • @AnkitNigam - 我没有阅读涉及键的问题 - 我将其阅读为 remove all entries with values between (但不包括) "a" 和“x”.
    猜你喜欢
    • 2011-03-21
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2015-04-13
    相关资源
    最近更新 更多