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

发布于 2024-11-03 21:15:31 字数 355 浏览 2 评论 0原文

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


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

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

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

An exercise demands that all people matching a given name parameter be removed from a List collection. The solution must use a for-each loop.


The solution presented below, does not throw any compile-time errors at me, but but it fails to pass one of the Unit tests that are run to verify the correctness of the solution.

Here is what I have tried so far:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

温柔嚣张 2024-11-10 21:15:31

哪个测试没有通过?

但让我们看一下代码:

您得到一个参数“name”。然后您迭代人员列表。当前人是i。在每个步骤中,您都会询问列表是否包含名称(这是一个字符串)。嗯。

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

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

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);
}

Which test isn't passed?

But let's look at the code:

You get a param 'name'. Then you iterate over a list of Persons. The current person is i. In each step, you ask the list, whether it contains the name (which is a String). Hm.

contains asks the whole list, whether it contains something - this something should match the typ of the elements in the list, shouldn't it?

But while iterating, you could ask each Person (i), whether the persons name is 'name'.

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

Iterating an meanwhile removing is another issue, to take care of.

Since there is much rumor, and a lot of people seemed to oversee the problem, I have a different solution, than using an interator: Collect the candidates for removing, and substract the whole blacklist as a bunch in the end:

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);
}
怼怹恏 2024-11-10 21:15:31

当然,这需要您的类有一个名为 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)

This will require that you person class has a method named getName() of course. Or you could override equals method, however beware of drawbacks as stated in the comments of this answer.

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

Returns true if this collection
contains the specified element. More
formally, returns true if and only if
this collection contains at least one
element e such that (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)

困倦 2024-11-10 21:15:31

编辑:

我的第一个答案(在线下)实际上是错误,就像迄今为止发布的所有其他答案一样。我做了一个小测试(如下)...我们都在 foreach 循环下面的迭代器中导致了 ConcurrentModificationException 。现在有一个问题要告诉你!叹。

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 方法,它返回一个字符串。

干杯。基思.

EDIT:

My first answer (below the line) is actually WRONG, just like all the others posted so far. I did-up a little test (below)... We're ALL causing a ConcurrentModificationException in the iterator which underlies the foreach loop. Now there's a gotcha for ya! Sigh.

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();
    }
  }

}

Output

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)

Dude,

THIS ANSWER IS WRONG, PLEASE IGNORE IT!!!

I suggest you use http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html#remove%28java.lang.Object%29 instead.

Something like:

public ArrayList<Person> people;

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

... presuming the Person has a getName mothod, which returns a string.

Cheers. Keith.

小ぇ时光︴ 2024-11-10 21:15:31

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

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

(来自文档

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

Don't use for-each loops if you about to remove from your list:

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

(from documentation)

Use standard iterator and its remove method instead.

心病无药医 2024-11-10 21:15:31

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

public ArrayList<Person> people;

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

I dont know how do you store the name on the Person class but maybe you could do something like this. Remember that i stores ith element on the people arraylist so each iteration you need to check for the name of the current person to check if you need to remove it

public ArrayList<Person> people;

public void remove(String name){
        for(Person i : people){
            if (i.getName().equals(name)){
                people.remove(i);
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文