Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- !!!!! There is now a project with much better code than this !!!!!
- http://claude-martin.ch/enumbitset/
- I made this because enums can not easily be stored to bit fields. Set and bitwise operations are equally difficult.
- I put this on pastebin because it's just one single interface. I will edit this paste if I change anything. Maybe I'll put in on a repository later.
- Note that I didn't really test this!
- You can use it for whatever you want. There is no copyright. But it would be nice if you would keep my name in the file.
- -----------------
- package ch.claude_martin.java8;
- import java.math.BigInteger;
- import java.util.Arrays;
- import java.util.BitSet;
- import java.util.EnumSet;
- import java.util.Set;
- /**
- * This adds support to use bit fields and bit masks for the enym type. The set
- * of enum values is interpreted as a bit set, which can be stored to a bit
- * field.
- *
- * <p>
- * Since this is an interface it does not change the state of the element it is
- * used on or any parameters. Instead it always returns a newly created object.
- * I.e. all methods that take a Set return a new Set. If you wish to alter the
- * set you can simply use the methods of that set.
- *
- * <p>
- * Bit fields are by default of type {@link BigInteger}, but {@link BitSet} and
- * {@link Long long} can be used as well. Bit masks should not be stored into a
- * database unless you can guarantee that no changes are made in the future. The
- * only change that would not break your code is to add new enums at the end of
- * the list of existing enums. Note that {@link EnumSet} and {@link BigInteger}
- * already has many methods to help using sets of enums and large integers.
- *
- * <p>
- * A bit field is always used to store a set of bits. Each bit can represent one
- * enum value. each enum has a distinct {@link #bitmask() bit mask}.
- *
- * <p>
- * Java 8 Beta has still a bug that does not allow assert statements in
- * interfaces: <a
- * href="https://bugs.openjdk.java.net/browse/JDK-8025141">https:/
- * /bugs.openjdk.java.net/browse/JDK-8025141</a>
- *
- * <p>
- * Nomenclature:
- * <dl>
- * <dt>enum type</dt>
- * <dd>Any type that is an enum. I.e. it uses "enum" insteaf of "class" in its
- * declaration. <br/>
- * Example: <code>Planet.class</code></dd>
- * <dt>enum</dt>
- * <dd>A field of an enumy type. This is one single value of any enum type.<br/>
- * Example: Planet.VENUS</dd>
- * </dl>
- * Example:
- *
- * <pre><blockquote>
- * public enum Planet {
- * MERCURY, VENUS, EARTH, ...
- * }
- * </blockquote></pre>
- * <p>
- * The goal of this interface is to use only existing types. Since all primitive
- * types are limited this uses {@link BigInteger} instead.
- *
- * @author Claude Martin
- *
- * @param <E>
- * The Enum-Type.
- */
- public interface EnumBitOperations<E extends Enum<E>> {
- /**
- * Returns whether this enum can be found in the list of enums of the same
- * type.
- *
- * @returns <code>true</code>, if <code>this</code> can be found.
- */
- public default boolean elementOf(final Enum<?>... set) {
- for (final Enum<?> e : set)
- if (e == this)
- return true;
- return false;
- }
- /**
- * Returns whether this enum can be found in the set of enums of the same
- * type.
- * <p>
- * This is equivalent to: <code>
- * set.contains(this);
- * </code>
- *
- * @returns <code>true</code>, if <code>this</code> can be found.
- */
- public default boolean elementOf(final Set<Enum<?>> set) {
- return set.contains(this);
- }
- /**
- * Creates a new EnumSet with <code>this</code> added.
- *
- * @returns A new {@link EnumSet} including all given elements and also
- * <code>this</code>.
- */
- @SuppressWarnings("unchecked")
- public default EnumSet<E> addTo(final E... set) {
- final EnumSet<E> result = EnumSet.copyOf(Arrays.asList(set));
- result.add((E) this);
- return result;
- }
- /**
- * Creates a new EnumSet with <code>this</code> added.
- *
- * @returns A new {@link EnumSet} including all elements of the set and also
- * <code>this</code>.
- */
- @SuppressWarnings("unchecked")
- public default EnumSet<E> addedTo(final EnumSet<E> set) {
- final EnumSet<E> result = EnumSet.copyOf(set);
- result.add((E) this);
- return result;
- }
- /**
- * Creates a new EnumSet with <code>this</code> removed.
- *
- * @returns A new {@link EnumSet} with all given enums, except
- * <code>this</code>. A copy of the set is returned if
- * <code>this</code> is not present.
- */
- @SuppressWarnings("unchecked")
- public default EnumSet<E> removedFrom(final E... set) {
- final EnumSet<E> result = EnumSet.copyOf(Arrays.asList(set));
- result.remove(this);
- return result;
- }
- /**
- * Creates a new EnumSet with <code>this</code> removed.
- *
- * @returns A new {@link EnumSet} with all elements of the set, except
- * <code>this</code>. A copy of the set is returned if
- * <code>this</code> is not present.
- */
- public default EnumSet<E> removedFrom(final EnumSet<E> set) {
- final EnumSet<E> result = EnumSet.copyOf(set);
- result.remove(this);
- return result;
- }
- /**
- * Returns a set of all enums except <code>this</code>.
- *
- * <p>
- * This is equivalent to: <code>EnumSet.complementOf(this.asSet())</code>
- *
- * @returns A new {@link EnumSet} with all elements except <code>this</code>.
- */
- @SuppressWarnings("unchecked")
- public default EnumSet<E> others() {
- final E e = (E) this;
- final EnumSet<E> result = EnumSet.allOf(e.getClass());
- result.remove(e);
- return result;
- }
- /**
- * Returns a set containing nothing but <code>this</code>.
- *
- * @returns A new {@link EnumSet} containing <code>this</code>.
- */
- @SuppressWarnings("unchecked")
- public default EnumSet<E> asEnumSet() {
- final E e = (E) this;
- final EnumSet<E> result = EnumSet.noneOf(e.getClass());
- result.add(e);
- return result;
- }
- /**
- * Returns a BitSet with all bits set to 0, except the bit representing
- * <code>this</code>.
- *
- * @returns A new {@link EnumSet} containing <code>this</code>.
- */
- @SuppressWarnings("unchecked")
- public default BitSet asBitSet() {
- final E e = (E) this;
- final BitSet result = new BitSet();
- result.set(e.ordinal());
- return result;
- }
- /**
- * Bitmask for <code>this</code>. The value is based on the ordinal.
- *
- * @return <code>1<<this.ordinal()</code>
- * @deprecated This is actually the same as {@link #bitmask()}. This is here
- * so that programmers will find and use {@link #bitmask()}.
- */
- @Deprecated
- public default BigInteger asBigInteger() {
- return this.bitmask();
- }
- /**
- * 64 bit bitmask for <code>this</code>. The value is based on the ordinal.
- *
- * @return <code>1<<this.ordinal()</code>
- */
- @SuppressWarnings("unchecked")
- public default long bitmask64() {
- final E e = (E) this;
- // assert EnumSet.allOf(e.getClass()).size() <= 64;
- return 1 << e.ordinal();
- }
- /**
- * Bitmask for <code>this</code>. The value is based on the ordinal.
- *
- * @return <code>1<<this.ordinal()</code>
- */
- @SuppressWarnings("unchecked")
- public default BigInteger bitmask() {
- final E e = (E) this;
- return BigInteger.ONE.shiftLeft(e.ordinal());
- }
- /**
- * Returns whether this value is set in the given bitmask.
- *
- * @param bitmask64
- * A bitmask.
- * @return (this.bitmask64() & bitmask8) != 0;
- */
- public default boolean elementOf(final long bitmask64) {
- return (this.bitmask64() & bitmask64) != 0;
- }
- /**
- * Returns whether this value is set in the given bitmask.
- *
- * @param bitmask
- * A bitmask.
- * @return (this.bitmask() & bitmask) != 0
- */
- public default boolean elementOf(final BigInteger bitmask) {
- return !this.bitmask().and(bitmask).equals(BigInteger.ZERO);
- }
- /**
- * Returns whether this value is set in the given bitset.
- *
- * @param bitset
- * @return bitset.get(this.ordinal());
- */
- @SuppressWarnings("unchecked")
- public default boolean elementOf(final BitSet bitset) {
- return bitset.get(((E) this).ordinal());
- }
- /** Creates a 64 bit bitmask of a given set of enums. */
- public static <X extends Enum<X> & EnumBitOperations<X>> long toBitmask64(final EnumSet<X> set) {
- long result = 0;
- for (final X e : set)
- result |= e.bitmask64();
- return result;
- }
- /** Creates a 64 bit bitmask of a given set of enums. */
- @SafeVarargs
- public static <X extends Enum<X> & EnumBitOperations<X>> long toBitmask64(final X... set) {
- long result = 0;
- for (final X e : set)
- result |= e.bitmask64();
- return result;
- }
- /** Creates a bitmask of a given set of enums. */
- public static <X extends Enum<X> & EnumBitOperations<X>> BigInteger toBitmask(final EnumSet<X> set) {
- BigInteger result = BigInteger.ZERO;
- for (final X e : set)
- result = result.or(e.bitmask());
- return result;
- }
- /** Creates a bitmask of a given set of enums. */
- @SafeVarargs
- public static <X extends Enum<X> & EnumBitOperations<X>> BigInteger toBitmask(final X... set) {
- BigInteger result = BigInteger.ZERO;
- for (final X e : set)
- result = result.or(e.bitmask());
- return result;
- }
- /**
- * Creates a BitSet of a given set of enums.
- * */
- @SafeVarargs
- public static <X extends Enum<X> & EnumBitOperations<X>> BitSet toBitSet(final X... set) {
- final BitSet result = new BitSet();
- for (final X e : set)
- result.set(e.ordinal());
- return result;
- }
- /**
- * Creates a BitSet of a given set of enums.
- */
- public static <X extends Enum<X> & EnumBitOperations<X>> BitSet toBitSet(final EnumSet<X> set) {
- final BitSet result = new BitSet();
- for (final X e : set)
- result.set(e.ordinal());
- return result;
- }
- /** Creates a BitSet of a given mask. */
- public static BitSet toBitSet(final BigInteger mask) {
- return BitSet.valueOf(mask.toByteArray());
- }
- /** Creates a BigInteger of a given mask. */
- public static BigInteger toBigInteger(final BitSet bitset) {
- return new BigInteger(bitset.toByteArray());
- }
- /** Creates set of enums from a 64 bit bitset. */
- public static <X extends Enum<X> & EnumBitOperations<X>> EnumSet<X> toEnumSet(final long mask, final Class<X> type) {
- final EnumSet<X> result = EnumSet.noneOf(type);
- for (final X e : EnumSet.allOf(type))
- if ((e.bitmask64() & mask) != 0)
- result.add(e);
- return result;
- }
- /** Creates set of enums from a BitSet. */
- public static <X extends Enum<X> & EnumBitOperations<X>> EnumSet<X> toEnumSet(final BitSet bitset, final Class<X> type) {
- long mask = 0L;
- for (int i = 0; i < bitset.length(); ++i)
- mask += bitset.get(i) ? 1L << i : 0L;
- return EnumBitOperations.toEnumSet(mask, type);
- }
- /**
- * Takes the bitmasks of <code>this</code> and all arguments, then applies
- * logical OR to all. This results in a bitmask for all given enums (including
- * <code>this</code>).
- *
- * @see #or(Enum...)
- * @see EnumSet#of(Enum)
- * @return <code>this.bitmask64() | arg0.bitmask64() | ... | argN.bitmask64()</code>
- */
- @SuppressWarnings("unchecked")
- public default <X extends Enum<X> & EnumBitOperations<X>> long or64(final X... set) {
- long result = this.bitmask64();
- for (final X e : set)
- result |= 1 << e.ordinal();
- return result;
- }
- /**
- *
- * Note that there is a much simpler way using {@link EnumSet#of(Enum)
- * of(...)}. The following expressions define the same set: <br>
- * <code>Planet.<b>EARTH</b>.or(Planet.<b>MARS</b>, Planet.<b>JUPITER</b>)<br/>
- * Planet.of(Planet.<b>EARTH</b>, Planet.<b>MARS</b>, Planet.<b>JUPITER</b>)</code>
- * <br/>
- * However, this method returns a bitmask of type BigInteger.
- *
- * @see EnumSet#of(Enum)
- * @see #or(BigInteger)
- * @return <code>this.bitmask() | arg<sub>0</sub>.bitmask() | ... | arg<sub>N</sub>.bitmask()</code>
- */
- @SuppressWarnings("unchecked")
- public default <X extends Enum<X> & EnumBitOperations<X>> BigInteger addedTo(final X... set) {
- BigInteger result = this.bitmask();
- for (final X e : set)
- result = result.or(e.bitmask());
- return result;
- }
- /**
- * Takes the bitmasks of <code>this</code> and <code>mask</code>, then applies
- * logical OR. This results in a new bitmask that also includes
- * <code>this</code>.
- *
- * @see #addedTo(BigInteger)
- * @see #addedTo(EnumSet)
- * @see #addedTo(Enum...)
- * @return <code>mask.or(this.bitmask())</code>
- */
- public default <X extends Enum<X> & EnumBitOperations<X>> BigInteger or(final BigInteger mask) {
- return mask.or(this.bitmask());
- }
- /**
- * @return <code>mask.and(this.bitmask())</code>
- */
- public default <X extends Enum<X> & EnumBitOperations<X>> BigInteger and(final BigInteger mask) {
- return mask.and(this.bitmask());
- }
- /**
- * @return <code>mask.xor(this.bitmask())</code>
- */
- public default <X extends Enum<X> & EnumBitOperations<X>> BigInteger xor(final BigInteger mask) {
- return mask.xor(this.bitmask());
- }
- /**
- * Removes this from mask, but only if its bit is set in the mask.
- *
- * @return <code>mask.andNot(this.bitmask())</code>
- */
- public default <X extends Enum<X> & EnumBitOperations<X>> BigInteger removedFrom(final BigInteger mask) {
- return mask.andNot(this.bitmask());
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement