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;
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
add a comment |
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
1
How about just collecting all keys that can be removed and then callremoveAll()
on that filtered set? Or how about "filtering" onfromKeys::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 usingif (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
instead of using both contains and remove inif (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);
– Naman
9 hours ago
add a comment |
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
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
java lambda java-8 java-stream
asked 12 hours ago
GhostCatGhostCat
103k1797174
103k1797174
1
How about just collecting all keys that can be removed and then callremoveAll()
on that filtered set? Or how about "filtering" onfromKeys::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 usingif (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
instead of using both contains and remove inif (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);
– Naman
9 hours ago
add a comment |
1
How about just collecting all keys that can be removed and then callremoveAll()
on that filtered set? Or how about "filtering" onfromKeys::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 usingif (fromKeys.remove(keyToRemove)) removedKeys.add(keyToRemove);
instead of using both contains and remove inif (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
add a comment |
6 Answers
6
active
oldest
votes
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.
Was working around with the existing code. Wouldn'tpublic 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 theretainAll
,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, theretainAll
/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 theremoveAll
iterate thefromKeys
instead ofkeysToRemove
there? About the first stream variant, how about using the predicate for reduction usingpartitioningBy
, wrote a sample code?
– Naman
8 hours ago
1
@Naman that’s hitting implementation details, but I assume that it works likeAbstractSet.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 forpartitioningBy
is as discouraged as forfilter
, but with the latter, you’re collection another set of actually unwanted elements…
– Holger
8 hours ago
add a comment |
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".
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
add a comment |
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;
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 thankeysToRemove
, soremoveAll(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
add a comment |
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;
add a comment |
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());
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
add a comment |
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);
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Was working around with the existing code. Wouldn'tpublic 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 theretainAll
,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, theretainAll
/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 theremoveAll
iterate thefromKeys
instead ofkeysToRemove
there? About the first stream variant, how about using the predicate for reduction usingpartitioningBy
, wrote a sample code?
– Naman
8 hours ago
1
@Naman that’s hitting implementation details, but I assume that it works likeAbstractSet.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 forpartitioningBy
is as discouraged as forfilter
, but with the latter, you’re collection another set of actually unwanted elements…
– Holger
8 hours ago
add a comment |
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.
Was working around with the existing code. Wouldn'tpublic 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 theretainAll
,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, theretainAll
/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 theremoveAll
iterate thefromKeys
instead ofkeysToRemove
there? About the first stream variant, how about using the predicate for reduction usingpartitioningBy
, wrote a sample code?
– Naman
8 hours ago
1
@Naman that’s hitting implementation details, but I assume that it works likeAbstractSet.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 forpartitioningBy
is as discouraged as forfilter
, but with the latter, you’re collection another set of actually unwanted elements…
– Holger
8 hours ago
add a comment |
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.
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.
answered 10 hours ago
HolgerHolger
177k24254481
177k24254481
Was working around with the existing code. Wouldn'tpublic 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 theretainAll
,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, theretainAll
/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 theremoveAll
iterate thefromKeys
instead ofkeysToRemove
there? About the first stream variant, how about using the predicate for reduction usingpartitioningBy
, wrote a sample code?
– Naman
8 hours ago
1
@Naman that’s hitting implementation details, but I assume that it works likeAbstractSet.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 forpartitioningBy
is as discouraged as forfilter
, but with the latter, you’re collection another set of actually unwanted elements…
– Holger
8 hours ago
add a comment |
Was working around with the existing code. Wouldn'tpublic 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 theretainAll
,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, theretainAll
/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 theremoveAll
iterate thefromKeys
instead ofkeysToRemove
there? About the first stream variant, how about using the predicate for reduction usingpartitioningBy
, wrote a sample code?
– Naman
8 hours ago
1
@Naman that’s hitting implementation details, but I assume that it works likeAbstractSet.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 forpartitioningBy
is as discouraged as forfilter
, 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
add a comment |
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".
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
add a comment |
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".
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
add a comment |
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".
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".
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
add a comment |
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
add a comment |
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;
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 thankeysToRemove
, soremoveAll(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
add a comment |
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;
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 thankeysToRemove
, soremoveAll(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
add a comment |
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;
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;
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 thankeysToRemove
, soremoveAll(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
add a comment |
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 thankeysToRemove
, soremoveAll(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
add a comment |
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;
add a comment |
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;
add a comment |
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;
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;
answered 12 hours ago
MaanooAkMaanooAk
1,339821
1,339821
add a comment |
add a comment |
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());
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
add a comment |
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());
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
add a comment |
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());
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());
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
add a comment |
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
add a comment |
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);
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
add a comment |
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);
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
add a comment |
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);
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);
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
1
How about just collecting all keys that can be removed and then call
removeAll()
on that filtered set? Or how about "filtering" onfromKeys::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 inif (fromKeys.contains(keyToRemove)) fromKeys.remove(keyToRemove); removedKeys.add(keyToRemove);
– Naman
9 hours ago