使用ListIterator修改LinkedList(每个节点2个整数)

时间:2017-06-30 15:42:20

标签: java linked-list listiterator

我正在编写一个代码来保存,删除和加载一个人的身高和体重数据。我创建了两个类:

class Person {
    private int height;
    private int weight;

    public Person(int h, int w) {
        height = h;
        weight = w;
    }

    public int getHeight() {
        return height;
    }

    public int getWeight() {
        return weight;
    }

    public String getValues() {
        return ("Height "+height+" and weight "+weight);
    }
}


class DataModified {        //Problem in this class
    private LinkedList<Person> lList;
    private ListIterator<Person> lIter;

    public DataModified() {
        lList = new LinkedList<Person>();
        lIter = lList.listIterator();
    }

    public void save(Person p) {        
        Person p1, p2;                                  //p1: Data needed to be saved
        p1 = new Person(p.getHeight(), p.getWeight());  //p2: Data already on the list
        boolean alreadyExist = false;
        lIter = lList.listIterator();
        while(lIter.hasNext()) {        
            p2 = lIter.next();      
            if ((p2.getHeight() == p1.getHeight()) && (p2.getWeight() == p1.getWeight())) {
                alreadyExist = true;        
            }
        }
        if(alreadyExist) {
            System.out.println("Person: " + p1.getValues() + " had already been on the list.");
        }
        else {
            lIter.add(p1);
            System.out.println("Person: " + p1.getValues() + " is added to the list.");
        }
    }

    public void delete(Person p) {
        Person p3, p2;                                  //p3: Data needed to be deleted
        p3 = new Person(p.getHeight(), p.getWeight());  
        boolean alreadyExist = false;
        lIter = lList.listIterator();
        while(lIter.hasNext()) {        
            p2 = lIter.next();      
            if ((p2.getHeight() == p3.getHeight()) && (p2.getWeight() == p3.getWeight())) {
                alreadyExist = true;        
            }
        }
        if(alreadyExist) {
            lIter.remove();
            System.out.println("Person: " + p3.getValues() + " is deleted from the list.");
        }
        else {
            System.out.println("Person: " + p3.getValues() + " is not on the list.");
        }
    }

    public void load() {            //Problem
        lIter = lList.listIterator();
        Person p2;
        for(int i = 1; lIter.hasNext(); i++){
            p2 = lIter.next();
            System.out.println("Person "+i+" has "+p2.getValues());
        }
    }
}

我已经从班级DataModified测试了这3个方法:我首先保存3个人的数据,然后删除1个人并加载其余的人。但是,最后一种方法不会打印列表中的2个人,而是打印之前删除的人。

我的问题是:

  1. 我的代码出了什么问题?为什么load()方法的工作方式如此?
  2. 我注意到迭代后,我只能修改lIter。那么lListlIter是相同的列表还是2个单独的列表?如果它们不相同,我如何从lList
  3. 提供lIter数据
  4. 有没有办法停止列表的迭代?

4 个答案:

答案 0 :(得分:2)

正如其他人指出的那样,您的delete方法肯定存在错误。如上所述,如果在列表中找到目标Person,则将删除列表中的最后一个Person,而不是目标。当你找到这个人并立即将其删除而不是继续循环时,你真的需要能够切断while循环。

