8.4 如何用Java实现python里的生成器函数?| Java Debug 笔记

625 阅读1分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>

提问:如何用Java实现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可以是多维数组或某种形式的嵌套集合。 我不确定这将如何工作。 有人能帮助我吗?

回答1:

出于同样的需要,为此写了一个类。这里有些例子:

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类与Thread配合使用以产生项目。 通过重写finalize(),它可以确保在Generator不再被使用的情况下,也没有线程停留在周围。

表现显然不是很好,但也不是太差。 在我的双核i5 CPU @ 2.67 GHz的计算机上,可以在<0.03s内生产1000件产品。

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

回答2:

Java确实没有生成器,但是您现在可以使用Java 8的Stream。

IMO确实是一个复杂的迭代器,因为它由数组(而不是函数)支持。给定它是一个循环,可以使用过滤器(跳过空值)和flatMap传递内部集合将其表示为Stream。

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