无法弄清楚如何修复Iterator删除方法

时间:2015-04-15 21:21:54

标签: java iterator override iterable

因此,该程序所做的是使用Iterator方法处理ArrayList并将其打印出来。

我正在通过覆盖来创建自己的迭代器,我需要帮助的是来自Iterator的remove方法。

代码:

public class MyArrayList implements Iterable<Object> {
public static final int DEFAULT_SIZE = 5;
public static final int EXPANSION = 5;
private int capacity;
private int size;
private Object[] items;
private int currentSize;
int modCount = 0;
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;


public MyArrayList() {
    size = 0;
    capacity = DEFAULT_SIZE;
    items = new Object[DEFAULT_SIZE];
    this.currentSize = items.length;
}


@Override
public Iterator<Object> iterator() {
    Iterator<Object> it = new Iterator<Object>() {
        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
        try { return currentIndex <= currentSize && items[currentIndex] != null;
        }catch(NoSuchElementException e){
            System.out.println("There is nothing in the next element.");
        }
            return currentIndex <= currentSize && items[currentIndex] != null;
        }

        @Override
        public Object next() {
            checkForComodification();
            try{
        }catch(NoSuchElementException e){
            System.out.println("There is nothing in the next element.");
        }
            return items[currentIndex++];
        }

        @Override
        public void remove(){
            if (lastRet< 0)
                throw new IllegalStateException();
            checkForComodification();
        try {
            MyArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        }catch (IndexOutOfBoundsException e){
            throw new ConcurrentModificationException();
            }

        }

    final void checkForComodification(){
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }


    };
    return it;
}


private void expand() {
    Object[] newItems = new Object[capacity + EXPANSION];
    for (int j = 0; j < size; j++) newItems[j] = items[j];
    items = newItems;
    capacity = capacity + EXPANSION;
}

public void add(Object obj) {
    try {
        if (size >= capacity) this.expand();
        items[size] = obj;
        size++;
    } catch (IndexOutOfBoundsException e) {
        System.out.println("There is an error adding this word." + e.getMessage());
    }
}

public int size() {
    return size;
}

public Object get(int index) {
    try {
        return items[index];
    }catch (ArrayIndexOutOfBoundsException e){
        System.out.println("ERROR- Cannot GET element. Index is out of range. Position: " +e.getMessage());
    }
    return items[index];
}


public boolean contains(Object obj) {
    for (int j = 0; j < size; j++) {
        if (obj.equals(this.get(j))) return true;
    }
    return false;
}

public void add(int index, Object obj) {
    try {
        if (size >= capacity) this.expand();
        for (int j = size; j > index; j--) items[j] = items[j - 1];
        items[index] = obj;
        size++;
    }catch (IndexOutOfBoundsException e){
        System.out.println("ERROR- Cannot ADD element. Index out of range. Position: " +e.getMessage()+".");
    }
}

public int indexOf(Object obj) {
    for (int j = 0; j < size; j++) {
        if (obj.equals(this.get(j))) return j;
    }
    return -1;
}

public boolean remove(Object obj) {
    for (int j = 0; j < size; j++) {
        if (obj.equals(this.get(j))) {
            for (int k = j; k < size - 1; k++) items[k] = items[k + 1];
            items[size] = null;
            size--;
            return true;
        }
    }
    return false;
}

public Object remove(int index) {
    try {
        Object result = this.get(index);
        for (int k = index; k < size - 1; k++) items[k] = items[k + 1];
        items[size] = null;
        size--;
        return result;
    }catch(IndexOutOfBoundsException e){
        System.out.print("ERROR- Cannot REMOVE element. Index out of range. Position: " + e.getMessage());
    }
    return null;
}

public void set(int index, Object obj) {
    try {
        items[index] = obj;
    }catch (IndexOutOfBoundsException e){
        System.out.println("ERROR- Cannot SET word.. Index out of range. Position: "+e.getMessage());
    }
}

}

主要方法代码:

class Task4Test {

static MyArrayList zoo = new MyArrayList();


public static void printZoo() {
    System.out.print("The zoo now holds " + zoo.size() + " animals: ");
    for (int j = 0; j < zoo.size(); j++) System.out.print(zoo.get(j) + " ");
    System.out.println();
}
public static void main(String[] args) {

    String[] zooList = {"Cheetah", "Jaguar", "Leopard", "Lion", "Panther", "Tiger"};

    for (String x: zooList) zoo.add(x);
    printZoo();

    System.out.printf("\nTesting the iterator\n>> ");
    Iterator it = zoo.iterator();
    while (it.hasNext()) {
        System.out.print(it.next() + " ");
    }
    System.out.println();

    System.out.printf("\nTesting the iterator again without resetting\n>> ");
    while (it.hasNext()) {
        System.out.print(it.next() + " ");
    }
    System.out.println();

    System.out.printf("\nTesting the iterator again after resetting\n>> ");
    it = zoo.iterator();
    while (it.hasNext()) {
        System.out.print(it.next() + " ");
    }
    System.out.println();

    System.out.printf("\nTesting for-each loop\n>> ");
    for(Object animal: zoo) System.out.print(animal + " ");
    System.out.println();

    System.out.println("\nLetting all the animals escape");
    while (zoo.size()>0) zoo.remove(0);
    printZoo();

    System.out.printf("\nTesting the iterator with an empty list\n>> ");
    it = zoo.iterator();
    while (it.hasNext()) {
        System.out.print(it.next() + " ");
    }
    System.out.println();

    System.out.println("\nTest complete");


}

}

