How to remove multiple elements from Set/Map AND knowing which ones were removed?In Java streams is peek really only for debugging?Possible side effect of Stream.peek changing state and why not use it like thisHow do I remove repeated elements from ArrayList?Trying to understand lambda and stream in Java 8How to map to multiple elements with Java 8 streams?Java Lambda expression to avoid multiple iterationsRe-using a stream in Java 8Java Lambda in Intellij: Expected not null but the lambda body is not value-compatibleIs it possible to get the index of ArrayList<Object> when using Java8 Streams?How to call a lambda on each element of a list and get the result in a new list? My working version is too verboseJava 8 Streams - Remove item from nested list based on other listBuild a list of maximum values from a set of lists nested inside nested maps with lambda

At zero velocity, is this object neither speeding up nor slowing down?

Arcane Tradition and Cost Efficiency: Learn spells on level-up, or learn them from scrolls/spellbooks?

How did the European Union reach the figure of 3% as a maximum allowed deficit?

Background for black and white chart

How did Avada Kedavra get its name?

What does the output current rating from an H-Bridge's datasheet really mean?

Can an escape pod land on Earth from orbit and not be immediately detected?

How to remove multiple elements from Set/Map AND knowing which ones were removed?

Can Dive Down protect a creature against Pacifism?

How to make a villain when your PCs are villains?

How do credit card companies know what type of business I'm paying for?

Nth term of Van Eck Sequence

Idiom for 'person who gets violent when drunk"

Is it unethical to quit my job during company crisis?

My parents claim they cannot pay for my college education; what are my options?

Are soroban (Japanese abacus) classes worth doing?

How to ask if I can mow my neighbor's lawn

Is it possible to install Firefox on Ubuntu with no desktop enviroment?

How many times to repeat an event with known probability before it has occurred a number of times

Difference between "drift" and "wander"

How do I say what something is made out of?

Converting 3x7 to a 1x7. Is it possible with only existing parts?

Is it possible to have battery technology that can't be duplicated?

How to avoid offending original culture when making conculture inspired from original



How to remove multiple elements from Set/Map AND knowing which ones were removed?


In Java streams is peek really only for debugging?Possible side effect of Stream.peek changing state and why not use it like thisHow do I remove repeated elements from ArrayList?Trying to understand lambda and stream in Java 8How to map to multiple elements with Java 8 streams?Java Lambda expression to avoid multiple iterationsRe-using a stream in Java 8Java Lambda in Intellij: Expected not null but the lambda body is not value-compatibleIs it possible to get the index of ArrayList<Object> when using Java8 Streams?How to call a lambda on each element of a list and get the result in a new list? My working version is too verboseJava 8 Streams - Remove item from nested list based on other listBuild a list of maximum values from a set of lists nested inside nested maps with lambda






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








12















I have a method that has to remove all elements found in a (small) Set<K> keysToRemove from some (potentially large) Map<K,V> from. But removeAll() doesn't do, as I need to return all keys that were actually removed.



Old-school code is straight forward:



public Set<K> removeEntries(Map<K, V> from) 
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for (K keyToRemove : keysToRemove)
if (fromKeys.contains(keyToRemove))
fromKeys.remove(keyToRemove);
removedKeys.add(keyToRemove);


return removedKeys;



The same, written using streams:



Set<K> fromKeys = from.keySet();
return keysToRemove.stream()
.filter(fromKeys::contains)
.map(k ->
fromKeys.remove(k);
return k;
)
.collect(Collectors.toSet());


I find that a bit more concise, but I also find that lambda too clunky.



Any suggestions how to achieve the same result in less clumsy ways?










share|improve this question

















  • 1





    How about just collecting all keys that can be removed and then call removeAll() on that filtered set? Or how about "filtering" on fromKeys::remove?

    – Thomas
    12 hours ago












  • @Thomas Slightly less clumsy, but still an extra call. And well, the stream() operation itself is expensive enough, so it ought as well do all the work ;-)

    – GhostCat
    11 hours ago











  • I believe and inferring from the answers here, the improvement that comes mostly out of any change is by using if (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove); instead of using both contains and remove in if (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);

    – Naman
    9 hours ago


















12















I have a method that has to remove all elements found in a (small) Set<K> keysToRemove from some (potentially large) Map<K,V> from. But removeAll() doesn't do, as I need to return all keys that were actually removed.



Old-school code is straight forward:



public Set<K> removeEntries(Map<K, V> from) 
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for (K keyToRemove : keysToRemove)
if (fromKeys.contains(keyToRemove))
fromKeys.remove(keyToRemove);
removedKeys.add(keyToRemove);


