因此,该程序所做的是使用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)方法有关。
此外,我理解在“没有重置的迭代器”部分之后应该没有任何东西,但是我的代码不应该有一个异常,说“下一个元素中没有任何东西”?
答案 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
,而是ArrayIndexOutOfBoundsException
。 NoSuchElementException
抛出了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]
反转这两个陈述之前将该元素归零,它应该按照你想要的方式工作
我已经解决了你的直接问题。但是 - 您的实施中还有其他错误,例如size
为next()
时,请尝试拨打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
}