现在打印出来:      动物园现在拥有6只动物:Cheetah Jaguar Leopard Lion Panther Tiger

 Testing the iterator
 >> Cheetah Jaguar Leopard Lion Panther Tiger 

 Testing the iterator again without resetting
 >> //Is it supposed to be empty like this? (read below)

 Testing the iterator again after resetting
 >> Cheetah Jaguar Leopard Lion Panther Tiger 

 Testing for-each loop
 >> Cheetah Jaguar Leopard Lion Panther Tiger 

 Letting all the animals escape
 The zoo now holds 0 animals: 

Testing the iterator with an empty list
>> Tiger //This is the main problem i'm trying to fix.

所以出于某种原因,老虎总是不断打印。即使我改变了不同方法的负载。我觉得它可能与Object remove(int index)方法有关。

此外,我理解在“没有重置的迭代器”部分之后应该没有任何东西,但是我的代码不应该有一个异常,说“下一个元素中没有任何东西”?

1 个答案:

答案 0 :(得分:1)

hasNext()行为

您的hasNext()方法的行为与编程完全一致 - 在try块中返回条件的结果,因此它只会返回false,因此会返回您尝试的循环永远不会输入通过迭代器而不重置。不会抛出Exception

编辑:回复评论

让我们更详细地剖析一下 - 您当前的方法是:

@Override
public boolean hasNext() {
    try { 
        return currentIndex <= currentSize && items[currentIndex] != null;
    }
    catch(NoSuchElementException e) {
        System.out.println("There is nothing in the next element.");
    }

    return currentIndex <= currentSize && items[currentIndex] != null;
}
try块中的

,您可以有效地执行两次比较,每次比较都会boolean,然后&&将它们放在一起并返回结果。第一个是

currentIndex <= currentSize

这可能是检查迭代器是否超出列表的“结尾”。如果false不大于currentIndex,则会评估currentSize。事实上,我认为这是错误的,因为currentSize似乎是在施工时设置的,并且从未改变过,但这不是重点。

第二个是

items[currentIndex] != null

如果currentIndex未超出items的结尾,则items[currentIndex]的值将仅针对null进行测试。 Exception被抛出的唯一情况是currentIndex >= items.length。但请注意,此处抛出的异常不是NoSuchElementException,而是ArrayIndexOutOfBoundsExceptionNoSuchElementException抛出了Enumeration(通常在标准语言库中)。

最后,你&&这些在一起。现在,这对于完整性来说是一个有点棘手的部分。由于the way that && is evaluated in Java - 如果第一个条件是false,则第二个条件永远不会被评估。因此,如果第一个条件是false,则函数会立即返回false。如果第一个是true,则函数返回第二个值。

所以,实际上,这里的try...catch构造完全是多余的,因为返回中的条件不会失败,即使它发生了,它也不会抛出你正在捕获的Exception类型无论如何。此外,该方法中的第二个return语句是多余的,并且正在评估与try中的那个完全相同的扩展,所以如果那个失败,那么第二个也是如此。

最后,但并非最不重要的一点是,您应该知道,您的特定实现中依赖于items的大小来抛出Exception的任何内容都可能是错误的 - 因为{{1} }并不限于与items.length相同。当size null中的值时,您不会从数组中“删除”它们 - 所以引用它们不会抛出items,它只会引用一个值Exception

null行为

你的remove(int index)没有按照你的意愿行事,因为你在remove(int index)减去items[size]反转这两个陈述之前将该元素归零,它应该按照你想要的方式工作

最终评论

我已经解决了你的直接问题。但是 - 您的实施中还有其他错误,例如sizenext()时,请尝试拨打hasNext()。您将获得false。我认为您打算满足ArrayIndexOutOfBoundsException接口规范并抛出Iterator

怀疑你从根本上误解了NoSuchElementException概念以及try...catch。您的代码应该投掷 throw,而不是尝试NoSuchElementException - 毕竟会产生什么?我认为值得阅读Oracle tutorial on Exceptions,try...catch,throw etc.,可能会问另一个问题,或者问你的导师。

简而言之 - 你在这里有两件事 - 你有底层的代码可以检测发生的令人讨厌的事情并产生异常,例如。

catch

然后你有其他代码使用可能抛出异常的功能/方法

a)允许向前抛出异常,或

b)(你的情况)捕获异常并用它做其他事情 - 例如

public Object get(int index) throws NoSuchElementException
{
    // error check for -ve index and throw exception if detected
    if (index < 0)
    {
         throw new NoSuchElementException();
    }

    //code to do the real processing if index is correct
}