Java 8 Map of Collections remove element from collection and remove entry if empty
I have a map for which the values are a collection. Given a key, I want to remove an element of the collection and return it, but I also want to remove the entry if the collection is empty. Is there a way to do this in a short way using one of the numerous new Map methods of Java 8?
One easy example (I use a Stack but it could be a List, a Set, etc.). For the sake of the example, let's say that it is already checked that the map contains the key.
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
Stack<String> stack = map.get(key);
String result = stack.pop();
if(stack.isEmpty()){
map.remove(key);
}
return result;
}
I tried doing something like
map.compute(1, (k, v) -> {v.pop(); return v.size() == 0 ? null : v;});
But even though it does indeed remove the entry if empty, I don't know how to get the value returned by pop()
.
java dictionary collections java-8 hashmap
add a comment |
I have a map for which the values are a collection. Given a key, I want to remove an element of the collection and return it, but I also want to remove the entry if the collection is empty. Is there a way to do this in a short way using one of the numerous new Map methods of Java 8?
One easy example (I use a Stack but it could be a List, a Set, etc.). For the sake of the example, let's say that it is already checked that the map contains the key.
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
Stack<String> stack = map.get(key);
String result = stack.pop();
if(stack.isEmpty()){
map.remove(key);
}
return result;
}
I tried doing something like
map.compute(1, (k, v) -> {v.pop(); return v.size() == 0 ? null : v;});
But even though it does indeed remove the entry if empty, I don't know how to get the value returned by pop()
.
java dictionary collections java-8 hashmap
3
Don't really see any reason to use streams/lambda here.
– Nicholas K
Dec 18 '18 at 11:57
1
@NicholasK the only beauty is that mapping to null and automatically removing the Entry IMO, otherwise, I'll have to agree
– Eugene
Dec 18 '18 at 11:58
I am not sure how generic this would be, but how about something like this?
– nullpointer
Dec 18 '18 at 17:31
add a comment |
I have a map for which the values are a collection. Given a key, I want to remove an element of the collection and return it, but I also want to remove the entry if the collection is empty. Is there a way to do this in a short way using one of the numerous new Map methods of Java 8?
One easy example (I use a Stack but it could be a List, a Set, etc.). For the sake of the example, let's say that it is already checked that the map contains the key.
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
Stack<String> stack = map.get(key);
String result = stack.pop();
if(stack.isEmpty()){
map.remove(key);
}
return result;
}
I tried doing something like
map.compute(1, (k, v) -> {v.pop(); return v.size() == 0 ? null : v;});
But even though it does indeed remove the entry if empty, I don't know how to get the value returned by pop()
.
java dictionary collections java-8 hashmap
I have a map for which the values are a collection. Given a key, I want to remove an element of the collection and return it, but I also want to remove the entry if the collection is empty. Is there a way to do this in a short way using one of the numerous new Map methods of Java 8?
One easy example (I use a Stack but it could be a List, a Set, etc.). For the sake of the example, let's say that it is already checked that the map contains the key.
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
Stack<String> stack = map.get(key);
String result = stack.pop();
if(stack.isEmpty()){
map.remove(key);
}
return result;
}
I tried doing something like
map.compute(1, (k, v) -> {v.pop(); return v.size() == 0 ? null : v;});
But even though it does indeed remove the entry if empty, I don't know how to get the value returned by pop()
.
java dictionary collections java-8 hashmap
java dictionary collections java-8 hashmap
edited Dec 29 '18 at 14:07
Ricola
asked Dec 18 '18 at 11:31
RicolaRicola
680111
680111
3
Don't really see any reason to use streams/lambda here.
– Nicholas K
Dec 18 '18 at 11:57
1
@NicholasK the only beauty is that mapping to null and automatically removing the Entry IMO, otherwise, I'll have to agree
– Eugene
Dec 18 '18 at 11:58
I am not sure how generic this would be, but how about something like this?
– nullpointer
Dec 18 '18 at 17:31
add a comment |
3
Don't really see any reason to use streams/lambda here.
– Nicholas K
Dec 18 '18 at 11:57
1
@NicholasK the only beauty is that mapping to null and automatically removing the Entry IMO, otherwise, I'll have to agree
– Eugene
Dec 18 '18 at 11:58
I am not sure how generic this would be, but how about something like this?
– nullpointer
Dec 18 '18 at 17:31
3
3
Don't really see any reason to use streams/lambda here.
– Nicholas K
Dec 18 '18 at 11:57
Don't really see any reason to use streams/lambda here.
– Nicholas K
Dec 18 '18 at 11:57
1
1
@NicholasK the only beauty is that mapping to null and automatically removing the Entry IMO, otherwise, I'll have to agree
– Eugene
Dec 18 '18 at 11:58
@NicholasK the only beauty is that mapping to null and automatically removing the Entry IMO, otherwise, I'll have to agree
– Eugene
Dec 18 '18 at 11:58
I am not sure how generic this would be, but how about something like this?
– nullpointer
Dec 18 '18 at 17:31
I am not sure how generic this would be, but how about something like this?
– nullpointer
Dec 18 '18 at 17:31
add a comment |
6 Answers
6
active
oldest
votes
Is there a way to do this in a short way using one of the numerous new
Map methods of Java 8?
There's no new method as of JDK8 that would improve your code whether that's in terms of readability or efficient.
if you're doing this as an exercise for your self then I can understand to some extent why you'd want to shorten the code (if possible) but when it comes to production code golfing should be avoided and instead go with the approach that is most readable and maintainable; doesn't matter if it's longer.
Your approach is good as is.
add a comment |
Or you could possibly rewrite it using size
as:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
return map.get(key).size() == 1 ? map.remove(key).pop() : map.get(key).pop();
}
1
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're usingget
twice, though this can be solved easily. +1 anyways for a good yet succinct answer
– Federico Peralta Schaffner
Dec 18 '18 at 17:51
1
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Usingget
was the part where I doubted if performance, in general, could've been harmed. But thenO(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner
– nullpointer
Dec 18 '18 at 18:06
add a comment |
Well, it's even uglier than what you have already in place, but there is a way, I guess:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
String removed = new String[1];
map.compute(key, (k, v) -> {
removed[0] = v.pop();
return v.size() == 0 ? null : v;
});
return removed[0];
}
Problem is that merge/compute
and the like return the value, and in your case that is a Stack/Set/List
, not and individual element from that collection.
2
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
add a comment |
Guava's Multimap handles the remove-collection-if-empty logic for you. You can get equivalent behaviour to your method in two lines:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
return stack.remove(stack.size() - 1);
}
Both your existing solution and the above throw Exceptions if the map has no entries for the given key. Optionally you can change the code to handle this:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
And of course you can make this generic:
public static <K, V> V removeOne(ListMultimap<K, V> map, K key) {
List<V> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
Thanks for the tip about the external library! By the way, it fits in one line:map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
add a comment |
I fully agree with @NicholasK. There's no reason to use any streams or lambdas here.
Your approach is pretty good. The only thing I would like to add is making it generic:
public static <K, E, C extends Collection<E>> E removeOne(Map<K, C> map, K key) {
C col = map.get(key);
Iterator<E> it = col.iterator();
E e = it.next();
it.remove();
if (!it.hasNext()) {
map.remove(key);
}
return e;
}
This method will be applicable to any collections (map values) returning valid iterator.
I don't find the part where you remove the entry if the collection is null. Also, you have to doit.remove()
in all cases, why the!it.hasNext()
check?
– Ricola
Dec 18 '18 at 14:24
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.
– ETO
Dec 18 '18 at 14:29
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
add a comment |
/* quite ugly
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
*/
@Test
public void test() {
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.addAll(Arrays.asList("a", "b"));
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("b", rv);
Assert.assertEquals(1, map.get(1).size());
Assert.assertEquals("a", map.get(1).iterator().next());
}
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.add("a");
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("a", rv);
Assert.assertNull(map.get(1));
}
}
4
@JurgenDeLandsheer you first need topop
and then check if it's empty
– Eugene
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
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%2f53832087%2fjava-8-map-of-collections-remove-element-from-collection-and-remove-entry-if-emp%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
Is there a way to do this in a short way using one of the numerous new
Map methods of Java 8?
There's no new method as of JDK8 that would improve your code whether that's in terms of readability or efficient.
if you're doing this as an exercise for your self then I can understand to some extent why you'd want to shorten the code (if possible) but when it comes to production code golfing should be avoided and instead go with the approach that is most readable and maintainable; doesn't matter if it's longer.
Your approach is good as is.
add a comment |
Is there a way to do this in a short way using one of the numerous new
Map methods of Java 8?
There's no new method as of JDK8 that would improve your code whether that's in terms of readability or efficient.
if you're doing this as an exercise for your self then I can understand to some extent why you'd want to shorten the code (if possible) but when it comes to production code golfing should be avoided and instead go with the approach that is most readable and maintainable; doesn't matter if it's longer.
Your approach is good as is.
add a comment |
Is there a way to do this in a short way using one of the numerous new
Map methods of Java 8?
There's no new method as of JDK8 that would improve your code whether that's in terms of readability or efficient.
if you're doing this as an exercise for your self then I can understand to some extent why you'd want to shorten the code (if possible) but when it comes to production code golfing should be avoided and instead go with the approach that is most readable and maintainable; doesn't matter if it's longer.
Your approach is good as is.
Is there a way to do this in a short way using one of the numerous new
Map methods of Java 8?
There's no new method as of JDK8 that would improve your code whether that's in terms of readability or efficient.
if you're doing this as an exercise for your self then I can understand to some extent why you'd want to shorten the code (if possible) but when it comes to production code golfing should be avoided and instead go with the approach that is most readable and maintainable; doesn't matter if it's longer.
Your approach is good as is.
answered Dec 18 '18 at 13:05
AomineAomine
41.3k74071
41.3k74071
add a comment |
add a comment |
Or you could possibly rewrite it using size
as:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
return map.get(key).size() == 1 ? map.remove(key).pop() : map.get(key).pop();
}
1
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're usingget
twice, though this can be solved easily. +1 anyways for a good yet succinct answer
– Federico Peralta Schaffner
Dec 18 '18 at 17:51
1
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Usingget
was the part where I doubted if performance, in general, could've been harmed. But thenO(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner
– nullpointer
Dec 18 '18 at 18:06
add a comment |
Or you could possibly rewrite it using size
as:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
return map.get(key).size() == 1 ? map.remove(key).pop() : map.get(key).pop();
}
1
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're usingget
twice, though this can be solved easily. +1 anyways for a good yet succinct answer
– Federico Peralta Schaffner
Dec 18 '18 at 17:51
1
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Usingget
was the part where I doubted if performance, in general, could've been harmed. But thenO(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner
– nullpointer
Dec 18 '18 at 18:06
add a comment |
Or you could possibly rewrite it using size
as:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
return map.get(key).size() == 1 ? map.remove(key).pop() : map.get(key).pop();
}
Or you could possibly rewrite it using size
as:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
return map.get(key).size() == 1 ? map.remove(key).pop() : map.get(key).pop();
}
answered Dec 18 '18 at 17:30
nullpointernullpointer
44.1k1095182
44.1k1095182
1
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're usingget
twice, though this can be solved easily. +1 anyways for a good yet succinct answer
– Federico Peralta Schaffner
Dec 18 '18 at 17:51
1
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Usingget
was the part where I doubted if performance, in general, could've been harmed. But thenO(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner
– nullpointer
Dec 18 '18 at 18:06
add a comment |
1
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're usingget
twice, though this can be solved easily. +1 anyways for a good yet succinct answer
– Federico Peralta Schaffner
Dec 18 '18 at 17:51
1
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Usingget
was the part where I doubted if performance, in general, could've been harmed. But thenO(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner
– nullpointer
Dec 18 '18 at 18:06
1
1
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're using
get
twice, though this can be solved easily. +1 anyways for a good yet succinct answer– Federico Peralta Schaffner
Dec 18 '18 at 17:51
Pity of this approach is that it only works when the entry exists in the map. I know that OP has said that we could suppose it already existed, I'm just saying that adding a check for the key makes the code uglier, because what to do in this case? Return null? Maybe... The other drawback I see is that you're using
get
twice, though this can be solved easily. +1 anyways for a good yet succinct answer– Federico Peralta Schaffner
Dec 18 '18 at 17:51
1
1
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Using
get
was the part where I doubted if performance, in general, could've been harmed. But then O(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner– nullpointer
Dec 18 '18 at 18:06
Well yes, the null check would make it more chaotic probably, but the functional implementation to answer what to do in that case would need a change in OP's existing code as well. Since that would possibly result in an NPE for such cases. Using
get
was the part where I doubted if performance, in general, could've been harmed. But then O(1)
lookup made me feel negligent about it, added to which I was thinking wouldn't there be a similar cost in terms of space if I store such value? @FedericoPeraltaSchaffner– nullpointer
Dec 18 '18 at 18:06
add a comment |
Well, it's even uglier than what you have already in place, but there is a way, I guess:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
String removed = new String[1];
map.compute(key, (k, v) -> {
removed[0] = v.pop();
return v.size() == 0 ? null : v;
});
return removed[0];
}
Problem is that merge/compute
and the like return the value, and in your case that is a Stack/Set/List
, not and individual element from that collection.
2
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
add a comment |
Well, it's even uglier than what you have already in place, but there is a way, I guess:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
String removed = new String[1];
map.compute(key, (k, v) -> {
removed[0] = v.pop();
return v.size() == 0 ? null : v;
});
return removed[0];
}
Problem is that merge/compute
and the like return the value, and in your case that is a Stack/Set/List
, not and individual element from that collection.
2
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
add a comment |
Well, it's even uglier than what you have already in place, but there is a way, I guess:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
String removed = new String[1];
map.compute(key, (k, v) -> {
removed[0] = v.pop();
return v.size() == 0 ? null : v;
});
return removed[0];
}
Problem is that merge/compute
and the like return the value, and in your case that is a Stack/Set/List
, not and individual element from that collection.
Well, it's even uglier than what you have already in place, but there is a way, I guess:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
String removed = new String[1];
map.compute(key, (k, v) -> {
removed[0] = v.pop();
return v.size() == 0 ? null : v;
});
return removed[0];
}
Problem is that merge/compute
and the like return the value, and in your case that is a Stack/Set/List
, not and individual element from that collection.
answered Dec 18 '18 at 11:56
EugeneEugene
68.5k999163
68.5k999163
2
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
add a comment |
2
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
2
2
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
Hahaha I actually thought about this solution but as you said, it's really ugly.
– Ricola
Dec 18 '18 at 12:13
add a comment |
Guava's Multimap handles the remove-collection-if-empty logic for you. You can get equivalent behaviour to your method in two lines:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
return stack.remove(stack.size() - 1);
}
Both your existing solution and the above throw Exceptions if the map has no entries for the given key. Optionally you can change the code to handle this:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
And of course you can make this generic:
public static <K, V> V removeOne(ListMultimap<K, V> map, K key) {
List<V> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
Thanks for the tip about the external library! By the way, it fits in one line:map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
add a comment |
Guava's Multimap handles the remove-collection-if-empty logic for you. You can get equivalent behaviour to your method in two lines:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
return stack.remove(stack.size() - 1);
}
Both your existing solution and the above throw Exceptions if the map has no entries for the given key. Optionally you can change the code to handle this:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
And of course you can make this generic:
public static <K, V> V removeOne(ListMultimap<K, V> map, K key) {
List<V> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
Thanks for the tip about the external library! By the way, it fits in one line:map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
add a comment |
Guava's Multimap handles the remove-collection-if-empty logic for you. You can get equivalent behaviour to your method in two lines:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
return stack.remove(stack.size() - 1);
}
Both your existing solution and the above throw Exceptions if the map has no entries for the given key. Optionally you can change the code to handle this:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
And of course you can make this generic:
public static <K, V> V removeOne(ListMultimap<K, V> map, K key) {
List<V> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
Guava's Multimap handles the remove-collection-if-empty logic for you. You can get equivalent behaviour to your method in two lines:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
return stack.remove(stack.size() - 1);
}
Both your existing solution and the above throw Exceptions if the map has no entries for the given key. Optionally you can change the code to handle this:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
And of course you can make this generic:
public static <K, V> V removeOne(ListMultimap<K, V> map, K key) {
List<V> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
answered Dec 18 '18 at 13:48
MikeFHayMikeFHay
3,10532035
3,10532035
Thanks for the tip about the external library! By the way, it fits in one line:map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
add a comment |
Thanks for the tip about the external library! By the way, it fits in one line:map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
Thanks for the tip about the external library! By the way, it fits in one line:
map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
Thanks for the tip about the external library! By the way, it fits in one line:
map.get(key).pop();
– Ricola
Dec 22 '18 at 16:18
add a comment |
I fully agree with @NicholasK. There's no reason to use any streams or lambdas here.
Your approach is pretty good. The only thing I would like to add is making it generic:
public static <K, E, C extends Collection<E>> E removeOne(Map<K, C> map, K key) {
C col = map.get(key);
Iterator<E> it = col.iterator();
E e = it.next();
it.remove();
if (!it.hasNext()) {
map.remove(key);
}
return e;
}
This method will be applicable to any collections (map values) returning valid iterator.
I don't find the part where you remove the entry if the collection is null. Also, you have to doit.remove()
in all cases, why the!it.hasNext()
check?
– Ricola
Dec 18 '18 at 14:24
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.
– ETO
Dec 18 '18 at 14:29
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
add a comment |
I fully agree with @NicholasK. There's no reason to use any streams or lambdas here.
Your approach is pretty good. The only thing I would like to add is making it generic:
public static <K, E, C extends Collection<E>> E removeOne(Map<K, C> map, K key) {
C col = map.get(key);
Iterator<E> it = col.iterator();
E e = it.next();
it.remove();
if (!it.hasNext()) {
map.remove(key);
}
return e;
}
This method will be applicable to any collections (map values) returning valid iterator.
I don't find the part where you remove the entry if the collection is null. Also, you have to doit.remove()
in all cases, why the!it.hasNext()
check?
– Ricola
Dec 18 '18 at 14:24
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.
– ETO
Dec 18 '18 at 14:29
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
add a comment |
I fully agree with @NicholasK. There's no reason to use any streams or lambdas here.
Your approach is pretty good. The only thing I would like to add is making it generic:
public static <K, E, C extends Collection<E>> E removeOne(Map<K, C> map, K key) {
C col = map.get(key);
Iterator<E> it = col.iterator();
E e = it.next();
it.remove();
if (!it.hasNext()) {
map.remove(key);
}
return e;
}
This method will be applicable to any collections (map values) returning valid iterator.
I fully agree with @NicholasK. There's no reason to use any streams or lambdas here.
Your approach is pretty good. The only thing I would like to add is making it generic:
public static <K, E, C extends Collection<E>> E removeOne(Map<K, C> map, K key) {
C col = map.get(key);
Iterator<E> it = col.iterator();
E e = it.next();
it.remove();
if (!it.hasNext()) {
map.remove(key);
}
return e;
}
This method will be applicable to any collections (map values) returning valid iterator.
edited Dec 19 '18 at 6:33
answered Dec 18 '18 at 13:35
ETOETO
1,976422
1,976422
I don't find the part where you remove the entry if the collection is null. Also, you have to doit.remove()
in all cases, why the!it.hasNext()
check?
– Ricola
Dec 18 '18 at 14:24
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.
– ETO
Dec 18 '18 at 14:29
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
add a comment |
I don't find the part where you remove the entry if the collection is null. Also, you have to doit.remove()
in all cases, why the!it.hasNext()
check?
– Ricola
Dec 18 '18 at 14:24
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.
– ETO
Dec 18 '18 at 14:29
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
I don't find the part where you remove the entry if the collection is null. Also, you have to do
it.remove()
in all cases, why the !it.hasNext()
check?– Ricola
Dec 18 '18 at 14:24
I don't find the part where you remove the entry if the collection is null. Also, you have to do
it.remove()
in all cases, why the !it.hasNext()
check?– Ricola
Dec 18 '18 at 14:24
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.– ETO
Dec 18 '18 at 14:29
!it.hasNext()
checks whether the collection is empty after we remove an element, as it's implemented by OP in his own example.– ETO
Dec 18 '18 at 14:29
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:
if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
I am OP and I'm 100% sure that this does not do the same thing. I just tested it. As I said, you never remove the empty collection from the map. I think you meant:
if (!it.hasNext()) { map.remove(key); } it.remove();
– Ricola
Dec 18 '18 at 23:38
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
Okay, I stand corrected. Now the updated version should do the same thing as your example for any collection type as map value.
– ETO
Dec 19 '18 at 6:35
add a comment |
/* quite ugly
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
*/
@Test
public void test() {
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.addAll(Arrays.asList("a", "b"));
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("b", rv);
Assert.assertEquals(1, map.get(1).size());
Assert.assertEquals("a", map.get(1).iterator().next());
}
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.add("a");
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("a", rv);
Assert.assertNull(map.get(1));
}
}
4
@JurgenDeLandsheer you first need topop
and then check if it's empty
– Eugene
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
add a comment |
/* quite ugly
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
*/
@Test
public void test() {
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.addAll(Arrays.asList("a", "b"));
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("b", rv);
Assert.assertEquals(1, map.get(1).size());
Assert.assertEquals("a", map.get(1).iterator().next());
}
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.add("a");
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("a", rv);
Assert.assertNull(map.get(1));
}
}
4
@JurgenDeLandsheer you first need topop
and then check if it's empty
– Eugene
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
add a comment |
/* quite ugly
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
*/
@Test
public void test() {
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.addAll(Arrays.asList("a", "b"));
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("b", rv);
Assert.assertEquals(1, map.get(1).size());
Assert.assertEquals("a", map.get(1).iterator().next());
}
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.add("a");
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("a", rv);
Assert.assertNull(map.get(1));
}
}
/* quite ugly
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
*/
@Test
public void test() {
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.addAll(Arrays.asList("a", "b"));
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("b", rv);
Assert.assertEquals(1, map.get(1).size());
Assert.assertEquals("a", map.get(1).iterator().next());
}
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.add("a");
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("a", rv);
Assert.assertNull(map.get(1));
}
}
edited Dec 18 '18 at 12:09
answered Dec 18 '18 at 11:49
Jurgen De LandsheerJurgen De Landsheer
826
826
4
@JurgenDeLandsheer you first need topop
and then check if it's empty
– Eugene
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
add a comment |
4
@JurgenDeLandsheer you first need topop
and then check if it's empty
– Eugene
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
4
4
@JurgenDeLandsheer you first need to
pop
and then check if it's empty– Eugene
Dec 18 '18 at 11:55
@JurgenDeLandsheer you first need to
pop
and then check if it's empty– Eugene
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
it does exactly what he asks, and it uses all new java 8 possibilities
– Jurgen De Landsheer
Dec 18 '18 at 11:55
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53832087%2fjava-8-map-of-collections-remove-element-from-collection-and-remove-entry-if-emp%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
3
Don't really see any reason to use streams/lambda here.
– Nicholas K
Dec 18 '18 at 11:57
1
@NicholasK the only beauty is that mapping to null and automatically removing the Entry IMO, otherwise, I'll have to agree
– Eugene
Dec 18 '18 at 11:58
I am not sure how generic this would be, but how about something like this?
– nullpointer
Dec 18 '18 at 17:31