0

I have been reading the Effective Java book and I have stuck with this code I am unable to understand how this code is generating power set.

Code:

public class PowerSet {

    public static final <E> Collection<Set<E>> of(Set<E> s) {
        List<E> src = new ArrayList<>(s);
        if (src.size() >= 30)
            throw new IllegalArgumentException("Set too big " + s);
        return new AbstractList<Set<E>>() {

            @Override
            public int size() {
                return 1 << src.size();
            }

            @Override
            public boolean contains(Object o) {
                return o instanceof Set && src.containsAll((Set) o);
            }

            @Override
            public Set<E> get(int index) {
                Set<E> result = new HashSet<>();
                for (int i = 0; index != 0; i++, index >>= 1)
                    if ((index & 1) == 1)
                        result.add(src.get(i));
                return result;
            }
        };
    }

    public static void main(String[] args) {
        Collection<Set<String>> result = of(Set.of("a", "b", "c"));
        System.out.println(result);
    }
}

Output:

[[], [a], [b], [a, b], [c], [a, c], [b, c], [a, b, c]]

Can someone explain how this code is generating powerset of a given set.

1

1 Answer 1

1

The code uses the binary representation of the index number as a map of which element of s to include.

For instance, assuming only 3 bits in a number:

index   | a | b | c
--------------------
0 (000) | 0 | 0 | 0 -> take nothing
1 (001) | 0 | 0 | 1 -> take only c
2 (010) | 0 | 1 | 0 -> take only b
3 (011) | 0 | 1 | 1 -> take a and b
4 (100) | 1 | 0 | 0 -> take only a
...

The get method of the generated list follows this logic with the index input given:

  • index >>= 1 shifts all bits one position to the right with each loop
  • (index & 1) == 1 checks whether the rightmost bit of index is a 1

The & operator is the binary AND, so 2 & 1 equals binary 010 AND 001, giving 000 (not equal to 1 or 001) and 3 & 1 equals binary 011 AND 001, giving 001 (equal to 1 or 001)

  • If this evaluates to true, the i-th element is added to the list
  • This terminates when index == 0, i.e. there are no more bits to shift / elements to add

Example for index = 3:

i | index | (index & 1) == 1 | element added
---------------------------------------------
0 |   011 |             TRUE |   a (0-th element)
1 |   001 |             TRUE |   b (1-th element)
2 |   000 |            FALSE |   - 
(terminates as index == 0)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.