使用流 API 到 return 一定数量的枚举值
Use stream API to return a certain number of enum values
使用 Java 8 中的流 API,下面的 createObjects()
将 return 一行 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;
}
}
我想做类似的事情 return 以下列表:
[VALUE_1, VALUE_1, VALUE_2]
换句话说,每个枚举值出现 i
次。
使用"old"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 上找到的大部分信息都指向 "easier" 教程。
我无法想象一个真实的用例但是
List<Y> createEnumList() {
return EnumSet.allOf(Y.class).stream()
.flatMap(y->Collections.nCopies(y.getI(), y).stream())
.collect(Collectors.toList());
}
会完成任务的。
你可以
return Stream.of(Y.values())
.flatMap(y -> Stream.generate(() -> y).limit(y.getI()))
.collect(Collectors.toList())
但这是否比 "old-style" 方式更具可读性是一个见仁见智的问题...
Stream.generate(() -> y).limit(y.getI())
创建可能无限的 y
值流,然后在重复 i
次后将其截断。
你总能做到
List<Y> createEnumList() {
return Stream.of(Y.values())
.flatMap(y -> IntStream.range(0, y.getI()).mapToObj(i -> y))
.collect(toList());
}
虽然你的要求有点奇怪
Stream.of
将创建一个 Stream<Y>
,您可以从中将每个 Y 实例映射到包含此实例 n 次的 Stream,n 是 getId()
值。这个 Stream<Stream<Y>>
然后被展平,这样你就可以得到一个 Stream<Y>
.
最后,您将管道的内容收集到列表中。
使用 Java 8 中的流 API,下面的 createObjects()
将 return 一行 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;
}
}
我想做类似的事情 return 以下列表:
[VALUE_1, VALUE_1, VALUE_2]
换句话说,每个枚举值出现 i
次。
使用"old"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 上找到的大部分信息都指向 "easier" 教程。
我无法想象一个真实的用例但是
List<Y> createEnumList() {
return EnumSet.allOf(Y.class).stream()
.flatMap(y->Collections.nCopies(y.getI(), y).stream())
.collect(Collectors.toList());
}
会完成任务的。
你可以
return Stream.of(Y.values())
.flatMap(y -> Stream.generate(() -> y).limit(y.getI()))
.collect(Collectors.toList())
但这是否比 "old-style" 方式更具可读性是一个见仁见智的问题...
Stream.generate(() -> y).limit(y.getI())
创建可能无限的 y
值流,然后在重复 i
次后将其截断。
你总能做到
List<Y> createEnumList() {
return Stream.of(Y.values())
.flatMap(y -> IntStream.range(0, y.getI()).mapToObj(i -> y))
.collect(toList());
}
虽然你的要求有点奇怪
Stream.of
将创建一个 Stream<Y>
,您可以从中将每个 Y 实例映射到包含此实例 n 次的 Stream,n 是 getId()
值。这个 Stream<Stream<Y>>
然后被展平,这样你就可以得到一个 Stream<Y>
.
最后,您将管道的内容收集到列表中。