简体   繁体   中英

Remove elements from hashset inside hashmap while iterating through java stream

I have a hashmap in Java with a string key and a HashSet value. The hashset may contain many PlacementBundles inside it.

public Map<String, Set<PlacementBundle>> placementByConcept;

I am trying to remove the value from the HashSet while iterating the map which matches a specific condition.

I tried the below code but cannot remove the matching element from the HashSet.

placementByConcept.entrySet()
                  .stream()
                  .map(e -> e.getValue()
                             .removeIf(s -> s.getBeatObjectiveId().equals("non-scored")));

you can use forEach:

placementByConcept.entrySet().forEach(e -> e.getValue().removeIf(s -> s.getBeatObjectiveId().equals("non-scored")));

In your case Set<PlacementBundle> is an immutable collection. You can't remove an element from it. If you use foreach as suggested in the accepted answer, you will get UnsupportedOperationException

import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
public class Test {

    public static void main(String[] args) {
        Map<String, Set<PlacementBundle>> placementByConcept = new HashMap<>();
        placementByConcept.put("concept1", Set.of(
                PlacementBundle.builder().beatObjectiveId("scored").build(),
                PlacementBundle.builder().beatObjectiveId("non-scored").build())
        );
        placementByConcept.put("concept2", Set.of(
                PlacementBundle.builder().beatObjectiveId("scored").build(),
                PlacementBundle.builder().beatObjectiveId("non-scored").build())
        );

        log.info("Original: {}", placementByConcept);

        /* This won't give any exception, neither will remove the entries */
        placementByConcept.entrySet()
                          .stream()
                          .map(e -> e.getValue()
                                     .removeIf(s -> s.getBeatObjectiveId().equals("non-scored")));
        log.info("Does not work: {}", placementByConcept);

        /* This will give you the exception UnsupportedOperationException */
        // placementByConcept.entrySet().forEach(e -> e.getValue().removeIf(s -> s.getBeatObjectiveId().equals("non-scored")));

        /* This is one of the correct way */
        for (Map.Entry<String, Set<PlacementBundle>> entry : placementByConcept.entrySet()) {
            var filtered = entry.getValue().stream()
                    .filter(placementBundle -> !placementBundle.getBeatObjectiveId().equals("non-scored"))
                    .collect(Collectors.toUnmodifiableSet());
            log.debug("New Value Set: {}", filtered);
            entry.setValue(filtered);
        }

        log.info("After: {}", placementByConcept);
    }

}

@Builder
@Data
class PlacementBundle {
    private String beatObjectiveId;
}

Output:

Original: {concept2=[PlacementBundle(beatObjectiveId=scored), PlacementBundle(beatObjectiveId=non-scored)], concept1=[PlacementBundle(beatObjectiveId=scored), PlacementBundle(beatObjectiveId=non-scored)]}

Does not work: {concept2=[PlacementBundle(beatObjectiveId=scored), PlacementBundle(beatObjectiveId=non-scored)], concept1=[PlacementBundle(beatObjectiveId=scored), PlacementBundle(beatObjectiveId=non-scored)]}

After: {concept2=[PlacementBundle(beatObjectiveId=scored)], concept1=[PlacementBundle(beatObjectiveId=scored)]}
public class Remove {
    public static void main(String[] args)
    {
        HashMap<Integer, String>
            map = new HashMap<>();

        map.put(1, "Stack");
        map.put(2, "Overflow");
        map.put(3, "StackOverflow");

        int keyToBeRemoved = 2;

        System.out.println("Original HashMap: "
                        + map);

        map.entrySet()
            .removeIf(
                entry -> (keyToBeRemoved == entry.getKey()));

        System.out.println("New HashMap: "
                        + map);
    }
}

Output:

Original HashMap: {1=Stack, 2=Overflow, 3=StackOverflow}
New HashMap: {1=Stack, 3=StackOverflow}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM