【问题标题】:Remove even numbers from an ArrayList从 ArrayList 中删除偶数
【发布时间】:2009-11-05 20:53:55
【问题描述】:

我必须创建一个具有 ArrayList 的方法;我需要从这个 ArrayList 中删除偶数。我已经为此编写了代码,但是有一个我无法识别的逻辑错误。

这是我的代码:

static void sortList(){

   List <Integer> number=new ArrayList <Integer>();

   number.add(11);
   number.add(45);
   number.add(12);
   number.add(32);
   number.add(36);

   System.out.println("Unsorted List: "+number);

   for (int i=0;i<number.size();i++){      
       int even=number.get(i)%2;       
        if (even==0){
            System.out.println("This is Even Number:"+ number.get(i));
            number.remove(i);
        }    
    }

    Collections.sort(number);
    System.out.println("Sorted List: "+number);

 }

代码的输出是:

Unsorted List: [11, 45, 12, 32, 36]
This is Even Number:12
This is Even Number:36
Sorted List: [11, 32, 45]

我想知道为什么 32 不是偶数,因为它是偶数,然后我在同一位置使用不同的偶数进行了测试,但结果是相同的。为什么在 index(3) 发生任何偶数都无法捕获。我真的很想知道为什么。所以请任何人都可以帮助我解决这个问题,还有其他更好的方法来实现这个解决方案。

谢谢

【问题讨论】:

  • 您在迭代列表时正在更改列表。一个简单的解决方法是向后迭代列表。

标签: java collections arraylist


【解决方案1】:

使用Iterator。它有一个您需要的remove() 方法。

List<Integer> numbers = new ArrayList<Integer>();

numbers.add(11);
numbers.add(45);
numbers.add(12);
numbers.add(32);
numbers.add(36);

System.out.println("Unsorted List: " + numbers);

for (Iterator<Integer> iterator = numbers.iterator(); iterator.hasNext();) {
    Integer number = iterator.next();
    if (number % 2 == 0) {
        System.out.println("This is Even Number: " + number);
        iterator.remove();
    }

}

Collections.sort(numbers);
System.out.println("Sorted List: " + numbers);

【讨论】:

    【解决方案2】:

    当您从列表中删除某些内容时,之后所有内容的索引都会更改!

    具体来说,在您的实现中,32 不会被删除,因为它紧跟在另一个偶数之后。

    我会使用迭代器遍历列表,然后使用该迭代器上的删除操作,如下所示:

    for(Iterator i = number.iterator(); i.hasNext(); ) {
        if (isEven(i.next()) {
            i.remove();
        }
    }
    

    【讨论】:

    • 对于ArrayList,迭代器将为您提供 O(n^2) 性能。这可能是也可能不是问题。
    • 或者,从末端向后走
    • 会吗?听起来很奇怪......无论如何,我倾向于使用 List (忽略它是否真的是一个 ArrayList 或某种其他类型的 List)并假设迭代会很快。应该是,而且我不喜欢花时间在性能优化上,除非我有性能问题……
    • 数组列表的删除会很慢,但这不是迭代器的错。
    • @Tom Hawtin:无论您如何操作,ArrayList 的删除都将是 O(n^2)。但是初学者应该知道,使用索引来迭代 LinkedList 会给你 O(n^2) 的性能,但使用迭代器总是 O(n) - 我已经无数次看到这个错误......
    【解决方案3】:

    关于列表索引更改的两个答案都是正确的。但是,还要注意从 ArrayList 中删除项目很慢,因为它实际上必须将以下所有条目打乱。相反,我建议创建一个仅包含偶数的新列表,然后丢弃旧列表。如果您想在另一个答案中使用基于迭代器的删除代码,它可以很好地处理小的结果,如果您使用 LinkedList,它也可以用于更大的数据集。 (我相信这就是名字;我的 Java 确实有点生疏了。)

    【讨论】:

    • @Kevin Bourrillion:你当然是对的。编辑反映。
    【解决方案4】:

    如果在循环遍历列表时从列表中删除条目,则必须调整循环索引。别忘了,移除元素会将列表的长度减一,并有效地“洗牌”之后所有元素的索引。

    【讨论】:

      【解决方案5】:

      问题(正如其他人所提到的)是您在遍历列表时正在修改它。尝试添加“i--;”在“if (even==0)”块内的行。像这样:

      for (int i=0;i<number.size();i++){
          int even=number.get(i)%2;
      
          if (even==0){
              System.out.println("This is Even Number:"+ number.get(i));
              number.remove(i);
      
              // Add this:
              i--;
          }
      }
      

      【讨论】:

        【解决方案6】:

        这是另一种过滤奇数元素的好方法。与其手动循环遍历集合,不如将工作卸载到Apache Commons Collections

         // apply a filter to the collection
         CollectionUtils.filter(numbers, new Predicate() {
             public boolean evaluate(Object o) {
                 if ((((Integer) o) % 2) == 0) { 
                     return false;  // even items don't match the filter
                 }
                 return true;  // odd items match the filter
             }
         });
        

        这是否真的更容易阅读和理解还有待商榷,但它更有趣。如果某种 Predicate 被频繁使用,它可以被重构为一个静态常量并在所有地方重用。这可以将它的使用变成更清洁的东西:

        CollectionUtils.filter(numberList, ODD_PREDICATE);
        

        【讨论】:

          【解决方案7】:

          我做什么(使用 kotlin 的 Intelliji)

          fun main(args: Array<String>) {
          
           var numbers = arrayList(1,2,3,4,5,6)
           println(numbers.filter{it %2 == 0})
          
          }
          

          结果=2,4,6

          【讨论】:

            【解决方案8】:
            public class RemoveEvenUsingAL {
            
                public static void main(String[] args) {
                    List<Integer> list= new ArrayList<Integer>();
            
                    list.add(1);
                    list.add(2);
                    list.add(3);
                    list.add(4);
                    list.add(5);
                    list.add(6);
            
                    Iterator<Integer> it = list.iterator();
                    while(it.hasNext()){
                        Integer number= it.next();
                        if(number % 2 ==0){
                            it.remove();
                        }
                    }
                    System.out.println("ArryList Odd Number="+list);
                }
            }
            

            【讨论】:

            • 欢迎来到 Stack Overflow!虽然此代码可能会回答问题,但最好在您的答案中包含一些 cmets。特别是您的答案与现有答案有何不同。
            【解决方案9】:

            我们可以在ArrayList类中使用removeIf默认方法。

                 List <Integer> number=new ArrayList <Integer>();
            
                   number.add(11);
                   number.add(45);
                   number.add(12);
                   number.add(32);
                   number.add(36);
            
                   number.removeIf(num -> num%2==0);
            
                   System.out.println(number);
            

            【讨论】:

              猜你喜欢
              • 2016-01-31
              • 2017-02-06
              • 1970-01-01
              • 1970-01-01
              • 2019-12-31
              • 2022-12-21
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多