Java 8 Map of Collections remove element from collection and remove entry if empty












12














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().










share|improve this question




















  • 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
















12














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().










share|improve this question




















  • 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














12












12








12


1





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().










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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














  • 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












6 Answers
6






active

oldest

votes


















2















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.






share|improve this answer





























    6














    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();
    }





    share|improve this answer

















    • 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






    • 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





















    5














    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.






    share|improve this answer

















    • 2




      Hahaha I actually thought about this solution but as you said, it's really ugly.
      – Ricola
      Dec 18 '18 at 12:13



















    2














    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);
    }





    share|improve this answer





















    • 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



















    2














    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.






    share|improve this answer























    • 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












    • 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





















    -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));
    }
    }





    share|improve this answer



















    • 4




      @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











    Your Answer






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

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

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

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


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%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









    2















    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.






    share|improve this answer


























      2















      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.






      share|improve this answer
























        2












        2








        2







        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.






        share|improve this answer













        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 18 '18 at 13:05









        AomineAomine

        41.3k74071




        41.3k74071

























            6














            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();
            }





            share|improve this answer

















            • 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






            • 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


















            6














            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();
            }





            share|improve this answer

















            • 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






            • 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
















            6












            6








            6






            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();
            }





            share|improve this answer












            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();
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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 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




              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
















            • 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






            • 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










            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













            5














            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.






            share|improve this answer

















            • 2




              Hahaha I actually thought about this solution but as you said, it's really ugly.
              – Ricola
              Dec 18 '18 at 12:13
















            5














            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.






            share|improve this answer

















            • 2




              Hahaha I actually thought about this solution but as you said, it's really ugly.
              – Ricola
              Dec 18 '18 at 12:13














            5












            5








            5






            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.






            share|improve this answer












            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            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














            • 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











            2














            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);
            }





            share|improve this answer





















            • 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
















            2














            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);
            }





            share|improve this answer





















            • 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














            2












            2








            2






            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);
            }





            share|improve this answer












            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);
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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


















            • 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











            2














            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.






            share|improve this answer























            • 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












            • 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


















            2














            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.






            share|improve this answer























            • 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












            • 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
















            2












            2








            2






            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.






            share|improve this answer














            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 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












            • 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










            • !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













            -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));
            }
            }





            share|improve this answer



















            • 4




              @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
















            -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));
            }
            }





            share|improve this answer



















            • 4




              @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














            -1












            -1








            -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));
            }
            }





            share|improve this answer














            /* 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));
            }
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 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














            • 4




              @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








            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


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


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

            But avoid



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

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


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





            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.




            draft saved


            draft discarded














            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





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Ellipse (mathématiques)

            Quarter-circle Tiles

            Mont Emei