拥有泛型对类的迭代器



我正在尝试为我自己的泛型类编写自己的迭代器。我一直在看几个YouTube教程并搜索网络。

import java.util.Iterator;
import java.util.NoSuchElementException;
public class Pair<T> implements Iterable<T> {
private T left;
private T right;
public Pair(T left, T right){
this.left = left;
this.right = right;
}
public  T getRight(){return this.right;}
public  T getLeft(){return this.left;}
// own Iterator
@Override
public Iterator<T> iterator() {
return new myIterator;
}

class myIterator implements Iterator<T>{
T newLeft = null;
@Override
public boolean hasNext() {
if(newLeft == null && Pair.getLeft() != null){
return true;
}
else if(newLeft !=null){
return Pair.getRight() !=null;
}
else {
return false;
}
}
@Override
public T next() {
if(newLeft == null && Pair.getLeft() != null){
newLeft = Pair.getLeft();
return newLeft;
}
else if(newLeft != null){
T newRight = Pair.getLeft();
newLeft = Pair.getRight();
return newRight;
}
throw new NoSuchElementException();
}
}
}

IntelliJ 指出的问题是,我不能像我尝试的那样在迭代器类中使用 getLeft 和 getRight,因为非静态方法不能从静态上下文中引用。我一直在深入研究静态和更多,但无法解决这个问题。我是否完全走错了轨道,或者我的方法至少有点接近?

更新

运行时:

public static void main(String[] args) {
Pair<Integer> intPair= new Pair(5,1);
Pair<String> stringPair=new Pair("foo", "bar");
Iterator<Integer> itr= intPair.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}

我遇到了一个无休止的循环,打印 5。所以,迭代器本身是有效的,但我的方法有一个逻辑错误。正在努力,但我感谢任何投入。:)

UPDATE2

发现逻辑错误:NewLeft 永远不会从空变为空。努力解决它。

UPDATE3

:解决! 具有嵌入式迭代器类的完整配对类和具有以下调用的主类:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Pair<T> implements Iterable<T> {
private T left;
private T right;
public Pair(T left, T right){
this.left = left;
this.right = right;
}
public  T getRight(){return this.right;}
public  T getLeft(){return this.left;}
// size of a pair is always 2
public int size =2;
// own Iterator
@Override
public Iterator<T> iterator() {
return new myIterator();
}
// embedded iterator class
public class myIterator implements Iterator<T>{
T newLeft = null;
T newRight = null;
@Override
public boolean hasNext() {
if(newLeft == null && getLeft() != null){
return true;
}
else if(newLeft !=null && newRight == null){
newRight=getRight();
return getRight() !=null;
}
else {
return false;
}
}
@Override
public T next() {
if(newLeft == null && getLeft() != null){
newLeft = getLeft();
return newLeft;
}
else if(newLeft != null && getRight() != null){
newRight = getRight();
return newRight;
}
throw new NoSuchElementException();
}
}
}

主要:

import java.util.Iterator;
public class main {
public static void main(String[] args) {
Pair<Integer> intPair= new Pair(5,1);
Pair<String> stringPair=new Pair("foo", "bar");
Iterator<Integer> itr= intPair.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
Iterator<String> itrS= stringPair.iterator();
while(itrS.hasNext()){
System.out.println(itrS.next());
}
}
}

谢谢所有帮助过我的人,您引导我找到了这个解决方案:)

您的初始代码正在定义一个变量T newLeft其唯一目的是跟踪 left 值是否已被消耗,由非null值指示。使用boolean变量会更清楚,即boolean hasSeenLeft;这里。然后,很明显,这个类是不完整的,因为它不跟踪是否使用了正确的值。

在您的固定代码中,您有newLeftnewRight,这解决了问题,但仍然具有误导性,因为它们的名称和类型都没有指示实际目的。如果将它们更改为boolean变量,则可以设计它们以指示是否存在挂起的值,例如

final class myIterator implements Iterator<T> { // no need to make this public
boolean hasPendingLeft = getLeft() != null, hasPendingRight = getRight() != null;
@Override
public boolean hasNext() {
return hasPendingLeft || hasPendingRight;
}
@Override
public T next() {
if(hasPendingLeft) {
hasPendingLeft = false;
return getLeft();
}
else if(hasPendingRight) {
hasPendingRight = false;
return getRight();
}
throw new NoSuchElementException();
}
}

这更简单,更具可读性。

请注意,这两种解决方案都无法处理中间的更改,但无论如何,这个Pair类看起来应该是不可变的。在这种情况下,值得将leftright声明为final.

对于可变类,值得为中间修改添加快速失败行为,类似于集合 API:

final class myIterator implements Iterator<T> { // no need to make this public
boolean hasPendingLeft = getLeft() != null, hasPendingRight = getRight() != null;
@Override
public boolean hasNext() {
return hasPendingLeft || hasPendingRight;
}
@Override
public T next() {
if(hasPendingLeft) {
hasPendingLeft = false;
T left = getLeft();
if(left == null) throw new ConcurrentModificationException();
return left;
}
else if(hasPendingRight) {
hasPendingRight = false;
T right = getRight();
if(right == null) throw new ConcurrentModificationException();
return right;
}
throw new NoSuchElementException();
}
}

因此,即使在错误的情况下,这仍然保证了非null值,并且会抛出更有意义的异常。

我猜你想迭代这个对中的 0 到 2 个可能的值?在你的迭代器中,你应该引用 T 的实例。您收到的消息是因为您尝试以静态方式调用 Pair 中的方法(即,当 Pair 是类时,您正在调用 Pair.getLeft(( (

最新更新