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());
}