Java 8 使用枚举的方式 [已关闭]

2022-08-31 17:19:22

我想知道在Java 8中处理枚举的所有值的最佳方法是什么。特别是当您需要获取所有值并将其添加到某个位置时,例如,假设我们有以下枚举:

public enum Letter {
 A, B, C, D;
}

我当然可以做到以下几点:

for (Letter l : Letter.values()) {
    foo(l);
}

但是,我还可以在枚举定义中添加以下方法:

public static Stream<Letter> stream() {
    return Arrays.stream(Letter.values());
}

然后将上面的 for 替换为:

Letter.stream().forEach(l -> foo(l));

这种方法是可以的,还是在设计或性能方面存在一些错误?此外,为什么枚举没有 stream() 方法?


答案 1

我会选择EnumSet。因为 也定义了 ,您可以完全避免创建流:forEach()Iterable

EnumSet.allOf(Letter.class).forEach(x -> foo(x));

或者使用方法引用:

EnumSet.allOf(Letter.class).forEach(this::foo);

尽管如此,老式的for-loop感觉更简单一些:

for (Letter x : Letter.values()) {
    foo(x);
}

答案 2

三个问题:三部分答案:

从设计的角度来看可以吗?

绝对。没什么错。如果您需要对枚举进行大量迭代,则流API是一种干净的方式,并且将样板隐藏在一个小方法后面是可以的。虽然我认为OldCumudgeon的版本更好。

从性能的角度来看可以吗?

这很可能并不重要。大多数时候,枚举并不大。因此,无论一种方法或另一种方法的开销在99.9%的情况下都无关紧要。

当然,有0.1%的地方。在这种情况下:使用您的真实数据和消费者进行正确测量。

如果我必须打赌,我希望循环会更快,因为它更直接地映射到内存模型,但在谈论性能时不要猜测,并且在实际需要调整之前不要调整。首先以正确的方式编写代码,其次是易于阅读,然后才担心代码样式的性能。for each

为什么枚举没有正确集成到流 API 中?

如果你将Java的Stream API与许多其他语言中的等效API进行比较,它似乎受到严重限制。缺少各种部分(例如,可重用的流和可选的流)。另一方面,实现流 API 对于 API 来说无疑是一个巨大的变化。由于某种原因,它被多次推迟。所以我想Oracle希望将更改限制在最重要的用例上。无论如何,枚举的使用并不多。当然,每个项目都有几个,但与列表和其他集合的数量相比,它们算不了什么。即使你有一个枚举,在许多情况下,你也不会迭代它。另一方面,列表和集可能几乎每次都会迭代。我认为这些是Enum没有获得自己的Stream世界适配器的原因。我们将看看在未来的版本中是否会添加更多这样的内容。在此之前,您始终可以使用.Arrays.stream