回答你的问题:

  1. 出了什么问题?删除中删除错误Person的错误。

  2. lListlIter列表相同吗?概念上是,技术上没有。 lList是列表本身,lIter是作用于该列表的迭代器。它本身不是一个列表。它是一个迭代器。但它所处理的数据绝对是同一个列表。

  3. 如何停止迭代?你有几个选择。目前编写代码的最简单方法是break语句。它停止执行当前循环并继续在块外执行。在你的添加和删除方法中,在alreadyExist设置为true后立即断开是有意义的。 jiveturkey首先建议的另一个选项是将alreadyExist添加为while循环的条件。然后,如果有更多项目要迭代并且alreadyExist尚未设置为true,那么您只会继续迭代。第三种选择是在找到Person后立即进行实际工作(即删除),然后完全从方法返回。

  4. 除此之外,还有一些未经请求的一般建议:)

    • 您在多种方法中比较Person对象。随着时间的推移,这将难以维护,因此最好在一个地方定义比较。 Java为此提供了equals方法。它位于每个Object中,但默认实现不会帮助您,因此您希望覆盖它。在您的情况下,如果它们的高度和权重相等,则认为两个不同的Person对象在概念上是相等的。因此,如果高度和重量相等,则覆盖Person中的equals()方法以返回true。有关提示,请参阅How to override equals method in javahttp://users.csc.calpoly.edu/~gfisher/classes/102/info/howToOverrideEquals.html。如果您覆盖equals,则还需要覆盖hashCode

    • 您正在复制Person参数。传入的确切对象不是从列表中添加或删除的实际对象;副本是。你可以使用paremeter。在最好的情况下,您目前有不必要的性能损失(创建额外的对象)。在最糟糕的情况下,你会遇到错误。

    • lIter在构造函数和每个方法中都设置。如果您不需要跨方法调用存储其当前状态,那么它应该只是一个局部变量,用于方法然后丢弃。

    • getValues()目前仅用于使对象具有人类可读性。这是一个常见问题,也是toString()的任务,也在Object中定义,并且在您编写的任何类中都可以覆盖。您需要做的就是将getValues重命名为toString。然后你可以直接在日志消息中使用它。以下示例。

    这是我如何重写删除,假设equals中的Person方法很好,getValues重命名为toString

    public void delete(Person p) {
        boolean alreadyExist = false;
        ListIterator definitelyNotLIter = lList.listIterator();
        while(definitelyNotLIter.hasNext()) {        
            Person current = definitelyNotLIter.next();      
            if (p.equals(current)) {
                alreadyExist = true;
                definitelyNotLIter.remove();
    
                // Option 1:
                break;  // next line to execute will be the if(alreadyExist) block
    
                // Option 2:
                // put your successful delete logging here
                // return;
                // and leave the failed delete logging outside the loop
    
                // Option 3:
                // Do nothing. The looping will continue, and you'd have a deleteAll method, where multiple items would get deleted if you managed to get duplicates in the list.
                // You actually wouldn't need alreadyExist any more.
    
                // I'd go with option 1, myself
            }
        }
        if(alreadyExist) {
            System.out.println("Person: " + p + " is deleted from the list."); // p.toString() will get called
        }
        else {
            System.out.println("Person: " + p + " is not on the list."); // p.toString() will get called
        }
    }
    

答案 1 :(得分:1)

delete()中,一旦找到了您的个人,就会在第一次找到某人并继续前进时将alreadyExist设置为true。因此,一旦设置好,它就会为每个人设置。如果您在位置1的列表中找到您的人员,则您将删除他,但之后您将删除下一个人,依此类推。你所有的while循环都需要说。

while (!alreadyExists && lIter.hasNext()) {        
    p2 = lIter.next();      
    if ((p2.getHeight() == p1.getHeight()) && (p2.getWeight() == p1.getWeight())) {
            alreadyExist = true;
            lIter.remove();
        }
    }

    // Delete the if/else code

你应该摆脱成员变量:

private ListIterator<Person> lIter;

答案 2 :(得分:0)

问题在于您的delete方法:

在删除任何内容之前,您将遍历整个列表。 ListIterator.remove only deletes the last item returned by next()。当您找到已存在的项目时,您需要中断:

while(lIter.hasNext()) {        
    p2 = lIter.next();      
    if ((p2.getHeight() == p3.getHeight()) && (p2.getWeight() == p3.getWeight())) {
        alreadyExist = true;   
        break;     
    }
}

此外,您要比较Person对象的方式应该采用equals()方法,described here

最后,您在这里完全没有必要创建/使用与参数Person重复的额外p。只需使用p代替p1save}和p3delete)。

答案 3 :(得分:0)

来自Documentation

  

void remove()从列表中删除返回的 最后 元素   by next()或previous()

当您到达所需的Person对象时,您会继续迭代下一个 Person对象。

找到目标对象后,您需要 break while循环。

if ((p2.getHeight()==p3.getHeight())&&(p2.getWeight()==p3.getWeight())){
      alreadyExist = true;
      break;        
}

现在最后一个元素是必需的对象,现在可以使用remove()

if(alreadyExist) {lIter.remove();}