Filter a list in Java












0















I have a list of people with additional information - let's say book rentals. So each Rental-object in my list would include a Person-object as an attribute and some rental information. For each person there will be 1..n entries in the list.



Now I need to filter this list based on some criteria. If ONE of the entries matches a certain criteria, I want to delete ALL entries for that person, even if the other entries do not match the criteria.



Is there a nice way to do this in one filter? Alternative would be to scan the list, identify people whose entries should be removed and then apply something like



Collections2.filter(myList, new MyPredicate(peopleIWantToRemove))


but I would like to do it with just one-time-list-traversal. How can I do this?










share|improve this question





























    0















    I have a list of people with additional information - let's say book rentals. So each Rental-object in my list would include a Person-object as an attribute and some rental information. For each person there will be 1..n entries in the list.



    Now I need to filter this list based on some criteria. If ONE of the entries matches a certain criteria, I want to delete ALL entries for that person, even if the other entries do not match the criteria.



    Is there a nice way to do this in one filter? Alternative would be to scan the list, identify people whose entries should be removed and then apply something like



    Collections2.filter(myList, new MyPredicate(peopleIWantToRemove))


    but I would like to do it with just one-time-list-traversal. How can I do this?










    share|improve this question



























      0












      0








      0








      I have a list of people with additional information - let's say book rentals. So each Rental-object in my list would include a Person-object as an attribute and some rental information. For each person there will be 1..n entries in the list.



      Now I need to filter this list based on some criteria. If ONE of the entries matches a certain criteria, I want to delete ALL entries for that person, even if the other entries do not match the criteria.



      Is there a nice way to do this in one filter? Alternative would be to scan the list, identify people whose entries should be removed and then apply something like



      Collections2.filter(myList, new MyPredicate(peopleIWantToRemove))


      but I would like to do it with just one-time-list-traversal. How can I do this?










      share|improve this question
















      I have a list of people with additional information - let's say book rentals. So each Rental-object in my list would include a Person-object as an attribute and some rental information. For each person there will be 1..n entries in the list.



      Now I need to filter this list based on some criteria. If ONE of the entries matches a certain criteria, I want to delete ALL entries for that person, even if the other entries do not match the criteria.



      Is there a nice way to do this in one filter? Alternative would be to scan the list, identify people whose entries should be removed and then apply something like



      Collections2.filter(myList, new MyPredicate(peopleIWantToRemove))


      but I would like to do it with just one-time-list-traversal. How can I do this?







      java list filter criteria traversal






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 6:39









      Giorgio

      2,70752858




      2,70752858










      asked Feb 1 '13 at 14:56









      i--i--

      78312




      78312
























          5 Answers
          5






          active

          oldest

          votes


















          1














          Going through the list twice (once to determine all the "bad" people, a second time to remove them) is, from an algorithm run-time standpoint, perfectly harmless. Whether you go through the list once or twice, the algorithm runs in O(n) time.



          However, if you're really serious about only going through the list once, you could construct a temporary data structure that keeps track of all the places each person appears alongside a list of the people you want to get rid of.



          Map<Person, List<Rental>> rentalsPerPerson;
          List<People> badPeople;


          When you parse the list the first time, you populate these two structures. Then you go through the list of badPeople, pull out their list of Rental objects, and purge those one at a time from your original list.



          But honestly, that feels like a lot of bother for not much gain.



          The way I'd recommend doing it? Go through the list twice. First pass: Compile a Set of bad people. Second pass: Create a new output List, initially empty. Go through your original List. For each element, if the Person isn't in the Bad set, add the entry to your output List.






          share|improve this answer
























          • I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

            – John B
            Feb 1 '13 at 15:25





















          0














          Make the predicate stateful so that it not only matches if some criterion is met, but also if the person is known as a "bad" person.






          share|improve this answer
























          • But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

            – i--
            Feb 1 '13 at 15:08













          • Oh, correct. I missed that, sorry. However, I think this is inevitable.

            – C-Otto
            Feb 1 '13 at 15:14



















          0














          Use Iterables.filter() instead. Per the class docs: "Unless otherwise noted, all of the iterables produced in this class are lazy, which means that their iterators only advance the backing iteration when absolutely necessary." That means you can compose multiple filters, but the traversal only happens once, when you do it yourself.






          share|improve this answer































            0














            Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said






            share|improve this answer































              0















              Now I need to filter this list based on some criteria. If ONE of the
              entries matches a certain criteria, I want to delete ALL entries for
              that person, even if the other entries do not match the criteria.




              I think you were not doing filtering. because filtering return a subCollection (filtered) against on some condition. You are gonna always get the same Person List but with some element changed.



              You want something like python's map(list, function). going through the list, for each person do something.



              Guava's collections.transform can do it.



              public static <F,T> Collection<T> transform(Collection<F> fromCollection,
              Function<? super F,T> function)


              check it out:



              http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)






              share|improve this answer

























                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%2f14648984%2ffilter-a-list-in-java%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                5 Answers
                5






                active

                oldest

                votes








                5 Answers
                5






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                1














                Going through the list twice (once to determine all the "bad" people, a second time to remove them) is, from an algorithm run-time standpoint, perfectly harmless. Whether you go through the list once or twice, the algorithm runs in O(n) time.



                However, if you're really serious about only going through the list once, you could construct a temporary data structure that keeps track of all the places each person appears alongside a list of the people you want to get rid of.



                Map<Person, List<Rental>> rentalsPerPerson;
                List<People> badPeople;


                When you parse the list the first time, you populate these two structures. Then you go through the list of badPeople, pull out their list of Rental objects, and purge those one at a time from your original list.



                But honestly, that feels like a lot of bother for not much gain.



                The way I'd recommend doing it? Go through the list twice. First pass: Compile a Set of bad people. Second pass: Create a new output List, initially empty. Go through your original List. For each element, if the Person isn't in the Bad set, add the entry to your output List.






                share|improve this answer
























                • I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

                  – John B
                  Feb 1 '13 at 15:25


















                1














                Going through the list twice (once to determine all the "bad" people, a second time to remove them) is, from an algorithm run-time standpoint, perfectly harmless. Whether you go through the list once or twice, the algorithm runs in O(n) time.



                However, if you're really serious about only going through the list once, you could construct a temporary data structure that keeps track of all the places each person appears alongside a list of the people you want to get rid of.



                Map<Person, List<Rental>> rentalsPerPerson;
                List<People> badPeople;


                When you parse the list the first time, you populate these two structures. Then you go through the list of badPeople, pull out their list of Rental objects, and purge those one at a time from your original list.



                But honestly, that feels like a lot of bother for not much gain.



                The way I'd recommend doing it? Go through the list twice. First pass: Compile a Set of bad people. Second pass: Create a new output List, initially empty. Go through your original List. For each element, if the Person isn't in the Bad set, add the entry to your output List.






                share|improve this answer
























                • I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

                  – John B
                  Feb 1 '13 at 15:25
















                1












                1








                1







                Going through the list twice (once to determine all the "bad" people, a second time to remove them) is, from an algorithm run-time standpoint, perfectly harmless. Whether you go through the list once or twice, the algorithm runs in O(n) time.



                However, if you're really serious about only going through the list once, you could construct a temporary data structure that keeps track of all the places each person appears alongside a list of the people you want to get rid of.



                Map<Person, List<Rental>> rentalsPerPerson;
                List<People> badPeople;


                When you parse the list the first time, you populate these two structures. Then you go through the list of badPeople, pull out their list of Rental objects, and purge those one at a time from your original list.



                But honestly, that feels like a lot of bother for not much gain.



                The way I'd recommend doing it? Go through the list twice. First pass: Compile a Set of bad people. Second pass: Create a new output List, initially empty. Go through your original List. For each element, if the Person isn't in the Bad set, add the entry to your output List.






                share|improve this answer













                Going through the list twice (once to determine all the "bad" people, a second time to remove them) is, from an algorithm run-time standpoint, perfectly harmless. Whether you go through the list once or twice, the algorithm runs in O(n) time.



                However, if you're really serious about only going through the list once, you could construct a temporary data structure that keeps track of all the places each person appears alongside a list of the people you want to get rid of.



                Map<Person, List<Rental>> rentalsPerPerson;
                List<People> badPeople;


                When you parse the list the first time, you populate these two structures. Then you go through the list of badPeople, pull out their list of Rental objects, and purge those one at a time from your original list.



                But honestly, that feels like a lot of bother for not much gain.



                The way I'd recommend doing it? Go through the list twice. First pass: Compile a Set of bad people. Second pass: Create a new output List, initially empty. Go through your original List. For each element, if the Person isn't in the Bad set, add the entry to your output List.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Feb 1 '13 at 15:14









                BlairHippoBlairHippo

                6,02484572




                6,02484572













                • I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

                  – John B
                  Feb 1 '13 at 15:25





















                • I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

                  – John B
                  Feb 1 '13 at 15:25



















                I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

                – John B
                Feb 1 '13 at 15:25







                I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining a Map<Person, List<Rental>> to start with would be the way to go. If you need ordering use a LinkedHashMap. Also, Guava provides a Multimap set of collections that are designed to do maps of lists and takes care of the back-end list creation for you.

                – John B
                Feb 1 '13 at 15:25















                0














                Make the predicate stateful so that it not only matches if some criterion is met, but also if the person is known as a "bad" person.






                share|improve this answer
























                • But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

                  – i--
                  Feb 1 '13 at 15:08













                • Oh, correct. I missed that, sorry. However, I think this is inevitable.

                  – C-Otto
                  Feb 1 '13 at 15:14
















                0














                Make the predicate stateful so that it not only matches if some criterion is met, but also if the person is known as a "bad" person.






                share|improve this answer
























                • But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

                  – i--
                  Feb 1 '13 at 15:08













                • Oh, correct. I missed that, sorry. However, I think this is inevitable.

                  – C-Otto
                  Feb 1 '13 at 15:14














                0












                0








                0







                Make the predicate stateful so that it not only matches if some criterion is met, but also if the person is known as a "bad" person.






                share|improve this answer













                Make the predicate stateful so that it not only matches if some criterion is met, but also if the person is known as a "bad" person.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Feb 1 '13 at 15:01









                C-OttoC-Otto

                3,54221952




                3,54221952













                • But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

                  – i--
                  Feb 1 '13 at 15:08













                • Oh, correct. I missed that, sorry. However, I think this is inevitable.

                  – C-Otto
                  Feb 1 '13 at 15:14



















                • But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

                  – i--
                  Feb 1 '13 at 15:08













                • Oh, correct. I missed that, sorry. However, I think this is inevitable.

                  – C-Otto
                  Feb 1 '13 at 15:14

















                But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

                – i--
                Feb 1 '13 at 15:08







                But then I still would need to apply the filter twice e.g. when the second entry for a person matches the criteria, the person is marked as "bad" but the first entry already "passed" the test.

                – i--
                Feb 1 '13 at 15:08















                Oh, correct. I missed that, sorry. However, I think this is inevitable.

                – C-Otto
                Feb 1 '13 at 15:14





                Oh, correct. I missed that, sorry. However, I think this is inevitable.

                – C-Otto
                Feb 1 '13 at 15:14











                0














                Use Iterables.filter() instead. Per the class docs: "Unless otherwise noted, all of the iterables produced in this class are lazy, which means that their iterators only advance the backing iteration when absolutely necessary." That means you can compose multiple filters, but the traversal only happens once, when you do it yourself.






                share|improve this answer




























                  0














                  Use Iterables.filter() instead. Per the class docs: "Unless otherwise noted, all of the iterables produced in this class are lazy, which means that their iterators only advance the backing iteration when absolutely necessary." That means you can compose multiple filters, but the traversal only happens once, when you do it yourself.






                  share|improve this answer


























                    0












                    0








                    0







                    Use Iterables.filter() instead. Per the class docs: "Unless otherwise noted, all of the iterables produced in this class are lazy, which means that their iterators only advance the backing iteration when absolutely necessary." That means you can compose multiple filters, but the traversal only happens once, when you do it yourself.






                    share|improve this answer













                    Use Iterables.filter() instead. Per the class docs: "Unless otherwise noted, all of the iterables produced in this class are lazy, which means that their iterators only advance the backing iteration when absolutely necessary." That means you can compose multiple filters, but the traversal only happens once, when you do it yourself.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Feb 1 '13 at 15:10









                    Ryan StewartRyan Stewart

                    99.9k17151182




                    99.9k17151182























                        0














                        Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said






                        share|improve this answer




























                          0














                          Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said






                          share|improve this answer


























                            0












                            0








                            0







                            Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said






                            share|improve this answer













                            Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Feb 1 '13 at 15:13









                            SteSte

                            1048




                            1048























                                0















                                Now I need to filter this list based on some criteria. If ONE of the
                                entries matches a certain criteria, I want to delete ALL entries for
                                that person, even if the other entries do not match the criteria.




                                I think you were not doing filtering. because filtering return a subCollection (filtered) against on some condition. You are gonna always get the same Person List but with some element changed.



                                You want something like python's map(list, function). going through the list, for each person do something.



                                Guava's collections.transform can do it.



                                public static <F,T> Collection<T> transform(Collection<F> fromCollection,
                                Function<? super F,T> function)


                                check it out:



                                http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)






                                share|improve this answer






























                                  0















                                  Now I need to filter this list based on some criteria. If ONE of the
                                  entries matches a certain criteria, I want to delete ALL entries for
                                  that person, even if the other entries do not match the criteria.




                                  I think you were not doing filtering. because filtering return a subCollection (filtered) against on some condition. You are gonna always get the same Person List but with some element changed.



                                  You want something like python's map(list, function). going through the list, for each person do something.



                                  Guava's collections.transform can do it.



                                  public static <F,T> Collection<T> transform(Collection<F> fromCollection,
                                  Function<? super F,T> function)


                                  check it out:



                                  http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)






                                  share|improve this answer




























                                    0












                                    0








                                    0








                                    Now I need to filter this list based on some criteria. If ONE of the
                                    entries matches a certain criteria, I want to delete ALL entries for
                                    that person, even if the other entries do not match the criteria.




                                    I think you were not doing filtering. because filtering return a subCollection (filtered) against on some condition. You are gonna always get the same Person List but with some element changed.



                                    You want something like python's map(list, function). going through the list, for each person do something.



                                    Guava's collections.transform can do it.



                                    public static <F,T> Collection<T> transform(Collection<F> fromCollection,
                                    Function<? super F,T> function)


                                    check it out:



                                    http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)






                                    share|improve this answer
















                                    Now I need to filter this list based on some criteria. If ONE of the
                                    entries matches a certain criteria, I want to delete ALL entries for
                                    that person, even if the other entries do not match the criteria.




                                    I think you were not doing filtering. because filtering return a subCollection (filtered) against on some condition. You are gonna always get the same Person List but with some element changed.



                                    You want something like python's map(list, function). going through the list, for each person do something.



                                    Guava's collections.transform can do it.



                                    public static <F,T> Collection<T> transform(Collection<F> fromCollection,
                                    Function<? super F,T> function)


                                    check it out:



                                    http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Feb 1 '13 at 15:27

























                                    answered Feb 1 '13 at 15:21









                                    KentKent

                                    146k27161220




                                    146k27161220






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Stack Overflow!


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

                                        But avoid



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

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


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




                                        draft saved


                                        draft discarded














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







                                        這個網誌中的熱門文章

                                        Xamarin.form Move up view when keyboard appear

                                        Post-Redirect-Get with Spring WebFlux and Thymeleaf

                                        Anylogic : not able to use stopDelay()