从名称字段与给定参数匹配的List中删除Person的所有实例

时间:2011-04-27 22:54:27

标签: java collections iteration concurrentmodification

练习要求从List集合中删除匹配给定名称参数的所有人。解决方案必须使用for-each循环。


下面给出的解决方案不会给我带来任何编译时错误,但是它无法通过运行的单元测试之一来验证解决方案的正确性。

这是我到目前为止所尝试的内容:

public ArrayList<Person> people;
public void remove(String name){
    for(Person i : people){
        if (people.contains(name)){
            people.remove(i);
        }
    }
}

5 个答案:

答案 0 :(得分:4)

哪个测试未通过?

但是让我们来看看代码:

你得到一个参数'name'。然后迭代一个人员列表。现在的人就是我。在每个步骤中,您询问列表,它是否包含名称(这是一个字符串)。嗯。

包含询问整个列表,是否包含某些东西 - 这个东西应该匹配列表中元素的类型,不应该吗?

但是在迭代时,您可以询问每个人(i),人名是否是“姓名”。

if (i.name.equals (name)) // or 
if (i.getName ().equals (name))

迭代同时删除是另一个问题,要照顾。

由于有很多谣言,并且很多人似乎都在监督这个问题,我有一个不同的解决方案,而不是使用一个交互者:收集候选人进行删除,并将整个黑名单最终减为一堆:< / p>

public void remove (String name) 
{
    List <Person> blacklist = new ArrayList <Person> ();
    for (Person p : people) 
    {
        if (p.getName ().equals (name))
        {
            blacklist.add (p);
        }
    }
    people.removeAll (blacklist);
}

答案 1 :(得分:1)

如果要从列表中删除,请不要使用for-each循环:

the for-each loop hides the iterator, so you cannot call remove. 

from documentation

改为使用standard iterator及其remove方法。

答案 2 :(得分:1)

这将要求您的person类当然有一个名为getName()的方法。或者你可以覆盖equals方法,但要注意这个答案的评论中所述的缺点。

public void remove(String name) {
for (Person person : people) {
    if (person.getName().equals(name)) {
        people.remove(person);
    }
}
  

如果此集合返回true   包含指定的元素。更多   正式地,当且仅当如果,则返回true   此集合包含至少一个   元素e使得(o == null?e == null   :o.equals(e))。

http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collection.html#contains(java.lang.Object

答案 3 :(得分:1)

修改

我的第一个答案(在线下)实际上是错误,就像到目前为止发布的所有其他答案一样。我做了一点测试(下面)...我们在迭代器中导致了一个 ConcurrentModificationException ,它是foreach循环的基础。现在有一个问题!叹。

package forums;

import java.util.List;
import java.util.ArrayList;

class Person
{
  private final String name;
  private final int age;
  Person(String name, int age) {
    this.name=name;
    this.age=age;
  }
  public String getName() { return name; }
  public int getAge() { return age; }
  public String toString() { return name + " " + age; }
}

public class PeopleTest
{
  public List<Person> people;

  public void remove(String name)
  {
    for ( int i=0; i<people.size(); i++ ) {
      Person person = people.get(i);
      if (person.getName().equals(name)) {
        people.remove(person);
        i--;
      }
    }
  }

  public void badRemove(String name)
  {
    for ( Person person : people ) {
      if (person.getName().equals(name)) {
        people.remove(person);
      }
    }
  }

  public void printAll(String message) {
    System.out.println(message);
    for ( Person person : people ) {
      System.out.println("  " + person);
    }
  }


  public void run() 
  {
    // setup
    people = new ArrayList<Person>(5);
    Person dave, kelly, jack, jill, xavier;
    people.add(dave=new Person("Dave", 36));
    people.add(kelly=new Person("Kelly", 25));
    people.add(jack=new Person("Jack", 42));
    people.add(jill=new Person("Jill", 19));
    xavier = new Person("Xavier", 136);

    badRemove("Dave");

    // before image
    assert people.size() == 4;
    printAll("the before list");

    // operation 1
    assert !people.contains(xavier);
    remove("Xavier"); // a no-op.
    assert people.size() == 4;
    assert !people.contains(xavier);

    // operation 2
    assert people.contains(jill);
    remove("Jill"); // she smells!

    // after image
    printAll("the after list");
    assert people.size() == 3;
    assert people.contains(dave);
    assert people.contains(kelly);
    assert people.contains(jack);
    assert !people.contains(jill);
  }

  public static void main(String[] args) {
    try {
      new PeopleTest().run();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

输出

C:\Java\home\src\forums>"C:\Program Files\Java\jdk1.6.0_16\bin\java.exe" -Xms4m -Xmx256m -enableassertions -cp c:\java\home\src;C:\Java\home\classes; forums.PeopleTest
java.util.ConcurrentModificationException
        at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
        at java.util.AbstractList$Itr.next(AbstractList.java:343)
        at forums.PeopleTest.badRemove(PeopleTest.java:36)
        at forums.PeopleTest.run(PeopleTest.java:62)
        at forums.PeopleTest.main(PeopleTest.java:89)

哥们,

这个答案错了​​,请不要这么做!!!

我建议你改用http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html#remove%28java.lang.Object%29

类似的东西:

public ArrayList<Person> people;

public void remove(String name) {
  for ( Person person : people ) {
    if (person.getName().equals(name)) {
      people.remove(person);
    }
  }
}

...假设Person有一个getName方法,它会返回一个字符串。

干杯。基思。

答案 4 :(得分:-3)

我不知道你如何在Person类上存储名称,但也许你可以做这样的事情。请记住,我将iith元素存储在人员arraylist上,因此每次迭代都需要检查当前人员的姓名以检查是否需要删除它

public ArrayList<Person> people;

public void remove(String name){
        for(Person i : people){
            if (i.getName().equals(name)){
                people.remove(i);
            }
        }
    }