当前位置: 首页 > 知识库问答 >
问题:

泛型对类的自己的迭代器

单嘉泽
2023-03-14

我试图为自己的泛型类编写自己的迭代器。我一直在看几个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。因此,迭代器本身可以工作,但我的方法有一个逻辑错误。为此而努力,但我感谢任何投入。:)

逻辑错误发现:新左派永远不会从空值改变。努力解决它。

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

谢谢大家,谁帮助了我,你带领我找到了这个解决方案:)

共有2个答案

毛博
2023-03-14

我猜你想迭代这对中的0到2个可能的值?在你的迭代器中,你应该引用t的实例。你得到的消息是因为你试图以静态方式调用Pair中的一个方法(也就是说,当Pair是类时,你正在调用Pair.getLeft())

温举
2023-03-14

您的初始代码正在定义一个变量 T newLeft,其唯一目的是跟踪左值是否已被使用,由非值指示。使用布尔变量会更清晰,即布尔变量在这里看到左派。然后,很明显,这个类是不完整的,因为它不跟踪是否使用了正确的值。

在您的固定代码中,您有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();
    }
}

这更简单易读。

注意,这两种解决方案都不能处理中间的更改,但是这个< code>Pair类看起来在最好的情况下应该是不可变的。在这种情况下,值得将< code>left和< code>right声明为< code>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();
    }
}

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

 类似资料:
  • 如何将此迭代器与泛型类型一起使用?以下是我在“main”函数中尝试的方法: 结果是:<代码>无法从静态上下文引用非静态类项 结果是:<代码>无法从静态上下文引用非静态类项 结果: 编辑: 我调用的是类而不是方法。这项工作: 迭代器it=deq。迭代器(); 我认为,由于iterator()中返回的实例的类型是ListIterator,因此我需要使用该类型声明“it”。

  • 我想创建一个自定义的树数据结构,只有节点,我可以迭代他们。然后,我可以扩展这个类,并有非常基本的树 我已经开始工作了,但是当我试图扩展Node类时,问题就来了。对于扩展类,继承的迭代器方法仍然返回节点迭代器,这意味着我每次都要强制转换。下面是我遇到的问题的一个基本示例。让我们建立一个包含整数的树: 是否有一种简单的方法可以解决这个问题,而不需要将iterator()方法从Node类复制到Integ

  • 所以我有一个抽象类,它准备我的查询,直到after where子句。它看起来像这样: 然后返回,具体实现使用该实例向其添加内容。 是否可以让此通话返回

  • 问题内容: 我有一个旧类,该类本身不是泛型,但其方法返回类型之一使用泛型: 使用泛型返回字符串的集合。因此,我可以进行遍历,而无需将元素强制转换为: 但是,如果我将自己更改为通用名称,但其他所有内容均保持不变: 然后继续使用对的非泛型引用,不再返回,而是返回非类型。因此,客户端代码无法编译: 为什么是这样?有哪些解决方法? 我的猜测是,通过使用对泛型类的非泛型引用,Java将关闭整个类的所有泛型。

  • 问题内容: 我偶然发现了对Java继承的好奇心,我希望您对此提出更好的想法: 假设两个接口A和A1 接口A1扩展了A 接口A具有返回泛型类型的方法。 通用类型将是。 现在的基本思想是将这种通用返回类型从接口A中更改 为 接口A1中的 一开始似乎很容易(不好的事情会在以后出现) 我们将接口A声明为 和接口A1一样 如您所见,我们被迫编写接口A本身,以允许使用基于泛型的“子类”覆盖它。(实际上,gen

  • 如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或