Java ArrayList.remove不在循环中工作
我有以下代码-Java ArrayList.remove不在循环中工作,java,arraylist,Java,Arraylist,我有以下代码- import java.util.ArrayList; public class ArrayListExp{ public static void main (String[] args){ ArrayList<String> name = new ArrayList<String>(); name.add("Chris"); name.add("Lois"); name.add
import java.util.ArrayList;
public class ArrayListExp{
public static void main (String[] args){
ArrayList<String> name = new ArrayList<String>();
name.add("Chris");
name.add("Lois");
name.add("Meg");
name.add("Meg");
name.add("Brain");
name.add("Peter");
name.add("Stewie");
System.out.println(name);
for ( int i = 0; i < name.size(); i++){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.remove(i);
}
}
System.out.println(name);
}
}
我不明白为什么这不能删除
Meg
,但我只尝试了一个Meg
,在这种情况下它是有效的。当我在最后添加几个Meg
时,一个Meg
不会从ArrayList
中删除。为什么?在从0到N迭代ArrayList时,从ArrayList中移除,因此当移除索引N处的第一个Meg时,下一个Meg向下移动到索引N,然后将i增加到N+1。所以第二个梅格没有被移除。尝试以相反的顺序(N到0)迭代:
移除第一个“Meg”时,索引i=2
。然后它是递增的,但是由于其中一个“Meg”已经被删除,现在name.get(3)
是“Brain”。所以你没有检查第二个“梅格”
来解决这个问题。删除元素时,可以减小索引:
public class ArrayListExp{
public static void main (String[] args){
ArrayList<String> name = new ArrayList<String>();
name.add("Chris");
name.add("Lois");
name.add("Meg");
name.add("Meg");
name.add("Brain");
name.add("Peter");
name.add("Stewie");
System.out.println(name);
for ( int i = 0; i < name.size(); i++){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.remove(i);
i--;
}
}
System.out.println(name);
}
}
公共类ArrayListXP{
公共静态void main(字符串[]args){
ArrayList name=新的ArrayList();
名称。添加(“克里斯”);
名称。添加(“意向书”);
名称。添加(“Meg”);
名称。添加(“Meg”);
名称。添加(“大脑”);
姓名。添加(“彼得”);
名称。添加(“炖肉”);
System.out.println(名称);
对于(int i=0;i
这是因为当i=2时,如果条件为真,则删除meg,并将所有索引上移。因此,下一步我将指向大脑,而不是梅格
试试这个。(如果条件成立,则将i减少1)
for(int i=0;i
删除循环中不应使用的元素时。它在实现某些逻辑时总是会出现问题。对您的问题使用reverse for loop,并始终尝试对每个问题使用。您正在迭代第一个Meg
,当该Meg
被删除时,数组值会移动一个
[Chris, Lois, Meg, Meg, Brain, Peter, Stewie]
0 1 2 3 4 5 6
首先,Meg
被删除,循环增加i,因为它完成了for循环中的所有操作,因此i
现在将为3,并且数组已被修改:
[Chris, Lois, Meg, Brain, Peter, Stewie]
0 1 2 3 4 5
尝试向后迭代
for ( int i = name.size() - 1; i >= 0; i--){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.remove(i);
}
}
您可以使用
name.removeAll(Arrays.asList(“Meg”)代码>删除所有“Meg”
您的完整代码将是
for ( int i = 0; i < name.size(); i++){
String oldName = name.get(i);
if(oldName.equals("Meg"))
{
name.removeAll(Arrays.asList("Meg"));
}
}
for(int i=0;i
Java8+
接口现在提供了一个就地修改它的方法,您可以向该方法提供一个谓词,如果该元素应该被删除,该谓词将返回true
因此,您可以像这样使用lambda:
name.removeIf(name -> name.equals("Meg"));
也可以使用方法引用,使其更加简洁。如果存在null
元素,则以下代码也将起作用
name.removeIf("Meg"::equals);
如果不想修改旧列表,可以使用和获取通过取消条件应保留的所有项目的列表
final List<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toList());
前Java 8
问题是ArrayList在迭代过程中被修改,这会改变其大小并向前移动后面的元素;如果需要删除连续的元素,则这是一个问题。每次删除一个元素时都需要将索引减少一,因为该索引现在将引用下一个元素
for (int i = 0; i < name.size(); i++) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
i--;//Important!
}
}
通常,使用迭代器
最适合这种操作,因为它支持在通过调用迭代器#remove
进行迭代时删除元素。这也修改了列表
。对于更复杂的操作,请考虑使用<代码> ListiTror < /C> > < /P>
final Iterator<String> it = name.iterator();
while(it.hasNext()){
final String name = it.next();
if(name.equals("Meg")){
it.remove();
}
}
final Iterator it=name.Iterator();
while(it.hasNext()){
最终字符串名称=it.next();
如果(名称等于(“兆欧”)){
it.remove();
}
}
您必须使用迭代器在循环中间移除。这是经常涉及的。在今天晚上之前,我已经看过这个片段至少两次了。如果您仔细查看过去几个小时提交的java文档,您会发现许多有用的评论,这些评论将有助于您的具体案例。
final List<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toList());
final ArrayList<String> filtered = name.stream()
.filter(name -> !"Meg".equals(name))
.collect(Collectors.toCollection(ArrayList::new));
for (int i = 0; i < name.size(); i++) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
i--;//Important!
}
}
for (int i = name.size() - 1; i >= 0; i--) {
String oldName = name.get(i);
if (oldName.equals("Meg")) {
name.remove(i);
}
}
final Iterator<String> it = name.iterator();
while(it.hasNext()){
final String name = it.next();
if(name.equals("Meg")){
it.remove();
}
}