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