return removedKeys;



The same, written using streams:



Set<K> fromKeys = from.keySet();
return keysToRemove.stream()
.filter(fromKeys::contains)
.map(k ->
fromKeys.remove(k);
return k;
)
.collect(Collectors.toSet());


I find that a bit more concise, but I also find that lambda too clunky.



Any suggestions how to achieve the same result in less clumsy ways?










share|improve this question

















  • 1





    How about just collecting all keys that can be removed and then call removeAll() on that filtered set? Or how about "filtering" on fromKeys::remove?

    – Thomas
    12 hours ago












  • @Thomas Slightly less clumsy, but still an extra call. And well, the stream() operation itself is expensive enough, so it ought as well do all the work ;-)

    – GhostCat
    11 hours ago











  • I believe and inferring from the answers here, the improvement that comes mostly out of any change is by using if (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove); instead of using both contains and remove in if (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);

    – Naman
    9 hours ago














12












12








12


1






I have a method that has to remove all elements found in a (small) Set<K> keysToRemove from some (potentially large) Map<K,V> from. But removeAll() doesn't do, as I need to return all keys that were actually removed.



Old-school code is straight forward:



public Set<K> removeEntries(Map<K, V> from) 
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for (K keyToRemove : keysToRemove)
if (fromKeys.contains(keyToRemove))
fromKeys.remove(keyToRemove);
removedKeys.add(keyToRemove);


return removedKeys;



The same, written using streams:



Set<K> fromKeys = from.keySet();
return keysToRemove.stream()
.filter(fromKeys::contains)
.map(k ->
fromKeys.remove(k);
return k;
)
.collect(Collectors.toSet());


I find that a bit more concise, but I also find that lambda too clunky.



Any suggestions how to achieve the same result in less clumsy ways?










share|improve this question














I have a method that has to remove all elements found in a (small) Set<K> keysToRemove from some (potentially large) Map<K,V> from. But removeAll() doesn't do, as I need to return all keys that were actually removed.



Old-school code is straight forward:



public Set<K> removeEntries(Map<K, V> from) 
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for (K keyToRemove : keysToRemove)
if (fromKeys.contains(keyToRemove))
fromKeys.remove(keyToRemove);
removedKeys.add(keyToRemove);


return removedKeys;



The same, written using streams:



Set<K> fromKeys = from.keySet();
return keysToRemove.stream()
.filter(fromKeys::contains)
.map(k ->
fromKeys.remove(k);
return k;
)
.collect(Collectors.toSet());


I find that a bit more concise, but I also find that lambda too clunky.



Any suggestions how to achieve the same result in less clumsy ways?







java lambda java-8 java-stream






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 12 hours ago









GhostCatGhostCat

103k1797174




103k1797174







  • 1





    How about just collecting all keys that can be removed and then call removeAll() on that filtered set? Or how about "filtering" on fromKeys::remove?

    – Thomas
    12 hours ago












  • @Thomas Slightly less clumsy, but still an extra call. And well, the stream() operation itself is expensive enough, so it ought as well do all the work ;-)

    – GhostCat
    11 hours ago











  • I believe and inferring from the answers here, the improvement that comes mostly out of any change is by using if (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove); instead of using both contains and remove in if (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);

    – Naman
    9 hours ago













  • 1





    How about just collecting all keys that can be removed and then call removeAll() on that filtered set? Or how about "filtering" on fromKeys::remove?

    – Thomas
    12 hours ago












  • @Thomas Slightly less clumsy, but still an extra call. And well, the stream() operation itself is expensive enough, so it ought as well do all the work ;-)

    – GhostCat
    11 hours ago











  • I believe and inferring from the answers here, the improvement that comes mostly out of any change is by using if (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove); instead of using both contains and remove in if (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);

    – Naman
    9 hours ago








1




1





How about just collecting all keys that can be removed and then call removeAll() on that filtered set? Or how about "filtering" on fromKeys::remove?

– Thomas
12 hours ago






How about just collecting all keys that can be removed and then call removeAll() on that filtered set? Or how about "filtering" on fromKeys::remove?

– Thomas
12 hours ago














@Thomas Slightly less clumsy, but still an extra call. And well, the stream() operation itself is expensive enough, so it ought as well do all the work ;-)

– GhostCat
11 hours ago





@Thomas Slightly less clumsy, but still an extra call. And well, the stream() operation itself is expensive enough, so it ought as well do all the work ;-)

– GhostCat
11 hours ago













I believe and inferring from the answers here, the improvement that comes mostly out of any change is by using if (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove); instead of using both contains and remove in if (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);

– Naman
9 hours ago






I believe and inferring from the answers here, the improvement that comes mostly out of any change is by using if (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove); instead of using both contains and remove in if (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);

– Naman
9 hours ago













6 Answers
6






active

oldest

votes


















9














The “old-school code” should rather be



public Set<K> removeEntries(Map<K, ?> from) 
Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
removedKeys.retainAll(fromKeys);
fromKeys.removeAll(removedKeys);
return removedKeys;



Since you said that keysToRemove is rather small, the copying overhead likely doesn’t matter. Otherwise, use the loop, but don’t do the hash lookup twice:



public Set<K> removeEntries(Map<K, ?> from) 
Set<K> fromKeys = from.keySet();
Set<K> removedKeys = new HashSet<>();
for(K keyToRemove : keysToRemove)
if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
return removedKeys;



You can express the same logic as a stream as



public Set<K> removeEntries(Map<K, ?> from) 
return keysToRemove.stream()
.filter(from.keySet()::remove)
.collect(Collectors.toSet());



but since this is a stateful filter, it is highly discouraged. A cleaner variant would be



public Set<K> removeEntries(Map<K, ?> from) 
Set<K> result = keysToRemove.stream()
.filter(from.keySet()::contains)
.collect(Collectors.toSet());
from.keySet().removeAll(result);
return result;



and if you want to maximize the “streamy” usage, you can replace from.keySet().removeAll(result); with from.keySet().removeIf(result::contains), which is quiet expensive, as it is iterating over the larger map, or with result.forEach(from.keySet()::remove), which doesn’t have that disadvantage, but still, isn’t more readable than removeAll.



All in all, the “old-school code” is much better than that.






share|improve this answer























  • Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

    – Naman
    9 hours ago












  • @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

    – Holger
    8 hours ago











  • Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

    – Naman
    8 hours ago






  • 1





    @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

    – Holger
    8 hours ago



















9














More concise solution, but still with unwanted side effect in the filter call:



Set<K> removedKeys =
keysToRemove.stream()
.filter(fromKeys::remove)
.collect(Collectors.toSet());


Set.remove already returns true if the set contained the specified element.



 P.S. In the end, I would probably stick with the "old-school code".






share|improve this answer




















  • 4





    Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

    – Thomas
    12 hours ago


















4














I wouldn’t use Streams for this. I would take advantage of retainAll:



public Set<K> removeEntries(Map<K, V> from) 
Set<K> matchingKeys = new HashSet<>(from.keySet());
matchingKeys.retainAll(keysToRemove);

from.keySet().removeAll(matchingKeys);

return matchingKeys;






share|improve this answer




















  • 2





    That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

    – Holger
    10 hours ago











  • @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

    – VGR
    10 hours ago






  • 2





    It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

    – Holger
    10 hours ago


















3














You can use the stream and the removeAll



Set<K> fromKeys = from.keySet();
Set<K> removedKeys = keysToRemove.stream()
.filter(fromKeys::contains)
.collect(Collectors.toSet());
fromKeys.removeAll(removedKeys);
return removedKeys;





