试试这个:
boolean[] bitSetToArray(BitSet bs, int width) {
boolean[] result = new boolean[width];
bs.stream().forEach(i -> result[i] = true);
return result;
}
List<boolean[]> bool(int n) {
return IntStream.range(0, (int)Math.pow(2, n))
.mapToObj(i -> bitSetToArray(BitSet.valueOf(new long[] { i }), n))
.collect(toList());
}
关键在于
BitSet
上有一个
stream()
方法,它返回一个一位的索引流。这可以用来将
true
值设置到
boolean[]
中。还要注意,(像Bubletan一样)可以使用
List<boolean[]>
代替
List<Boolean[]>
。也就是说,可以使用原始类型
boolean
值的数组列表,而不是装箱的
Boolean
值的数组列表。 (这是因为数组属于引用类型,因此可以用作类型参数。)
最后,感谢
Bubletan,我通过添加
bitSetToArray()
来增强他的解决方案。
更新
srborlongan在评论中问是否以下内容更好:
List<boolean[]> bool(int n) {
return IntStream.range(0, (int)Math.pow(2, n))
.mapToObj(i -> new long[] { i })
.map(BitSet::valueOf)
.map(bs -> bitSetToArray(bs, n))
.collect(toList());
}
它有一个更少密集的优点。毕竟,这不是代码高尔夫、APL或Perl,目标似乎是以最简洁的方式编写某事。代码越简单,通常情况下,阅读和理解起来就越容易。
尽管如此,在这种情况下有一些微妙之处。由“mapToObj”阶段发出的“obj”是
long[]
,它被推断为
BitSet::valueOf
的参数类型。这反过来影响了重载分辨率!除非您已经非常熟悉
BitSet
API,否则您必须自己进行一些类型推断才能弄清楚这是在做什么。因此,在这种情况下,直接调用
BitSet.valueOf(long[])
可能更好。
就性能而言——这并不总是首要任务——我认为直接方法调用可能比一系列
map
操作表现更好。通过额外的流操作传递一个值可能需要两次方法调用,以及附加lambda的Lambda Metafactory调用的开销。此外,与通过流传递值相比,直接方法调用很可能更容易被JIT优化和内联。但我还没有验证任何内容。