从List中删除对象的最佳方法是什么

时间:2010-09-22 07:19:01

标签: java

我有以下逻辑删除系统中的非活动用户,因为我们在迭代列表时无法删除行。有没有更好的方法来解决这个问题?

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

9 个答案:

答案 0 :(得分:13)

如果使用ArrayList,最好的方法是Jeff M的变体。您也可以使用您的变体,但您应该考虑使用Set(HashSet或IdentityHashSet)而不是ArrayList for removeUser。对于大量数据,它将具有更好的性能。

但对于LinkedList,最好的方法是使用Iterator.remove方法:

for (Iterator<User> it = users.iterator(); it.hasNext();)
    if (it.next().isActive())
        it.remove();

答案 1 :(得分:8)

这是一个非常好的方式来做它恕我直言。

我可能采用的其他方式,使用索引并在反向循环时删除。

for (int i = users.size()-1; i >= 0; i--)
{
    if (!users.get(i).isActive())
    {
        users.remove(i);
    }
}

或者创建要保留的项目的新列表,并将其替换为旧列表。

List<User> newUsers = new ArrayList<User>();
for (User user : users)
{
    if (user.isActive())
    {
        newUsers.add(user);
    }
}
users = newUsers;

目前无法想到任何其他人。

答案 2 :(得分:4)

如何使用Guava魔法?

List<User> users = new ArrayList<User>();
Iterables.removeIf(users, new Predicate<User>() {

 @Override
 public boolean apply(User user) {
  return !user.isActive();
 }
});

如果你在几个地方使用Predicate,你甚至可以为它创建一个命名类,让你的代码更好:

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

答案 3 :(得分:3)

Gosling希望我们这样做的方法是使用Iterator.remove

Iterator<User> it = users.iterator();
while (it.hasNext()) {
    if (! it.next().isActive()) {
        it.remove();
    }
}

如果您使用ArrayList,从性能角度来看这可能不是最好的,但是再次看来,您似乎可以考虑更改为LinkedList

无论如何,这是在迭代时从集合中删除元素的方法。

答案 4 :(得分:1)

你可以这样做:

for (int i = users.size()-1; i >= 0; i--) {
  if (!users.get(i).isActive()) {
    users.remove(i);
  }
}

答案 5 :(得分:0)

这是使用Collections2.filter的另一个番石榴版本:

final List<User> activeUsers =
    Lists.newArrayList(Collections2.filter(userList, new Predicate<User>(){

        @Override
        public boolean apply(final User input){
            return input.isActive();
        }
    }));

答案 6 :(得分:0)

这是另一种基于数组的列表相当有效的方法。这是因为每次删除都不需要复制整个尾部。它使用两个步骤:首先将所有需要保留的元素复制到列表开头的最终位置,然后删除列表末尾的所有剩余元素。

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

答案 7 :(得分:0)

如果要删除任何一个对象,如当前对象或所选对象,您可以按照以下步骤进行操作。

    Object currentObject = null;
    for (User user : users)
    {
        if (user.isActive())
        {
            currentObject  = user ;
        }
    }

    if(currentObject != null) {
    users.remove(currentObject);
    }

答案 8 :(得分:0)

我意识到这是一个古老的问题,但它是我在进行搜索时提出的,因此其他人可能仍会来到这里。使用Java 8,最简单的方法是在Collection类上使用新的“ removeIf”方法,如下所示:

users.removeIf(user -> !user.isActive());

轻松自如! 应该注意的是,在幕后,Java代码使用的是Iterator.remove()。

Oracle documentation