Obtaining a powerset of a set in Java

后端 未结 26 2120
青春惊慌失措
青春惊慌失措 2020-11-22 11:33

The powerset of {1, 2, 3} is:

{{}, {2}, {3}, {2, 3}, {1, 2}, {1, 3}, {1, 2, 3}, {1}}

Let\'s say I have a Set in Java:<

26条回答
  •  野性不改
    2020-11-22 11:52

    Yet another solution - with java8+ streaming api It is lazy and ordered so it returns correct subsets when it is used with "limit()".

     public long bitRangeMin(int size, int bitCount){
        BitSet bs = new BitSet(size);
        bs.set(0, bitCount);
        return bs.toLongArray()[0];
    }
    
    public long bitRangeMax(int size, int bitCount){
        BitSet bs = BitSet.valueOf(new long[]{0});
        bs.set(size - bitCount, size);
        return bs.toLongArray()[0];
    }
    
    public  Stream> powerSet(Collection data)
    {
        List list = new LinkedHashSet<>(data).stream().collect(Collectors.toList());
        Stream head = LongStream.of(0).mapToObj( i -> BitSet.valueOf(new long[]{i}));
        Stream tail = IntStream.rangeClosed(1, list.size())
                .boxed()
                .flatMap( v1 -> LongStream.rangeClosed( bitRangeMin(list.size(), v1), bitRangeMax(list.size(), v1))
                        .mapToObj(v2 -> BitSet.valueOf(new long[]{v2}))
                        .filter( bs -> bs.cardinality() == v1));
    
        return Stream.concat(head, tail)
                .map( bs -> bs
                        .stream()
                        .mapToObj(list::get)
                        .collect(Collectors.toList()));
    }
    

    And the client code is

    @Test
    public void testPowerSetOfGivenCollection(){
        List data = new LinkedList<>();
        for(char i = 'a'; i < 'a'+5; i++ ){
            data.add(i);
        }
        powerSet(data)
                .limit(9)
                .forEach(System.out::print);
    
    }
    

    /* Prints : [][a][b][c][d][e][a, b][a, c][b, c] */

提交回复
热议问题