Java 生成可能的布尔组合的最优雅的方法
在给定最大布尔数的情况下,生成可能的布尔组合的最优雅的方法是什么 例: 这是我当前的实现:Java 生成可能的布尔组合的最优雅的方法,java,java-8,java-stream,Java,Java 8,Java Stream,在给定最大布尔数的情况下,生成可能的布尔组合的最优雅的方法是什么 例: 这是我当前的实现: public static List<Boolean[]> bool(int n) { return IntStream.range(0, (int) Math.pow(2, n)) .mapToObj(i -> StringUtils.leftPad(Integer.toBinaryString(i), n, '0').chars().m
public static List<Boolean[]> bool(int n) {
return IntStream.range(0, (int) Math.pow(2, n))
.mapToObj(i -> StringUtils.leftPad(Integer.toBinaryString(i), n, '0').chars().mapToObj(c -> c != '0').toArray(Boolean[]::new))
.collect(Collectors.toList());
}
公共静态列表bool(int n){
返回IntStream.range(0,(int)Math.pow(2,n))
.mapToObj(i->StringUtils.leftPad(Integer.toBinaryString(i),n,'0').chars().mapToObj(c->c!='0').toArray(Boolean[]::new))
.collect(Collectors.toList());
}
但是,我不满意这样一个事实:我使用整数,然后使用StringUtils.leftPad
映射到二进制,然后使用map
返回Boolean[]
而不是Boolean[]
使用流API在单行程序中有更好的方法吗?仅是一种单行程序-它提供了一个迭代器
而不是列表
,但它演示了计数的原理,并将计数的每一位呈现为布尔值
public static Iterator<Boolean[]> bool(final int n) {
return new Iterator<Boolean[]>() {
final BigInteger max = BigInteger.ONE.shiftLeft(n);
BigInteger next = BigInteger.ZERO;
@Override
public boolean hasNext() {
return next.compareTo(max) < 0;
}
@Override
public Boolean[] next() {
Boolean[] b = new Boolean[n];
for (int i = 0; i < n; i++) {
b[i] = next.testBit(i);
}
next = next.add(BigInteger.ONE);
return b;
}
};
}
我在终止infine流时遇到问题
尝试了一些东西。并非所有内容都使用流API。。尽管我认为不可能用它创建一个boolean[]
。我没怎么用,所以我可能错了
public static List<boolean[]> bool(int n) {
return IntStream.range(0, 1 << n)
.mapToObj(i -> BitSet.valueOf(new long[] {i}))
.map(bs -> {
boolean[] a = new boolean[n];
for (int i = 0; i < n; i++) {
a[n - i - 1] = bs.get(i);
}
return a;
})
.collect(Collectors.toList());
}
公共静态列表bool(int n){
返回IntStream.range(0,1位集.valueOf(新长[]{i}))
.map(bs->{
布尔值[]a=新的布尔值[n];
对于(int i=0;i
试试这个:
boolean[] bitSetToArray(BitSet bs, int width) {
boolean[] result = new boolean[width]; // all false
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());
}
它的优点是密度较小。毕竟,这不是代码高尔夫、APL或Perl,它们的目标似乎不是以最简洁的方式编写东西。密度较低的代码通常(但并非总是)更易于阅读和理解
不过,我认为在这种情况下有一些细微差别。mapToObj
阶段发出的“obj”是long[]
,它被推断为BitSet::valueOf
的参数类型。这反过来会影响过载分辨率!除非您已经非常熟悉位集
API,否则您必须自己进行一点类型推断,以了解这是在做什么。因此,在这种情况下,最好直接调用BitSet.valueOf(long[])
就性能而言——这并不总是头等大事——我认为直接方法调用的性能可能比一连串的map
操作要好。通过附加流操作传递值可能涉及两个方法调用,加上附加Lambda的Lambda元工厂调用的开销。此外,直接方法调用可能比通过流传递值更容易通过JIT和内联方式进行优化。但是我还没有验证任何一个。如果必须是Stream
s:
public static List<boolean[]> bool(int n) {
return IntStream.range(0, 1<<n).mapToObj(
i->IntStream.range(0, n)
.collect(()->new boolean[n], (ba,j)->ba[j]=((i>>>j)&1)!=0,
(x,y)->{throw new UnsupportedOperationException();})
).collect(Collectors.toList());
}
从零开始计算,用整数类型作为位域?这不是他在做的吗?将int->binary string,然后逐字符转换为boolean.mappoobj中没有这样的方法,将mapToObj函数拆分为.mapToObj(i->new long[]{i}).map(BitSet::valueOf).map(bs->bitsetoarray(bs,n))?
boolean[] bitSetToArray(BitSet bs, int width) {
boolean[] result = new boolean[width]; // all false
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());
}
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());
}
public static List<boolean[]> bool(int n) {
return IntStream.range(0, 1<<n).mapToObj(
i->IntStream.range(0, n)
.collect(()->new boolean[n], (ba,j)->ba[j]=((i>>>j)&1)!=0,
(x,y)->{throw new UnsupportedOperationException();})
).collect(Collectors.toList());
}
public static List<boolean[]> bool(int n) {
return IntStream.range(0, 1<<n).mapToObj(i-> {
boolean[] ba=new boolean[n];
for(int j=0; j<n; j++) ba[j]=((i>>>j)&1)!=0;
return ba;
}).collect(Collectors.toList());
}