Filter a list in Java
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
add a comment |
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
add a comment |
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
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
java list filter criteria traversal
edited Nov 23 '18 at 6:39
Giorgio
2,70752858
2,70752858
asked Feb 1 '13 at 14:56
i--i--
78312
78312
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
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
.
I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining aMap<Person, List<Rental>>
to start with would be the way to go. If you need ordering use aLinkedHashMap
. Also, Guava provides aMultimap
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
add a comment |
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.
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
add a comment |
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.
add a comment |
Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said
add a comment |
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)
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%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
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
.
I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining aMap<Person, List<Rental>>
to start with would be the way to go. If you need ordering use aLinkedHashMap
. Also, Guava provides aMultimap
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
add a comment |
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
.
I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining aMap<Person, List<Rental>>
to start with would be the way to go. If you need ordering use aLinkedHashMap
. Also, Guava provides aMultimap
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
add a comment |
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
.
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
.
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 aMap<Person, List<Rental>>
to start with would be the way to go. If you need ordering use aLinkedHashMap
. Also, Guava provides aMultimap
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
add a comment |
I think the post points the the notion that maybe the collection you are using is not appropriate. I would think that maintainining aMap<Person, List<Rental>>
to start with would be the way to go. If you need ordering use aLinkedHashMap
. Also, Guava provides aMultimap
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
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Feb 1 '13 at 15:10
Ryan StewartRyan Stewart
99.9k17151182
99.9k17151182
add a comment |
add a comment |
Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said
add a comment |
Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said
add a comment |
Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said
Sort list based on bad people criteria (bad entry first), and then filter using stateful predicate as C-Otto said
answered Feb 1 '13 at 15:13
SteSte
1048
1048
add a comment |
add a comment |
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)
add a comment |
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)
add a comment |
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)
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)
edited Feb 1 '13 at 15:27
answered Feb 1 '13 at 15:21
KentKent
146k27161220
146k27161220
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f14648984%2ffilter-a-list-in-java%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown