【问题标题】:Use stream API to return a certain number of enum values使用流 API 返回一定数量的枚举值
【发布时间】:2015-04-10 13:03:11
【问题描述】:

使用 Java 8 中的流 API,下面的 createObjects() 将在单行中返回 X 对象的列表。

public class StreamObjectCreator {

    public List<X> createObjects(Integer... s) {
        return Arrays.stream(s).map(X::new).collect(Collectors.toList());
    }

    private static class X {
        int s;
        public X(int s) {
            this.s = s;
        }
    }
}

现在,考虑下面的枚举Y

private static enum Y {

    VALUE_1(2), VALUE_2(1);

    private int i;

    private Y(int i) {
        this.i = i;
    }

    public int getI() {
        return i;
    }

}

我想做类似的事情并返回以下列表:

[VALUE_1,VALUE_1,VALUE_2]

换句话说,i 每个枚举值的出现次数。

使用“旧”的Java方式,可以这样实现。

List<Y> createEnumList() {
    List<Y> list = new ArrayList<Y>();
    for (Y y : Y.values()) {
        for (int i = 0; i < y.getI(); i++) {
            list.add(y);
        }
    }
    return list;
}

这可以通过使用流 API 或一些 lambda 表达式的更少样板代码来完成吗?我玩了一段时间的流 API 没有成功,在 Google 上找到的大多数信息都指向“更简单”的教程。

【问题讨论】:

  • 我不明白这段代码的目的......
  • 你可以用流来做,是的,但不能用“更少的代码”

标签: java enums java-8 java-stream


【解决方案1】:

我无法想象一个真实的用例,但是

List<Y> createEnumList() {
    return EnumSet.allOf(Y.class).stream()
        .flatMap(y->Collections.nCopies(y.getI(), y).stream())
        .collect(Collectors.toList());
}

会做的。

【讨论】:

    【解决方案2】:

    你总是可以做到的

    List<Y> createEnumList() {
        return Stream.of(Y.values())
                     .flatMap(y -> IntStream.range(0, y.getI()).mapToObj(i -> y))
                     .collect(toList());
    }
    

    虽然你的要求有点奇怪。

    Stream.of 将创建一个Stream&lt;Y&gt;,您可以从中将每个 Y 实例映射到包含该实例 n 次的 Stream,n 是 getId() 值。然后这个Stream&lt;Stream&lt;Y&gt;&gt; 被展平,这样你就可以得到一个Stream&lt;Y&gt;

    最后,您将管道的内容收集到一个列表中。

    【讨论】:

    • 我知道这可能看起来很奇怪,但这是我想做的。顺便说一句,你的代码返回List&lt;Object&gt;,除非我导入了错误的toList() 方法。
    • @Magnilex 这是java.util.stream.Collectors.toList; 的静态导入。它应该按预期返回List&lt;Y&gt;(我已经使用 IntelliJ 对其进行了测试,也许您正在使用 Eclipse 及其有缺陷的 Java 8 编译器)。
    • 你是对的。实际上,我发现 Eclispe 现在对 Java 8 的支持非常好,但这真是太糟糕了。 IDEA 获胜的另一个案例。
    【解决方案3】:

    你可以的

    return Stream.of(Y.values())
                 .flatMap(y -> Stream.generate(() -> y).limit(y.getI()))
                 .collect(Collectors.toList())
    

    但这是否比“旧式”方式更具可读性是一个见仁见智的问题......

    Stream.generate(() -> y).limit(y.getI())
    

    创建一个潜在无限的y 值流,然后在i 重复后截断它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-06
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      相关资源
      最近更新 更多