What is the best way to remove objects from a List
I have the following logic to r开发者_StackOverflow中文版emove inactive users in the system, since we cannot remove a row while iterating on the list. Is there a better way to handle this?
List<User> users = new ArrayList<User>();
List<User> removeUsers = new ArrayList<User>();
for (User user : users) {
if (!user.isActive()) {
removeUsers.add(user);
}
}
users.removeAll(removeUsers);
If you use ArrayList, best way is Jeff M's variant. You may also use your variant, but you should consider to use Set (HashSet or IdentityHashSet) intstead of ArrayList for removeUser. For large amount of data it will have better performance.
But for LinkedList best way will be to use Iterator.remove method:
for (Iterator<User> it = users.iterator(); it.hasNext();)
if (it.next().isActive())
it.remove();
That's a perfectly fine way to do it IMHO.
Other ways that I might do it, use indexing and remove as you loop through in reverse.
for (int i = users.size()-1; i >= 0; i--)
{
if (!users.get(i).isActive())
{
users.remove(i);
}
}
Or create a new list of the items to be kept and replace it with the old list.
List<User> newUsers = new ArrayList<User>();
for (User user : users)
{
if (user.isActive())
{
newUsers.add(user);
}
}
users = newUsers;
Can't think of any others at the moment.
How about using some Guava magic?
List<User> users = new ArrayList<User>();
Iterables.removeIf(users, new Predicate<User>() {
@Override
public boolean apply(User user) {
return !user.isActive();
}
});
If you use the Predicate in several place you could even create a named class fro it and make your code even better:
private static final class IsNotActiveUserPredicate implements Predicate<User> {
@Override
public boolean apply(User user) {
return !user.isActive();
}
}
List<User> users = new ArrayList<User>();
Iterables.removeIf(users, new IsNotActiveUserPredicate());
The way Gosling intended us to do it is using Iterator.remove
:
Iterator<User> it = users.iterator();
while (it.hasNext()) {
if (! it.next().isActive()) {
it.remove();
}
}
This might not be the best from a performance perspective if you're using ArrayList
, but then again, seems like you might want to consider changing to LinkedList
.
In any way, this is the way to remove elements from a collection while iterating over it.
You could do:
for (int i = users.size()-1; i >= 0; i--) {
if (!users.get(i).isActive()) {
users.remove(i);
}
}
I realize this is an old question, but it came up in a search I was doing, so others might still be getting here. With Java 8, the easiest way is to use the new "removeIf" method on the Collection class like so:
users.removeIf(user -> !user.isActive());
Easy peasy! It should be noted that, under the covers, the Java code is using Iterator.remove().
Oracle documentation
Here's another Guava Version using Collections2.filter:
final List<User> activeUsers =
Lists.newArrayList(Collections2.filter(userList, new Predicate<User>(){
@Override
public boolean apply(final User input){
return input.isActive();
}
}));
Here is another approach that is rather efficient with array based lists. This is because it does not need to copy the entire tail with every remove. It uses 2 steps: First all elements that need to be retained are copied to their final position at the beginning of the list and then all remaining elements at the end of the list are removed.
public static void removeInactiveUsers( ArrayList<User> users )
{
int j = 0, len = users.size();
for( int i = 0; i < len; ++i )
{
User user = user.get( i );
if( user.isActive() )
{
if( i != j )
users.set( j, user );
++j;
}
}
users.removeRange( j, len );
}
If you want remove any one object like current object or selected object you can follow as below.
Object currentObject = null;
for (User user : users)
{
if (user.isActive())
{
currentObject = user ;
}
}
if(currentObject != null) {
users.remove(currentObject);
}
精彩评论