J中的等价生成函数

2024-05-12 11:19:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在Java中实现一个Iterator,其行为类似于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可以是多维数组或某种形式的嵌套集合。我不知道这会怎样。思想?


Tags: 函数innoneforifdef数组java
1条回答
网友
1楼 · 发布于 2024-05-12 11:19:02

我希望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 + ", ");
        }
    }
}
网友
2楼 · 发布于 2024-05-12 11:19:02

有同样的需要,所以写了一个小类。下面是一些例子:

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<Integer> infiniteGenerator = new Generator<Integer>() {
    public void run() throws InterruptedException {
        while (true)
            yield(1);
    }
};

Generator类在内部与一个线程一起工作以生成项。通过重写finalize(),它确保如果不再使用相应的生成器,则不会有线程留在周围。

这场演出显然不怎么样,但也不算太差。在我的机器上,2.67ghz的双核i5 CPU可以用<;0.03s生产1000种产品

代码在GitHub上。在这里,您还可以找到关于如何将其作为Maven/Gradle依赖项包含在内的说明。

网友
3楼 · 发布于 2024-05-12 11:19:02

实际上,Java没有屈服点,但是现在可以使用Java 8流。实际上,它是一个复杂的迭代器,因为它是由数组而不是函数支持的。假设它是一个循环中的循环,则可以使用filter(跳过空值)和flatMap将内部集合表示为流。这也与Python代码的大小有关。我已经将它转换为迭代器,以便在您空闲时使用并打印出来演示,但是如果您所做的只是打印,那么可以使用forEach(System.out::println)而不是迭代器()来结束流序列。

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

我在http://thecannycoder.wordpress.com/写关于生成器实现的文章,作为我关于Java 8函数式编程和Lambda表达式的博客的一部分,这可能会给您一些将Python生成器函数转换为Java等价函数的更多想法。

相关问题 更多 >