【问题标题】:for-each loop can only iterate over an array or an instance of java.lang.Iterable [duplicate]for-each 循环只能遍历数组或 java.lang.Iterable 的实例 [重复]
【发布时间】:2013-08-25 21:34:10
【问题描述】:

以下代码不起作用。这段代码有什么问题?编译器在 for 循环中抱怨 NumberList 不是 Iterable 类。

for-each 循环中可以使用什么样的类?如何使NumberList 可迭代?我尝试制作NumberList implement Iterable,但它似乎不起作用,因为我不知道如何正确定义迭代器。

如果有人可以演示如何使此代码工作,或者将我链接到一个很棒的教程。

public class Test{
    public class NumberList{
        private int numItems;
        private Number[] numbers;

        public NumberList(int size){
            this.numbers = new Number[size];
            this.numItems=0;
        }

        public void add(Number n){
            this.numbers[this.numItems++]=n;
        }
    }

    public void printPairs() {
        ArrayList<Integer> num=new ArrayList<Integer>();

        NumberList numbers = new NumberList(50);
        numbers.add(4);
        numbers.add(5);
        numbers.add(6);

        for(Number n1: numbers){
            System.out.println(n1);
        }
    }
}

【问题讨论】:

  • 为什么要定义自己的列表,而不是使用 ArrayList?
  • 首先,一定要使用JDK自带的列表。正如前面的评论者所说,定义你自己的没有用。但是如果你想修复你的代码,编译器会给你答案。只需实现 Iterable 并填写所需的方法即可。
  • 还有其他关于SO实现Iterable方法的问题,包括Implementing the Iterable interface

标签: java


【解决方案1】:

NumberList 没有实现 Iterable。就编译器而言,它只是任何其他类。

你需要做这样的事情

public class NumberList implements Iterable<Number> {

    private int numItems;
    private Number[] numbers;

    public NumberList(int size) {
        this.numbers = new Number[size];
        this.numItems = 0;
    }

    public void add(Number n) {
        this.numbers[this.numItems++] = n;
    }

    @Override
    public Iterator<Number> iterator() {
        return Arrays.asList(numbers).subList(0, numItems).iterator();
    }
}

【讨论】:

  • 答案很好,但说明了这个练习的徒劳:你所拥有的只是一个没有任何价值的薄委托层。
  • 而且答案不是很好,因为迭代器会遍历数组的所有元素,而不仅仅是前 numItems 个元素。
  • @JB 您当然是对的,更新了答案。有了这些愚蠢的玩具例子,很容易让人误以为你不会弄错。
【解决方案2】:

你的类NumberList需要实现Iterable接口:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

public class Test {
    public class NumberList implements Iterable<Number> {
        private int numItems;
        private Number[] numbers;

        public NumberList(int size) {
            this.numbers = new Number[size];
            this.numItems = 0;
        }

        public void add(Number n) {
            this.numbers[this.numItems++] = n;
        }

        @Override
        public Iterator<Number> iterator() {
            return Arrays.asList(numbers).iterator();
        }

    }

    public void printPairs() {

        ArrayList<Integer> num = new ArrayList<Integer>();

        NumberList numbers = new NumberList(50);
        numbers.add(4);
        numbers.add(5);
        numbers.add(6);

        for (Number n1 : numbers) {
            System.out.println(n1);
        }
    }
}    

【讨论】:

  • 我有一个问题,为什么“实现 Iterable”需要泛型类型?为什么我不能将其保留为 Iterable?在我的编译器中,我似乎可以将迭代器方法保留为原始类型,但需要将 作为泛型类型放在“实现”中。
  • @Jimster 如果你实现了原始的Iterable 而不是Iterable&lt;Number&gt;,那么你只能说for(Object o : numbers),编译器会拒绝for(Number n : numbers)
  • 一般来说,即使编译器允许,如果有其他选择,将任何内容保留为原始类型也不是一个好主意。
【解决方案3】:

你需要implementIterable interface。在这种情况下,这仅意味着您需要将方法 Iterator&lt;T&gt; iterator() 添加到您的 NumberList 类中。由于您的列表在这种情况下仅包含数字,因此泛型类型参数 T 只是 Number

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 2018-01-10
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    相关资源
    最近更新 更多