繁体   English   中英

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

[英]What is the best way to remove objects from a List

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

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

如果你使用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();

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

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

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;

目前想不到任何其他人。

如何使用一些番石榴魔法?

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

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

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

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

Gosling打算让我们这样做的方法是使用Iterator.remove

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

如果您正在使用ArrayList ,这可能不是从性能角度来看最好的,但是再次看起来您可能想要考虑更改为LinkedList

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

你可以这样做:

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

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

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

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

这是使用Collections2.filter的另一个Guava版本:

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

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

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

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

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

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

十分简单! 应该注意的是,在封面下,Java代码使用的是Iterator.remove()。

Oracle文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM