我想知道在Java8中处理枚举的所有值的最好方法是什么。特别是当您需要获取所有值并将其添加到某个位置时,例如,假设我们有以下枚举:
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()方法?
发布于 2015-04-28 22:59:21
三个问题:三部分回答:
从设计的角度来看,这是可以的吗?
绝对一点儿没错。这没什么问题。如果您需要在枚举上进行大量迭代,流API是一种简洁的方法,并且可以将样板隐藏在一个小方法后面。不过,我会认为OldCumudgeon的version更好。
从性能的角度来看,这是可以的吗?
这很可能无关紧要。大多数情况下,枚举并没有那么大。因此,在99.9%的情况下,一种或另一种方法的开销可能并不重要。
当然,也有0.1%的人这样做。在这种情况下:用你的真实数据和消费者进行适当的衡量。
如果我必须打赌,我会认为for each
循环会更快,因为它更直接地映射到内存模型,但在谈论性能时不要猜测,并且在实际需要调优之前不要调优。以一种正确的方式编写代码,首先是正确的,其次是容易阅读的,然后才是代码风格的性能。
为什么Enums没有正确集成到Stream API中?
如果您将Java的Stream API与许多其他语言中的等价物进行比较,它似乎存在严重的局限性。有各种各样的片段缺失(例如,可重用的流和可选的流)。另一方面,实现Stream API对API来说无疑是一个巨大的变化。它被多次推迟是有原因的。因此,我猜Oracle希望将更改限制在最重要的用例上。无论如何,枚举并不经常被使用。当然,每个项目都有几个这样的项目,但与列表和其他集合的数量相比,它们算不了什么。即使你有一个Enum,在很多情况下你也不会遍历它。另一方面,列表和集合可能几乎每次都会被迭代。我认为这就是为什么Enums没有获得自己的Stream世界适配器的原因。我们将看到在未来的版本中是否会添加更多这样的功能。在此之前,您始终可以使用Arrays.stream
。
发布于 2015-04-29 01:31:39
我会去找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);
}
https://stackoverflow.com/questions/29922296
复制相似问题