share|improve this answer






























    3














    You can use this:



    Set<K> removedKeys = keysToRemove.stream()
    .filter(from::containsKey)
    .collect(Collectors.toSet());
    removedKeys.forEach(from::remove);


    It's similar to Oleksandr's answer, but avoiding the side effect. But I would stick with that answer, if you are looking for performance.



    Alternatively you could use Stream.peek() for the remove, but be careful with other side effects (see the comments). So I would not recommend that.



    Set<K> removedKeys = keysToRemove.stream()
    .filter(from::containsKey)
    .peek(from::remove)
    .collect(Collectors.toSet());





    share|improve this answer




















    • 5





      Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

      – Michael A. Schaffrath
      11 hours ago






    • 2





      @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

      – GhostCat
      11 hours ago






    • 4





      Or more general general: In Java streams is peek really only for debugging?

      – Holger
      10 hours ago


















    2














    To add another variant to the approaches, one could also partition the keys and return the required Set as:



    public Set<K> removeEntries(Map<K, ?> from) 
    Map<Boolean, Set<K>> partitioned = keysToRemove.stream()
    .collect(Collectors.partitioningBy(k -> from.keySet().remove(k),
    Collectors.toSet()));
    return partitioned.get(Boolean.TRUE);






    share|improve this answer























    • Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

      – Naman
      9 hours ago











    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56582681%2fhow-to-remove-multiple-elements-from-set-map-and-knowing-which-ones-were-removed%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    6 Answers
    6






    active

    oldest

    votes








    6 Answers
    6






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    9














    The “old-school code” should rather be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
    removedKeys.retainAll(fromKeys);
    fromKeys.removeAll(removedKeys);
    return removedKeys;



    Since you said that keysToRemove is rather small, the copying overhead likely doesn’t matter. Otherwise, use the loop, but don’t do the hash lookup twice:



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = new HashSet<>();
    for(K keyToRemove : keysToRemove)
    if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
    return removedKeys;



    You can express the same logic as a stream as



    public Set<K> removeEntries(Map<K, ?> from) 
    return keysToRemove.stream()
    .filter(from.keySet()::remove)
    .collect(Collectors.toSet());



    but since this is a stateful filter, it is highly discouraged. A cleaner variant would be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> result = keysToRemove.stream()
    .filter(from.keySet()::contains)
    .collect(Collectors.toSet());
    from.keySet().removeAll(result);
    return result;



    and if you want to maximize the “streamy” usage, you can replace from.keySet().removeAll(result); with from.keySet().removeIf(result::contains), which is quiet expensive, as it is iterating over the larger map, or with result.forEach(from.keySet()::remove), which doesn’t have that disadvantage, but still, isn’t more readable than removeAll.



    All in all, the “old-school code” is much better than that.






    share|improve this answer























    • Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

      – Naman
      9 hours ago












    • @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

      – Holger
      8 hours ago











    • Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

      – Naman
      8 hours ago






    • 1





      @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

      – Holger
      8 hours ago
















    9














    The “old-school code” should rather be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
    removedKeys.retainAll(fromKeys);
    fromKeys.removeAll(removedKeys);
    return removedKeys;



    Since you said that keysToRemove is rather small, the copying overhead likely doesn’t matter. Otherwise, use the loop, but don’t do the hash lookup twice:



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = new HashSet<>();
    for(K keyToRemove : keysToRemove)
    if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
    return removedKeys;



    You can express the same logic as a stream as



    public Set<K> removeEntries(Map<K, ?> from) 
    return keysToRemove.stream()
    .filter(from.keySet()::remove)
    .collect(Collectors.toSet());



    but since this is a stateful filter, it is highly discouraged. A cleaner variant would be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> result = keysToRemove.stream()
    .filter(from.keySet()::contains)
    .collect(Collectors.toSet());
    from.keySet().removeAll(result);
    return result;



    and if you want to maximize the “streamy” usage, you can replace from.keySet().removeAll(result); with from.keySet().removeIf(result::contains), which is quiet expensive, as it is iterating over the larger map, or with result.forEach(from.keySet()::remove), which doesn’t have that disadvantage, but still, isn’t more readable than removeAll.



    All in all, the “old-school code” is much better than that.






    share|improve this answer























    • Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

      – Naman
      9 hours ago












    • @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

      – Holger
      8 hours ago











    • Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

      – Naman
      8 hours ago






    • 1





      @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

      – Holger
      8 hours ago














    9












    9








    9







    The “old-school code” should rather be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
    removedKeys.retainAll(fromKeys);
    fromKeys.removeAll(removedKeys);
    return removedKeys;



    Since you said that keysToRemove is rather small, the copying overhead likely doesn’t matter. Otherwise, use the loop, but don’t do the hash lookup twice:



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = new HashSet<>();
    for(K keyToRemove : keysToRemove)
    if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
    return removedKeys;



    You can express the same logic as a stream as



    public Set<K> removeEntries(Map<K, ?> from) 
    return keysToRemove.stream()
    .filter(from.keySet()::remove)
    .collect(Collectors.toSet());



    but since this is a stateful filter, it is highly discouraged. A cleaner variant would be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> result = keysToRemove.stream()
    .filter(from.keySet()::contains)
    .collect(Collectors.toSet());
    from.keySet().removeAll(result);
    return result;



    and if you want to maximize the “streamy” usage, you can replace from.keySet().removeAll(result); with from.keySet().removeIf(result::contains), which is quiet expensive, as it is iterating over the larger map, or with result.forEach(from.keySet()::remove), which doesn’t have that disadvantage, but still, isn’t more readable than removeAll.



    All in all, the “old-school code” is much better than that.






    share|improve this answer













    The “old-school code” should rather be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet(), removedKeys = new HashSet<>(keysToRemove);
    removedKeys.retainAll(fromKeys);
    fromKeys.removeAll(removedKeys);
    return removedKeys;



    Since you said that keysToRemove is rather small, the copying overhead likely doesn’t matter. Otherwise, use the loop, but don’t do the hash lookup twice:



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = new HashSet<>();
    for(K keyToRemove : keysToRemove)
    if(fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
    return removedKeys;



    You can express the same logic as a stream as



    public Set<K> removeEntries(Map<K, ?> from) 
    return keysToRemove.stream()
    .filter(from.keySet()::remove)
    .collect(Collectors.toSet());



    but since this is a stateful filter, it is highly discouraged. A cleaner variant would be



    public Set<K> removeEntries(Map<K, ?> from) 
    Set<K> result = keysToRemove.stream()
    .filter(from.keySet()::contains)
    .collect(Collectors.toSet());
    from.keySet().removeAll(result);
    return result;



    and if you want to maximize the “streamy” usage, you can replace from.keySet().removeAll(result); with from.keySet().removeIf(result::contains), which is quiet expensive, as it is iterating over the larger map, or with result.forEach(from.keySet()::remove), which doesn’t have that disadvantage, but still, isn’t more readable than removeAll.



    All in all, the “old-school code” is much better than that.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 10 hours ago









    HolgerHolger

    177k24254481




    177k24254481












    • Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

      – Naman
      9 hours ago












    • @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

      – Holger
      8 hours ago











    • Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

      – Naman
      8 hours ago






    • 1





      @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

      – Holger
      8 hours ago


















    • Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

      – Naman
      9 hours ago












    • @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

      – Holger
      8 hours ago











    • Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

      – Naman
      8 hours ago






    • 1





      @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

      – Holger
      8 hours ago

















    Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

    – Naman
    9 hours ago






    Was working around with the existing code. Wouldn't public Set<K> removeEntries(Map<K, ?> from) Set<K> removedKeys = new HashSet<>(); for (K keyToRemove : keysToRemove) if (from.keySet().remove(keyToRemove)) removedKeys.add(keyToRemove); return removedKeys; be a better old school code than the retainAll, removeAll solution. I meant to be focussing(nitpicking) on the single iteration versus two iterations with their implementation. (I might just be wrong though in inferring so.)

    – Naman
    9 hours ago














    @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

    – Holger
    8 hours ago





    @Naman that’s what I posted as second variant, right for the case that the iteration matters. However, the retainAll/removeAll combo will iterate over the set that has been specified by the OP as being rather small.

    – Holger
    8 hours ago













    Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

    – Naman
    8 hours ago





    Oh, yes the second variant indeed is the same. But wouldn't the removeAll iterate the fromKeys instead of keysToRemove there? About the first stream variant, how about using the predicate for reduction using partitioningBy, wrote a sample code?

    – Naman
    8 hours ago




    1




    1





    @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

    – Holger
    8 hours ago






    @Naman that’s hitting implementation details, but I assume that it works like AbstractSet.removeAll(…), if not even inheriting right that method: “This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. …[etc]”. Using a stateful predicate for partitioningBy is as discouraged as for filter, but with the latter, you’re collection another set of actually unwanted elements…

    – Holger
    8 hours ago














    9














    More concise solution, but still with unwanted side effect in the filter call:



    Set<K> removedKeys =
    keysToRemove.stream()
    .filter(fromKeys::remove)
    .collect(Collectors.toSet());


    Set.remove already returns true if the set contained the specified element.



     P.S. In the end, I would probably stick with the "old-school code".






    share|improve this answer




















    • 4





      Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

      – Thomas
      12 hours ago















    9














    More concise solution, but still with unwanted side effect in the filter call:



    Set<K> removedKeys =
    keysToRemove.stream()
    .filter(fromKeys::remove)
    .collect(Collectors.toSet());


    Set.remove already returns true if the set contained the specified element.



     P.S. In the end, I would probably stick with the "old-school code".






    share|improve this answer




















    • 4





      Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

      – Thomas
      12 hours ago













    9












    9








    9







    More concise solution, but still with unwanted side effect in the filter call:



    Set<K> removedKeys =
    keysToRemove.stream()
    .filter(fromKeys::remove)
    .collect(Collectors.toSet());


    Set.remove already returns true if the set contained the specified element.



     P.S. In the end, I would probably stick with the "old-school code".






    share|improve this answer















    More concise solution, but still with unwanted side effect in the filter call:



    Set<K> removedKeys =
    keysToRemove.stream()
    .filter(fromKeys::remove)
    .collect(Collectors.toSet());


    Set.remove already returns true if the set contained the specified element.



     P.S. In the end, I would probably stick with the "old-school code".







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 6 hours ago

























    answered 12 hours ago









    OleksandrOleksandr

    10.3k44474




    10.3k44474







    • 4





      Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

      – Thomas
      12 hours ago












    • 4





      Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

      – Thomas
      12 hours ago







    4




    4





    Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

    – Thomas
    12 hours ago





    Exactly my thought ;) - It just feels a little hacky because we're "filtering" on a method that actually represents a side effect.

    – Thomas
    12 hours ago











    4














    I wouldn’t use Streams for this. I would take advantage of retainAll:



    public Set<K> removeEntries(Map<K, V> from) 
    Set<K> matchingKeys = new HashSet<>(from.keySet());
    matchingKeys.retainAll(keysToRemove);

    from.keySet().removeAll(matchingKeys);

    return matchingKeys;






    share|improve this answer




















    • 2





      That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

      – Holger
      10 hours ago











    • @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

      – VGR
      10 hours ago






    • 2





      It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

      – Holger
      10 hours ago















    4














    I wouldn’t use Streams for this. I would take advantage of retainAll:



    public Set<K> removeEntries(Map<K, V> from) 
    Set<K> matchingKeys = new HashSet<>(from.keySet());
    matchingKeys.retainAll(keysToRemove);

    from.keySet().removeAll(matchingKeys);

    return matchingKeys;






    share|improve this answer




















    • 2





      That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

      – Holger
      10 hours ago











    • @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

      – VGR
      10 hours ago






    • 2





      It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

      – Holger
      10 hours ago













    4












    4








    4







    I wouldn’t use Streams for this. I would take advantage of retainAll:



    public Set<K> removeEntries(Map<K, V> from) 
    Set<K> matchingKeys = new HashSet<>(from.keySet());
    matchingKeys.retainAll(keysToRemove);

    from.keySet().removeAll(matchingKeys);

    return matchingKeys;






    share|improve this answer















    I wouldn’t use Streams for this. I would take advantage of retainAll:



    public Set<K> removeEntries(Map<K, V> from) 
    Set<K> matchingKeys = new HashSet<>(from.keySet());
    matchingKeys.retainAll(keysToRemove);

    from.keySet().removeAll(matchingKeys);

    return matchingKeys;







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 10 hours ago

























    answered 11 hours ago









    VGRVGR

    24.7k42941




    24.7k42941







    • 2





      That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

      – Holger
      10 hours ago











    • @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

      – VGR
      10 hours ago






    • 2





      It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

      – Holger
      10 hours ago












    • 2





      That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

      – Holger
      10 hours ago











    • @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

      – VGR
      10 hours ago






    • 2





      It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

      – Holger
      10 hours ago







    2




    2





    That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

    – Holger
    10 hours ago





    That’s pointing into the right direction, but you are copying the “potentially large” from map’s keyset whereas you can copy the “small” keysToRemove instead, as the intersection of a and b is the same as of b and a. Further, matchingKeys is potentially smaller than keysToRemove, so removeAll(matchingKeys) is preferable.

    – Holger
    10 hours ago













    @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

    – VGR
    10 hours ago





    @Holger I see your point, but the Set is merely copying references, which seems benign to me, unless the Map’s size is truly huge. You’re right about removeAll(matchingKeys) though. Updated.

    – VGR
    10 hours ago




    2




    2





    It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

    – Holger
    10 hours ago





    It’s not just copying references, but hashing. And since the OP stated the expected sizes and swapping the two is trivial, I’d do this. In fact, I did.

    – Holger
    10 hours ago











    3














    You can use the stream and the removeAll



    Set<K> fromKeys = from.keySet();
    Set<K> removedKeys = keysToRemove.stream()
    .filter(fromKeys::contains)
    .collect(Collectors.toSet());
    fromKeys.removeAll(removedKeys);
    return removedKeys;





    share|improve this answer



























      3














      You can use the stream and the removeAll



      Set<K> fromKeys = from.keySet();
      Set<K> removedKeys = keysToRemove.stream()
      .filter(fromKeys::contains)
      .collect(Collectors.toSet());
      fromKeys.removeAll(removedKeys);
      return removedKeys;





      share|improve this answer

























        3












        3








        3







        You can use the stream and the removeAll



        Set<K> fromKeys = from.keySet();
        Set<K> removedKeys = keysToRemove.stream()
        .filter(fromKeys::contains)
        .collect(Collectors.toSet());
        fromKeys.removeAll(removedKeys);
        return removedKeys;





        share|improve this answer













        You can use the stream and the removeAll



        Set<K> fromKeys = from.keySet();
        Set<K> removedKeys = keysToRemove.stream()
        .filter(fromKeys::contains)
        .collect(Collectors.toSet());
        fromKeys.removeAll(removedKeys);
        return removedKeys;






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 12 hours ago









        MaanooAkMaanooAk

        1,339821




        1,339821





















            3














            You can use this:



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .collect(Collectors.toSet());
            removedKeys.forEach(from::remove);


            It's similar to Oleksandr's answer, but avoiding the side effect. But I would stick with that answer, if you are looking for performance.



            Alternatively you could use Stream.peek() for the remove, but be careful with other side effects (see the comments). So I would not recommend that.



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .peek(from::remove)
            .collect(Collectors.toSet());





            share|improve this answer




















            • 5





              Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

              – Michael A. Schaffrath
              11 hours ago






            • 2





              @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

              – GhostCat
              11 hours ago






            • 4





              Or more general general: In Java streams is peek really only for debugging?

              – Holger
              10 hours ago















            3














            You can use this:



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .collect(Collectors.toSet());
            removedKeys.forEach(from::remove);


            It's similar to Oleksandr's answer, but avoiding the side effect. But I would stick with that answer, if you are looking for performance.



            Alternatively you could use Stream.peek() for the remove, but be careful with other side effects (see the comments). So I would not recommend that.



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .peek(from::remove)
            .collect(Collectors.toSet());





            share|improve this answer




















            • 5





              Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

              – Michael A. Schaffrath
              11 hours ago






            • 2





              @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

              – GhostCat
              11 hours ago






            • 4





              Or more general general: In Java streams is peek really only for debugging?

              – Holger
              10 hours ago













            3












            3








            3







            You can use this:



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .collect(Collectors.toSet());
            removedKeys.forEach(from::remove);


            It's similar to Oleksandr's answer, but avoiding the side effect. But I would stick with that answer, if you are looking for performance.



            Alternatively you could use Stream.peek() for the remove, but be careful with other side effects (see the comments). So I would not recommend that.



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .peek(from::remove)
            .collect(Collectors.toSet());





            share|improve this answer















            You can use this:



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .collect(Collectors.toSet());
            removedKeys.forEach(from::remove);


            It's similar to Oleksandr's answer, but avoiding the side effect. But I would stick with that answer, if you are looking for performance.



            Alternatively you could use Stream.peek() for the remove, but be careful with other side effects (see the comments). So I would not recommend that.



            Set<K> removedKeys = keysToRemove.stream()
            .filter(from::containsKey)
            .peek(from::remove)
            .collect(Collectors.toSet());






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 7 hours ago

























            answered 11 hours ago









            Samuel PhilippSamuel Philipp

            6,29181635




            6,29181635







            • 5





              Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

              – Michael A. Schaffrath
              11 hours ago






            • 2





              @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

              – GhostCat
              11 hours ago






            • 4





              Or more general general: In Java streams is peek really only for debugging?

              – Holger
              10 hours ago












            • 5





              Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

              – Michael A. Schaffrath
              11 hours ago






            • 2





              @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

              – GhostCat
              11 hours ago






            • 4





              Or more general general: In Java streams is peek really only for debugging?

              – Holger
              10 hours ago







            5




            5





            Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

            – Michael A. Schaffrath
            11 hours ago





            Never use peek for anything other than debugging! See stackoverflow.com/questions/47356992/… and the questions linked in it

            – Michael A. Schaffrath
            11 hours ago




            2




            2





            @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

            – GhostCat
            11 hours ago





            @MichaelA.Schaffrath Makes perfect sense. Fun fact: I tried my initial lambda again, with map. IntelliJ suggests to replace that call to map() to peek() ;-)

            – GhostCat
            11 hours ago




            4




            4





            Or more general general: In Java streams is peek really only for debugging?

            – Holger
            10 hours ago





            Or more general general: In Java streams is peek really only for debugging?

            – Holger
            10 hours ago











            2














            To add another variant to the approaches, one could also partition the keys and return the required Set as:



            public Set<K> removeEntries(Map<K, ?> from) 
            Map<Boolean, Set<K>> partitioned = keysToRemove.stream()
            .collect(Collectors.partitioningBy(k -> from.keySet().remove(k),
            Collectors.toSet()));
            return partitioned.get(Boolean.TRUE);






            share|improve this answer























            • Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

              – Naman
              9 hours ago















            2














            To add another variant to the approaches, one could also partition the keys and return the required Set as:



            public Set<K> removeEntries(Map<K, ?> from) 
            Map<Boolean, Set<K>> partitioned = keysToRemove.stream()
            .collect(Collectors.partitioningBy(k -> from.keySet().remove(k),
            Collectors.toSet()));
            return partitioned.get(Boolean.TRUE);






            share|improve this answer























            • Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

              – Naman
              9 hours ago













            2












            2








            2







            To add another variant to the approaches, one could also partition the keys and return the required Set as:



            public Set<K> removeEntries(Map<K, ?> from) 
            Map<Boolean, Set<K>> partitioned = keysToRemove.stream()
            .collect(Collectors.partitioningBy(k -> from.keySet().remove(k),
            Collectors.toSet()));
            return partitioned.get(Boolean.TRUE);






            share|improve this answer













            To add another variant to the approaches, one could also partition the keys and return the required Set as:



            public Set<K> removeEntries(Map<K, ?> from) 
            Map<Boolean, Set<K>> partitioned = keysToRemove.stream()
            .collect(Collectors.partitioningBy(k -> from.keySet().remove(k),
            Collectors.toSet()));
            return partitioned.get(Boolean.TRUE);







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 9 hours ago









            NamanNaman

            48.7k13105209




            48.7k13105209












            • Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

              – Naman
              9 hours ago

















            • Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

              – Naman
              9 hours ago
















            Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

            – Naman
            9 hours ago





            Also leaves a choice of using the keys that were not a part of the keySet of the map. (just in case)

            – Naman
            9 hours ago

















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56582681%2fhow-to-remove-multiple-elements-from-set-map-and-knowing-which-ones-were-removed%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

            Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

            Tom Holland Mục lục Đầu đời và giáo dục | Sự nghiệp | Cuộc sống cá nhân | Phim tham gia | Giải thưởng và đề cử | Chú thích | Liên kết ngoài | Trình đơn chuyển hướngProfile“Person Details for Thomas Stanley Holland, "England and Wales Birth Registration Index, 1837-2008" — FamilySearch.org”"Meet Tom Holland... the 16-year-old star of The Impossible""Schoolboy actor Tom Holland finds himself in Oscar contention for role in tsunami drama"“Naomi Watts on the Prince William and Harry's reaction to her film about the late Princess Diana”lưu trữ"Holland and Pflueger Are West End's Two New 'Billy Elliots'""I'm so envious of my son, the movie star! British writer Dominic Holland's spent 20 years trying to crack Hollywood - but he's been beaten to it by a very unlikely rival"“Richard and Margaret Povey of Jersey, Channel Islands, UK: Information about Thomas Stanley Holland”"Tom Holland to play Billy Elliot""New Billy Elliot leaving the garage"Billy Elliot the Musical - Tom Holland - Billy"A Tale of four Billys: Tom Holland""The Feel Good Factor""Thames Christian College schoolboys join Myleene Klass for The Feelgood Factor""Government launches £600,000 arts bursaries pilot""BILLY's Chapman, Holland, Gardner & Jackson-Keen Visit Prime Minister""Elton John 'blown away' by Billy Elliot fifth birthday" (video with John's interview and fragments of Holland's performance)"First News interviews Arrietty's Tom Holland"“33rd Critics' Circle Film Awards winners”“National Board of Review Current Awards”Bản gốc"Ron Howard Whaling Tale 'In The Heart Of The Sea' Casts Tom Holland"“'Spider-Man' Finds Tom Holland to Star as New Web-Slinger”lưu trữ“Captain America: Civil War (2016)”“Film Review: ‘Captain America: Civil War’”lưu trữ“‘Captain America: Civil War’ review: Choose your own avenger”lưu trữ“The Lost City of Z reviews”“Sony Pictures and Marvel Studios Find Their 'Spider-Man' Star and Director”“‘Mary Magdalene’, ‘Current War’ & ‘Wind River’ Get 2017 Release Dates From Weinstein”“Lionsgate Unleashing Daisy Ridley & Tom Holland Starrer ‘Chaos Walking’ In Cannes”“PTA's 'Master' Leads Chicago Film Critics Nominations, UPDATED: Houston and Indiana Critics Nominations”“Nominaciones Goya 2013 Telecinco Cinema – ENG”“Jameson Empire Film Awards: Martin Freeman wins best actor for performance in The Hobbit”“34th Annual Young Artist Awards”Bản gốc“Teen Choice Awards 2016—Captain America: Civil War Leads Second Wave of Nominations”“BAFTA Film Award Nominations: ‘La La Land’ Leads Race”“Saturn Awards Nominations 2017: 'Rogue One,' 'Walking Dead' Lead”Tom HollandTom HollandTom HollandTom Hollandmedia.gettyimages.comWorldCat Identities300279794no20130442900000 0004 0355 42791085670554170004732cb16706349t(data)XX5557367