2

I want to make the method removeValue( "a", "x").
It must delete all keys and values between the letters. For example:

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

I tried with equals and iterator but I don't know how to write it.

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);
        }
    }
}
2
  • 3
    You have a problem already, in that a Map doesn't guarantee the ordering of its entries; so there is no such thing as "keys between a and x" to begin with. Of course, you could also use a LinkedHashMap but my suspiscion is that this is a XY problem to begin with. Commented Jul 2, 2015 at 11:54
  • I am not sure what you are trying to do. As @fge mentioned HashMap doesn't have guaranteed order. Also LinkedHashMap orders its elements like List, new elements are placed at the end, so still you are not getting guaranteed order of elements by their value (nor key). So lets say that you have map {a=1, b=2, c=3, d=2, e=1} and you invoke removeValue( "1", "3"). Should result be {a=1, c=3, d=2, e=1} or {a=1, c=3, e=1} or maybe something else? Commented Jul 2, 2015 at 12:07

3 Answers 3

2

Try the following code.I'm using treemap to maintain the order and then iterating to remove the elements.

 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
Sign up to request clarification or add additional context in comments.

Comments

1

First of all, a HashMap never keeps the orders of the Object which are put in it. So you need to use LinkedHashMap which maintains its insertion order. For removal of Object you need to make use of Iterator

Map testMap = new LinkedHashMap<Integer, String>(); If your key is of any other type except Integer change it accordingly.

So for your requirement, you can use the below code :-

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

Output

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

1 Comment

Glad that it helped. You can mark this as correct if it worked for you
0

Using an Iterator allows you to remove entries on the fly.

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

prints

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

After:{1=a, 5=x}

If you are using Java 8 you can also stream and filter a 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);
}

2 Comments

v.compareTo(from) > 0 && v.compareTo(to) < 0 this will fail if in map we have map.put(1, "a"); map.put(2, "x"); map.put(3, "w"); map.put(4, "c"); means the order of keys is changed
@AnkitNigam - I don't read the question involving keys - I read it as remove all entries with values between (but not including) "a" and "x".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.