4

I have a Map. The input is coming from another class, so I can't change the format. The value is a List in my case. I want to remove a few elements for a particular key. For example, below is the input map:

Map<String, Object> map = new HashMap<>();
    map.put("1", Arrays.asList("A","V","C","M"));
    map.put("Roll", 123); 

This "map" has been given to me and I want to remove two entries for Key = "1", i.e., Arrays.asList("V","M")

I tried the below code and it worked. I want to know is there any better approach than this. Note: I am trying to do it using Java 8.

List<String> list = Arrays.asList("V","M") 
List<String> lst =  map.entrySet().stream()
            .map(Map.Entry::getValue)
            .filter(c -> c instanceof Collection)
            .map(c -> (Collection<String>)c)
            .flatMap(Collection::stream)
            .collect(Collectors.toList());

        lst.removeIf(c -> list.contains(c));

/** * After that, I can add this final list to the map again.. */

final output: <"1", {"A", "C"}>
                 <"Roll", 123>
RoyalTiger
  • 511
  • 2
  • 8
  • 27
  • You can simplify `map.entrySet().stream().map(Map.Entry::getValue)` to `map.values().stream()` in your example, but I'd like to point out that if the map has more than one value with a List as value you'll end up mashing them together. – Jeroen Steenbeeke Jul 30 '19 at 09:20

2 Answers2

3

There is no need of stream for doing this, i prefer using computeIfPresent if key present in Map alter the value else ignore. Don't use Arrays.asList unless you need immutable list because it will not support remove operation

List<String> list = new ArrayList<String>();
    list.add("A");
    list.add("V");
    list.add("C");
    list.add("M");

    Map<String, Object> map = new HashMap<>();
    map.put("1", list);
    map.put("Roll", 123); 

    List<String> remove = Arrays.asList("V","M");

    map.computeIfPresent("1", (k,v)->{
              if(Objects.nonNull(v) && v instanceof List) {
                  @SuppressWarnings("unchecked")
                  List<String> result = (List<String>) v;
                  result.removeIf(i->remove.contains(i));
                  return  result;
              }
            return v;
    });

    System.out.println(map);    //{1=[A, C], Roll=123}
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • `l` as variable name is problematic, especially if the key is `1`. – John Jul 30 '19 at 09:32
  • Thanks @Deadpool . This is nice and looks very neat. Yes, `computeIfPresent` is perfect for this scenario. I've not used it before. Will try it now. – RoyalTiger Jul 30 '19 at 09:37
  • Why am I getting 'incompatible types: incompatible parameter types in lambda expression' in line "if(Objects.nonNull(v) && v instanceof List) {" - Cannot ase to – RoyalTiger Jul 30 '19 at 10:01
  • what does it says exactly? the above code works for me, i'm on jdk 11 @RoyalTiger – Ryuzaki L Jul 30 '19 at 10:04
  • It's giving a compilation error: Inconvertible Types: Cannot cast to 'java.util.List' I am on jdk 1.8 – RoyalTiger Jul 30 '19 at 10:06
  • can you please post the error and have you tried executing it? does it break? @RoyalTiger – Ryuzaki L Jul 30 '19 at 10:08
  • 1
    updated post just add that annotation `@SuppressWarnings("unchecked")` – Ryuzaki L Jul 30 '19 at 10:31
  • Sure. It's working now @Deadpool. It's my bad. It was some local settings due to which the error was coming. Also some checkstyle errors too (All these are related to my project settings). But the above code WORKS just FINE. – RoyalTiger Jul 30 '19 at 10:38
2

You could filter the entries which are not in the list, like:

List<String> lst =  map.entrySet().stream()
            .map(Map.Entry::getValue)
            .filter(c -> c instanceof Collection)
            .map(c -> (Collection<String>)c)
            .flatMap(Collection::stream)
            .filter(c -> !list.contains(c));
            .collect(Collectors.toList());
tobsob
  • 602
  • 9
  • 22
  • I tried this one, but I have to put it back to the map again. I think the solution given by Deadpool looks neat and clean. – RoyalTiger Jul 30 '19 at 09:39