2009-11-05 140 views
1

我必须创建一个具有ArrayList的方法;我需要从这个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没有被捕获为偶数,因为它是偶数,然后我在同一位置使用不同的偶数进行测试,但结果相同。为什么在指数(3)发生的情况是任何偶数都不可能被捕获。我真的很想知道为什么。所以请任何人都可以帮我解决这个问题,还有其他更好的方法来实现这个解决方案。

谢谢

+0

您正在改变列表同时迭代它。一个简单的解决方法是在列表中向后迭代。 – 2009-11-07 01:15:57

回答

5

使用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); 
7

当您从列表中删除某些东西,其后的所有内容的索引更改!

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

我会用一个Iterator走过去列表,而不是在这个迭代删除操作,是这样的:如果您从列表中的条目,同时遍历它

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

迭代器会给你'ArrayList'的O(n^2)性能。这可能也可能不是问题。 – 2009-11-05 21:00:34

+1

交替,从结尾走回 – Mikeb 2009-11-05 21:01:58

+0

它会?听起来很奇怪...无论如何,我倾向于使用列表(忽略它是否真的是一个ArrayList或其他类型的列表),并假设迭代将会很快。它应该是,我不喜欢花时间在性能优化上,除非我有性能问题...... – 2009-11-05 21:04:06

1

,你”你必须调整你的循环索引。不要忘了,删除元素会将列表的长度减少一个,并有效地“拖回”后面的所有元素的索引。

1

问题(正如其他人所提到的)是,您在修改列表的同时遍历它。尝试添加“我 - ”;在你的“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--; 
    } 
} 
4

关于列表索引改变的两个答案都是正确的。但是,请注意,从ArrayList中删除项目很慢,因为它必须将所有下列条目实际混洗。相反,我建议创建一个仅包含偶数的新列表,然后丢弃旧列表。如果您想在其他答案中使用基于迭代器的删除代码,那么对于小型结果,以及对于较大的数据集(如果使用LinkedList)它都可以正常工作。 (我相信这是名字;我的Java无疑是有点生疏的。)

+1

你的意思是* ArrayList *。 – 2009-11-05 21:51:10

+0

@Kevin Bourrillion:你当然是对的。编辑来反映。 – 2009-11-06 08:24:57

0

这里是奇数元素的另一种漂亮的方式过滤。而不是通过手工收集的循环,卸载工作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 
    } 
}); 

这是值得商榷的,这是否实际上是更容易阅读和理解,但它更多的乐趣。如果经常使用某种谓词,它可以被重构为一个静态常量并在整个地方重用。这可以把它使用到的东西有很多清洁:

CollectionUtils.filter(numberList, ODD_PREDICATE); 
0

我该怎么办(Intelliji与科特林)

fun main(args: Array<String>) { 

var numbers = arrayList(1,2,3,4,5,6) 
println(numbers.filter{it %2 == 0}) 

} 

结果= 2,4,6