如何在java中一个接一个地遍历两个不同类型的通用列表?

Tos*_*vos 6 java generics iterator list wildcard

我想创建一个迭代器类,它允许我遍历具有泛型类型(例如lst1 integer,lst2 string)的列表.为此,我必须考虑以下给定的情况.

该接口是通用迭代器.这部分代码无法修改.

interface Iterator<E> {
E next ();
boolean hasNext();
}
Run Code Online (Sandbox Code Playgroud)

列表类也定义如下.最重要的是,列表对象可以使用方法getIterator()返回迭代器对象.这部分代码无法修改.

class List<T> {
class ListNode {
    T val;
    ListNode next;

    ListNode (T v) {
        val = v; next = null;
    }
}

ListNode head;

List (ListNode hd) { head = hd; }
List () { this(null); }

void prepend (T val) {
    ListNode p = new ListNode(val);
    p.next = head;
    head = p;
}

//some other methods

class ListIterator implements Iterator<T> {
    ListNode pos;

    ListIterator () {
        pos = head;
    }

    public T next () {       
        T res = pos.val;
        pos = pos.next;
        return res;
    }

    public boolean hasNext () {
        return pos != null;
    }
}

Iterator<T> getIterator () {        
    return this.new ListIterator();
}
}
Run Code Online (Sandbox Code Playgroud)

让我们假设两个列表具有相同的类型,现在它们也具有相同的长度.我尝试使用两个迭代器对象创建一个类,并使用迭代器对象的方法来实现接口Iterator.这部分代码是由我创建的,可以修改.

class ZipIterator<T> implements Iterator<T>
{
int counter;
Iterator<T> first;
Iterator<T> second;

ZipIterator (Iterator<T> f, Iterator<T> s)
{
    first = f;
    second = s;
    counter = 0;
}

public T next ()
{
    if (counter % 2 == 0)
    {
        counter++;
        return first.next();
    }

    else
    {
        counter++;
        return second.next();
    }

}
public boolean hasNext ()
{
    if (counter % 2 == 0)
        return first.hasNext();
    else
        return second.hasNext();
}
}
Run Code Online (Sandbox Code Playgroud)

这适用于具有相同类型的两个列表.这是我用于测试的代码和输出:

class IteratorUtils
{
public static void main (String[] args)
{
    List<Integer> lst1 = new List<>();
    List<Integer> lst2 = new List<>();
    lst1.prepend(3);
    lst1.prepend(2);
    lst1.prepend(1);
    lst2.prepend(8);
    lst2.prepend(9);
    lst2.prepend(10);
    Iterator<Integer> it1 = lst1.getIterator();
    Iterator<Integer> it2 = lst2.getIterator();
    ZipIterator<Integer> zit = new ZipIterator<>(it1, it2);
    while (zit.hasNext())
    {
        System.out.println(zit.next());
    }
}
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
10
2
9
3
8
Run Code Online (Sandbox Code Playgroud)

现在我想以通用方式实现ZipIterator,因此我可以使用两个具有不同类型项的列表(例如整数和字符串).我知道我必须更改ZipIterator类,所以方法next()返回泛型类型,但我不知道如何.这是我必须要做的大学任务,教授已经留下了一个提示"使用如下的外卡:?扩展T,?超级T,?extends Object".但是通过外卡,我只能指定继承方向中的类型或对抗继承方向的类型,对吧?这是否可以以这种方式更改ZipIterator类,以便它接受两个具有不同类型的迭代器对象?

use*_*551 3

我不会给出完整的解决方案(从你的努力来看,你并不想要它),但我会尝试以一种让你自己找到它的方式进行解释。

首先,一个不相关的注释:您正在指定特定的迭代顺序。我认为这很好,我不会碰它。

你的教授给了你使用有界泛型的提示。让我们了解为什么需要它们(另请参阅此处和/或此处的教程)。如果您被要求编写一个接受两种未知类型中任意一种参数的方法,您的解决方案将是找到并采用它们的共同超类 - Object

在泛型中,情况类似 - 找到最常见的分母,只是语法有点棘手。如果你要写构造函数

ZipIterator(Iterator<Object> f, Iterator<Object> s) {...}
Run Code Online (Sandbox Code Playgroud)

并尝试初始化

List<Integer> lst1 = new List<>();
List<String> lst2 = new List<>();
new ZipIterator(it1, it2);
Run Code Online (Sandbox Code Playgroud)

你会得到一个编译错误(阅读它)。这是因为 aList<String>不是 a List<Object>,尽管 aString是 an Object。正确的方法是

ZipIterator(Iterator<? extends Object> f, Iterator<? extends Object> s) {...}
Run Code Online (Sandbox Code Playgroud)

其中? extends Object表示“任何扩展的类型Object”(这是所有类型,因为Object......)。

所以你有了构造函数,你需要对你的类进行更改才能适应它。你甚至不需要实现给定的Iterator<E>,你只需像你已经做的那样持有其中的两个。最后,类本身不需要具有泛型类型:因为它的next方法必须能够返回任何类型,所以它总是返回Object

如果您在以后尝试解决此问题时有任何疑问,或者您发现此解决方案不符合作业要求,请随时发表评论。