Java中等价的生成器函数

Java中等价的生成器函数,java,python,iterator,generator,Java,Python,Iterator,Generator,我想在Java中实现一个迭代器,其行为有点像Python中的以下生成器函数: def iterator(array): for x in array: if x!= None: for y in x: if y!= None: for z in y: if z!= None: yield z java端的x可以是多维数组或某种形式的嵌套集合。我不确定这将如何

我想在Java中实现一个迭代器,其行为有点像Python中的以下生成器函数:

def iterator(array):
   for x in array:
      if x!= None:
        for y in x:
          if y!= None:
            for z in y:
              if z!= None:
                yield z

java端的x可以是多维数组或某种形式的嵌套集合。我不确定这将如何工作。想法?

Java中没有收益,因此您必须自己完成所有这些事情,最终得到荒谬的代码,如下所示:

    for(Integer z : new Iterable<Integer>() {

        @Override
        public Iterator<Integer> iterator() {

            return new Iterator<Integer>() {

                final Integer[][][] d3 = 
                        { { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },
                        { { 10, 11, 12 }, { 13, 14, 15 }, { 16, 17, 18 } },
                        { { 19, 20, 21 }, { 22, 23, 24 }, { 25, 26, 27 } } };

                int x = 0; 
                int y = 0; 
                int z = 0;

                @Override
                public boolean hasNext() {
                    return !(x==3 && y == 3 && z == 3);
                }

                @Override
                public Integer next() {
                    Integer result = d3[z][y][x];
                    if (++x == 3) {
                        x = 0;
                        if (++y == 3) {
                            y = 0;
                            ++z;
                        }
                    }
                    return result;
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    }) {
        System.out.println(z);
    }
for(整数z:new Iterable(){
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
最终整数[][]d3=
{ { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } },
{ { 10, 11, 12 }, { 13, 14, 15 }, { 16, 17, 18 } },
{ { 19, 20, 21 }, { 22, 23, 24 }, { 25, 26, 27 } } };
int x=0;
int y=0;
int z=0;
@凌驾
公共布尔hasNext(){
返回!(x==3&&y==3&&z==3);
}
@凌驾
公共整数next(){
整数结果=d3[z][y][x];
如果(++x==3){
x=0;
如果(++y==3){
y=0;
++z;
}
}
返回结果;
}
@凌驾
公共空间删除(){
抛出新的UnsupportedOperationException();
}
};
}
}) {
系统输出打印ln(z);
}

但是如果你的样本有不止一个
收益率
,结果会更糟

我希望Java有generator/yield,但因为它不使用迭代器,所以可能是最好的选择

在本例中,我坚持使用数组,但通常我建议使用Iterable集合,例如List。在本例中,我展示了如何非常容易地为数组获取迭代器:

package example.stackoverflow;

import com.sun.xml.internal.xsom.impl.scd.Iterators;

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

public class ArrayGenerator<T> implements Iterable<T> {
    private final T[][][] input;

    public ArrayGenerator(T[][][] input) {
        this.input = input;
    }


    @Override
    public Iterator<T> iterator() {
        return new Iter();
    }

    private class Iter implements Iterator<T> {
        private Iterator<T[][]> x;
        private Iterator<T[]> y;
        private Iterator<T> z;

        {
            x = Arrays.asList(input).iterator();
            y = Iterators.empty();
            z = Iterators.empty();
        }

        @Override
        public boolean hasNext() {
            return z.hasNext() || y.hasNext() || x.hasNext();
        }

        @Override
        public T next() {
            while(! z.hasNext()) {
                while(! y.hasNext()) {
                    y = Arrays.asList(x.next()).iterator();
                }
                z = Arrays.asList(y.next()).iterator();
            }
            return z.next();
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("remove not supported");
        }
    }

    public static void main(String[] args) {
        for(Integer i :
                new ArrayGenerator<Integer>(
                        new Integer[][][]{
                          {
                            {1, 2, 3},
                            {4, 5}
                          },
                          {
                            {},
                            {6}
                          },
                          {
                          },
                          {
                            {7, 8, 9, 10, 11}
                          }
                        }
                )) {
            System.out.print(i + ", ");
        }
    }
}
package-example.stackoverflow;
导入com.sun.xml.internal.xsom.impl.scd.Iterators;
导入java.util.array;
导入java.util.Iterator;
公共类ArrayGenerator实现Iterable{
专用最终T[][]输入;
公共阵列生成器(T[]输入){
这个输入=输入;
}
@凌驾
公共迭代器迭代器(){
返回新的Iter();
}
私有类Iter实现迭代器{
专用迭代器x;
私有迭代器y;
私有迭代器z;
{
x=Arrays.asList(输入).iterator();
y=迭代器.empty();
z=迭代器.empty();
}
@凌驾
公共布尔hasNext(){
返回z.hasNext()| | y.hasNext()| | x.hasNext();
}
@凌驾
公共交通工具{
而(!z.hasNext()){
而(!y.hasNext()){
y=Arrays.asList(x.next()).iterator();
}
z=Arrays.asList(y.next()).iterator();
}
返回z.next();
}
@凌驾
公共空间删除(){
抛出新的UnsupportedOperationException(“删除不受支持”);
}
}
公共静态void main(字符串[]args){
对于(整数i:
新阵列发生器(
新整数[][]{
{
{1, 2, 3},
{4, 5}
},
{
{},
{6}
},
{
},
{
{7, 8, 9, 10, 11}
}
}
)) {
系统输出打印(i+“,”);
}
}
}

也有同样的需求,所以为此编写了一个小类。以下是一些例子:

Generator<Integer> simpleGenerator = new Generator<Integer>() {
    public void run() throws InterruptedException {
        yield(1);
        // Some logic here...
        yield(2);
    }
};
for (Integer element : simpleGenerator)
    System.out.println(element);
// Prints "1", then "2".
Generator simpleGenerator=new Generator(){
public void run()引发InterruptedException{
产量(1);
//这里有些逻辑。。。
产量(2);
}
};
for(整型元素:simpleGenerator)
系统输出打印项次(元素);
//打印“1”,然后打印“2”。
无限发电机也是可能的:

Generator<Integer> infiniteGenerator = new Generator<Integer>() {
    public void run() throws InterruptedException {
        while (true)
            yield(1);
    }
};
Generator infiniteGenerator=新发电机(){
public void run()引发InterruptedException{
while(true)
产量(1);
}
};
生成器
类在内部与一个线程一起工作以生成项目。通过重写
finalize()
,它可以确保如果不再使用相应的生成器,则不会有线程留在附近

演出显然不是很好,但也不是太差。在我的双核i5处理器@2.67 GHz的机器上,可以在<0.03秒内生产1000件产品


密码打开了。在这里,您还可以找到关于如何将其作为Maven/Gradle依赖项包含的说明。

事实上,Java没有收益,但您现在可以使用Java8流。在我看来,它确实是一个复杂的迭代器,因为它是由数组而不是函数支持的。假设它是一个循环中的一个循环,那么可以使用filter(跳过null)和flatMap将循环中的一个循环表示为一个流,以流化内部集合。它还与Python代码的大小有关。我已经将它转换为一个迭代器供您随意使用,并打印出来演示,但是如果您所做的只是打印,那么可以使用forEach(System.out::println)而不是iterator()来结束流序列

公共类数组编辑器
{
公共静态void main(字符串参数[])
{
整数[][]a=新整数[][]{{{{{1,2,null,3},
无效的
{ 4 }
},
无效的
public class ArrayIterate
{
    public static void main(String args[])
    {
        Integer[][][] a = new Integer[][][] { { { 1, 2, null, 3 },
                                                null,
                                                { 4 }
                                              },
                                              null,
                                              { { 5 } } };

        Iterator<Object> iterator = Arrays.stream(a)
                                          .filter(ax -> ax != null)
                                          .flatMap(ax -> Arrays.stream(ax)
                                               .filter(ay -> ay != null)
                                               .flatMap(ay -> Arrays.stream(ay)
                                               .filter(az -> az != null)))
                                          .iterator();

        while (iterator.hasNext())
        {
            System.out.println(iterator.next());
        }
    }
}
for (T z : iterator(array)) {
  // do something with z
}
public <T> Iterable<T> iterator(List<List<List<T>>> array) {
  return array.stream()
      .filter(Objects::nonNull) // -> emits stream of non-null `x`s
    .flatMap(x -> x.stream()).filter(Objects::nonNull) // -> emits […] `y`s
    .flatMap(y -> y.stream()).filter(Objects::nonNull) // -> emits […] `z`s
    .collect(Collectors.toList()); // get list of non-null `z`s to iterate on
}