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.
Advertisement
Answer
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 ofindex
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)