-6

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


下面介绍的解决方案不会向我抛出任何编译时错误,但它未能通过运行以验证解决方案正确性的单元测试之一。

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

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

5 回答 5

4

哪个考试没通过?

但是让我们看一下代码:

你得到一个参数'name'。然后你遍历一个 Person 列表。现在的人是i。在每一步中,您都会询问列表,它是否包含名称(它是一个字符串)。嗯。

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

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

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

迭代同时删除是另一个需要处理的问题。

由于谣言很多,而且似乎很多人都在监督这个问题,所以我有一个与使用交互器不同的解决方案:收集要删除的候选人,最后将整个黑名单减去一堆:

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);
}
于 2011-04-27T23:04:54.150 回答
1

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

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

来自文档

请改用标准迭代器及其remove方法。

于 2011-04-27T23:15:50.963 回答
1

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

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

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

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

于 2011-04-27T23:22:53.660 回答
1

编辑:

我的第一个答案(线下)实际上是WRONG,就像迄今为止发布的所有其他人一样。我做了一个小测试(如下)......我们都在迭代器中导致了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方法,它返回一个字符串。

干杯。基思。

于 2011-04-27T23:24:52.157 回答
-3

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

public ArrayList<Person> people;

public void remove(String name){
        for(Person i : people){
            if (i.getName().equals(name)){
                people.remove(i);
            }
        }
    }
于 2011-04-27T23:00:10.400 回答