List 删除属性为指定值的对象的3种方法
这本是一个很基础的问题,只有底层基础扎实了,才能造更好的上层建筑,正好我自己在学stream
的是由也是一脸懵,正好写系统是遇到了这么个场景,写个文章小记一下。
一、数据准备
首先,要处理的列表如下:
@Data
@AllArgsConstructor
class ListItem{
private int id;
private String name;
}
List<ListItem> list = new ArrayList<>(4);
list.add(new ListItem(1,"张三"));
list.add(new ListItem(2,"李四"));
list.add(new ListItem(3,"李四"));
list.add(new ListItem(4,"王五"));
需求是删除名字为李四
的ListItem
二、一个错误的实践案例:
/**
* 按照索引检索
*/
@Test
void testListRemoveByIndex(){
List<ListItem> list = new ArrayList<>(4);
list.add(new ListItem(1,"张三"));
list.add(new ListItem(2,"李四"));
list.add(new ListItem(3,"李四"));
list.add(new ListItem(4,"王五"));
for (int i = 0; i <list.size(); i++) {
if (list.get(i).getName().equals("李四")) {
list.remove(i);
}
}
System.out.println(list);
}
以下为输出结果:
[ServiceTest.ListItem(id=1, name=张三), ServiceTest.ListItem(id=3, name=李四), ServiceTest.ListItem(id=4, name=王五)]
结果上来看,并没有实现我们预期的效果,俗称BUG
.
三、正确的操作步骤
以上出问题的原因,这个可以自己分析一下,再或者通过debug 打断点的方式就能明白,另外还有就是通过for循环,进行删除的方式。这里不做赘述了,主要说一下以下两种方式。
1.iterator删除,遍历到元素,删除
/**
* 使用迭代器删除
*/
@Test
void testListRemoveByIterator(){
List<ListItem> list = new ArrayList<>(4);
list.add(new ListItem(1,"张三"));
list.add(new ListItem(2,"李四"));
list.add(new ListItem(3,"李四"));
list.add(new ListItem(4,"王五"));
Iterator<ListItem> iterator = list.iterator();
while (iterator.hasNext()){
ListItem next = iterator.next();
if ("李四".equals(next.getName())) {
iterator.remove();
}
}
System.out.println(list);
}
以下为输出结果:
[ServiceTest.ListItem(id=1, name=张三), ServiceTest.ListItem(id=4, name=王五)]
2.stream.filter 过滤掉指定id的元素,重新组合
/**
* 使用stream filter
*/
@Test
void testListRemoveByStreamFilter(){
List<ListItem> list = new ArrayList<>(4);
list.add(new ListItem(1,"张三"));
list.add(new ListItem(2,"李四"));
list.add(new ListItem(3,"李四"));
list.add(new ListItem(4,"王五"));
list = list.stream().filter(e->!"李四".equals(e.getName())).collect(Collectors.toList());
System.out.println(list);
}
以下为输出结果:
[ServiceTest.ListItem(id=1, name=张三), ServiceTest.ListItem(id=4, name=王五)]
不用纠结,这俩方法都挺好。现在硬件这么牛了。