Rum*_*mal 57 java enums java-8
我想知道Java 8中最好的方法是使用枚举的所有值.特别是当你需要获取所有值并将其添加到某个地方时,例如,假设我们有以下枚举:
public enum Letter {
A, B, C, D;
}
Run Code Online (Sandbox Code Playgroud)
我当然可以做以下事情:
for (Letter l : Letter.values()) {
foo(l);
}
Run Code Online (Sandbox Code Playgroud)
但是,我还可以在枚举定义中添加以下方法:
public static Stream<Letter> stream() {
return Arrays.stream(Letter.values());
}
Run Code Online (Sandbox Code Playgroud)
然后用以下内容替换上面的for:
Letter.stream().forEach(l -> foo(l));
Run Code Online (Sandbox Code Playgroud)
这种方法是正确的还是在设计或性能方面有问题?而且,为什么enums没有stream()方法?
Nat*_*tix 27
我会去的EnumSet.因为forEach()还定义了Iterable,您可以完全避免创建流:
EnumSet.allOf(Letter.class).forEach(x -> foo(x));
Run Code Online (Sandbox Code Playgroud)
或者使用方法参考:
EnumSet.allOf(Letter.class).forEach(this::foo);
Run Code Online (Sandbox Code Playgroud)
仍然,oldschool for循环感觉有点简单:
for (Letter x : Letter.values()) {
foo(x);
}
Run Code Online (Sandbox Code Playgroud)
Jen*_*der 26
三个问题:三部分答案:
绝对.它没有错.如果你需要对枚举进行大量的迭代,那么流API就是一个干净的方法,将一个方法隐藏在一个小方法后面就可以了.虽然我认为OldCumudgeon的版本更好.
它很可能无关紧要.大多数时候,枚举并不是那么大.因此,对于一种方法或另一种方法的任何开销可能在99.9%的情况下无关紧要.
当然,它有0.1%.在这种情况下:使用您的真实数据和消费者正确衡量.
如果我不得不打赌,我希望for each循环更快,因为它更直接地映射到内存模型,但是在谈论性能时不要猜测,并且在实际需要调整之前不要调整.以正确的方式编写代码,第二方便阅读,然后再担心代码风格的性能.
如果将Java的Stream API与许多其他语言中的等效API进行比较,则它看起来非常有限.缺少各种各样的部分(例如,可重用的Streams和Optionals作为Streams).另一方面,实现Stream API肯定是API的巨大变化.它被推迟多次是有原因的.所以我想Oracle希望将更改限制在最重要的用例中.无论如何,枚举不会那么用.当然,每个项目都有几个,但它们与列表和其他集合的数量相比没什么.即使你有一个Enum,在很多情况下你也不会迭代它.另一方面,列表和集合几乎每次都可以迭代.我认为这些是为什么Enums没有得到自己的适配器到Stream世界的原因.我们将在未来的版本中看到是否会添加更多内容.在那之前你总是可以使用Arrays.stream.
Gio*_*nni 12
我的猜测是枚举的大小有限(即大小不受语言限制但受使用限制),因此它们不需要本机流API.当你必须操纵变换并重新收集流中的元素时,流非常好; 这些不是Enum的常见用例(通常是迭代枚举值,但很少需要转换,映射和收集它们).
如果您只需要对每个元素执行操作,则可能只应公开forEach方法
public static void forEach(Consumer<Letter> action) {
Arrays.stream(Letter.values()).forEach(action);
}
.... //example of usage
Letter.forEach(e->System.out.println(e));
Run Code Online (Sandbox Code Playgroud)
我认为获得Stream枚举常量的最短代码是Stream.of(Letter.values()).它不是那么好,Letter.values().stream()但这是数组的问题,而不是特别的枚举.
而且,为什么enums没有
stream()方法呢?
你是对的,最好的电话会是Letter.stream().不幸的是,一个类不能有两个具有相同签名的方法,因此不可能隐式地stream()为每个枚举添加静态方法(与每个枚举具有隐式添加的静态方法的方式相同values()),因为这会破坏每个现有的枚举已经有一个没有参数调用的静态或实例方法stream().
这种方法可以吗?
我认同.缺点是stream静态方法,所以没有办法避免代码重复; 它必须分别添加到每个枚举.