【问题标题】:Removing name if case matches from ArrayList not working [duplicate]如果 ArrayList 中的大小写匹配不起作用,则删除名称 [重复]
【发布时间】:2020-07-01 17:56:35
【问题描述】:

我正在尝试编写一个程序,如果名称具有特定值,它将从 ArrayList 中删除名称,但我无法做到这一点。

class UserNamesTest {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>();
        names.add("John");
        names.add("Jerry");
        names.add("Jim");
        names.add("Todd");

        for(String name : names) {
            if(name.equals("John")) {
                System.out.println("true");
                names.remove(names.indexOf(name));
            }
        }
    }
}

当我执行这段代码时,我得到一个异常:

Exception in thread "main" java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
        at java.util.ArrayList$Itr.next(Unknown Source)
        at UserNamesTest.main(UserNamesTest.java:13)

我怎样才能做到这一点?

【问题讨论】:

标签: java list algorithm for-loop arraylist


【解决方案1】:

使用迭代器不要对您正在迭代的List 进行操作:

Iterator<String> iterator = names.iterator();
while(iterator.hasNext()) {
    String name iterator.next();
    if(name.equals("John")) {
        System.out.println("true");
        iterator.remove();
    }
}

【讨论】:

    【解决方案2】:

    除了使用Iterator,使用java-8,你可以做如下,

    names = names.stream()
                 .collect(Collectors.partitioningBy(e->e.equals("John")))
                 .get(false);
    

    或使用过滤器更具可读性,

    names = names.stream()
                 .filter(e->e.equals("John"))
                 .collect(Collectors.toList());
    

    【讨论】:

    • 我宁愿使用过滤器,这种方式不可读。此外,在创建包含我们想要的元素列表的地图以及其余部分时,会产生开销。
    【解决方案3】:

    使用 Java8 或 11,您可以:

    class UserNamesTest {
        public static void main(String[] args) {
            ArrayList<String> names = new ArrayList<>();
            names.add("John");
            names.add("Jerry");
            names.add("Jim");
            names.add("Todd");
    
            List<String> namesWithoutJohn = names.stream()
                    .filter(((Predicate<String>)("John"::equals)).negate()) // Java 8
    //                .filter(Predicate.not("John"::equals)) // Java 11
                    .collect(Collectors.toList());
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      因为当这种修改是不允许的java doc时,检测到对象的并发修改的方法可能会抛出此异常。 在您的列表中使用removeIf

              ArrayList<String> names = new ArrayList<>();
              names.add("John");
              names.add("Jerry");
              names.add("Jim");
              names.add("Todd");
              names.removeIf(name->name.equals("John"));
      

      或者直接使用Iterator

              Iterator<String> iter = names.iterator();
              while (iter.hasNext()) {
                  String str = iter.next();
                  if (str.equals("John"))
                      iter.remove();
              }
      

      请注意,Iterator.remove() 是在迭代期间修改集合的唯一安全方法。more about iterator

      【讨论】:

        【解决方案5】:

        使用索引遍历列表以删除项目时要小心。因为物品在移动后会移动,您可能会错过其中的一些。这是一个例子:

               ArrayList<String> names = new ArrayList<>();
               names.add("Jerry");
               names.add("Jim");
               names.add("John");
               names.add("John");
               names.add("Todd");
        
               for(int i = 0; i < names.size(); i++) {
                   String name = names.get(i);
                   if(name.equals("John")) {
                       names.remove(i);
                   }
               }
        
               names.forEach(System.out::println);   
        

        打印

        Jerry
        Jim
        John  <-- wasn't removed
        Todd
        

        如果您打算这样做,请从最后一项开始,因为删除一项不会影响后续位置。

               names = new ArrayList<>();
               names.add("Jerry");
               names.add("Jim");
               names.add("John");
               names.add("John");
               names.add("Todd");
        
               for (int i = names.size() -1; i >= 0; i--) {
                   String name = names.get(i);
                   if(name.equals("John")) {
                       names.remove(i);
                   }
               }
        
               names.forEach(System.out::println);   
        

        打印

        Jerry
        Jim
        Todd
        

        但我更喜欢使用以下方法:

        names.removeIf(name->name.equals("John"));
        

        一个语句就能得到所有这些。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-09-12
          • 2021-12-26
          • 1970-01-01
          • 2013-06-03
          • 2019-11-25
          • 1970-01-01
          • 1970-01-01
          • 2021-08-13
          相关资源
          最近更新 更多