Skip to content

Select enum constants from boolean[] or bit mask#44

Merged
runeflobakk merged 8 commits intomainfrom
select-enums-from-bits-n-bools
Mar 27, 2026
Merged

Select enum constants from boolean[] or bit mask#44
runeflobakk merged 8 commits intomainfrom
select-enums-from-bits-n-bools

Conversation

@runeflobakk
Copy link
Copy Markdown
Member

@runeflobakk runeflobakk commented Mar 6, 2026

Use a bit mask to select constants from an enum, based on which indices which are set (1-bits):

<E extends Enum<E>> Stream<E> DiggEnums.selectOrdinalsByBitmask(Class<E>, BitSet)

Use an array of booleans to select constants from an enum, based on which indices which are true;

<E extends Enum<E>> Stream<E> DiggEnums.selectOrdinalsByIndex(Class<E>, boolean[])

Use case

This is obviously a bit esoteric functionality. The intention is to ease the use of some APIs which may (probably for valid performance reasons, at least at the time the APIs were defined) return a kind of bitmask to represent a standardized set of possibly set or unset values.

An example of this is X509Certificate.getKeyUsage(), which returns an array of booleans, where each element's position in the array indicate if a known set of ordered values is true or false. This will enable e.g. the following:

/// Enum representation of the X.509 KeyUsage extension (OID = 2.5.29.15).
/// The order of constants reflect the order of the ASN.1 definition, see
/// [X509Certificate#getKeyUsage()].
enum KeyUsage {
    digitalSignature,
    nonRepudiation,
    keyEncipherment,
    dataEncipherment,
    keyAgreement,
    keyCertSign,
    cRLSign,
    encipherOnly,
    decipherOnly;

    static Stream<KeyUsage> allFrom(X509Certificate certificate) {
        return selectByIndexAsOrdinals(certificate.getKeyUsage(), KeyUsage.class);
    }
}

Note on EnumSet

Java already has a way to represent a set of enum constants using a compact and efficient bitmask, but no way to construct the EnumSet using a bitmask as the source.

@runeflobakk runeflobakk requested a review from haralkvi March 6, 2026 14:18
@runeflobakk runeflobakk force-pushed the select-enums-from-bits-n-bools branch 2 times, most recently from ddcd566 to 0a7477e Compare March 6, 2026 14:27
Comment thread src/test/resources/simplelogger.properties Outdated
Comment thread src/main/java/no/digipost/DiggEnums.java Outdated
Comment thread src/main/java/no/digipost/DiggEnums.java
if (candidates.length == 0) {
return Stream.empty();
}
return mask.get(0, candidates.length).stream().mapToObj(selectedOrdinal -> candidates[selectedOrdinal]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jeg skjønner åpenbart ikke hvordan dette virker… vil ikke selectedOrdnial alltid bare være 0 eller 1?

Copy link
Copy Markdown
Member Author

@runeflobakk runeflobakk Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ja, den er sneaky 😅
Et BitSet er ikke en Collection (eller java.util.Set), det er en helt standalone struktur for å behandle bit-sekvenser.

BitSet.stream() gir ikke hvert av elementene i bit-sekvensen, altså en strøm med 0-er og 1-ere og som typisk ville vært ekvivalent til å kalle .stream() på en collection, men (hold deg fast) indeksene til de bit-ene som er satt, altså hvilke bits som er 1. Dette gir altså en strøm-linjeformet (høhø) tilgang til hvilke bits som er "påskrudd", fremfor å selv traversere alle bits, holde styr på hvilke posisjon man er på og sjekke 0 vs. 1 etc.

Edit: Det som kanskje ikke er åpenbart her heller, er at BitSet.get(0, candidates.length) gir et nytt BitSet, og ikke en collection hvor man får det antallet første bits man spesifiserer, også kaller .stream() på en sånn collection.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BitSet.stream() gir ikke hvert av elementene i bit-sekvensen, altså en strøm med 0-er og 1-ere […], men […] indeksene til de bit-ene som er satt, altså hvilke bits som er 1.

Da gir det straks mer mening! 💡

@runeflobakk runeflobakk force-pushed the select-enums-from-bits-n-bools branch 2 times, most recently from ef33d0e to cd52ab5 Compare March 6, 2026 15:50
Copy link
Copy Markdown

@haralkvi haralkvi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Only log warns, and use System.out (not slf4j-simple's default
System.err)
Grouping into nested test classes
A BitSet constructed from a long is interpreted little endian, i.e. the
bits of a long is traversed "from right-to-left".
@runeflobakk runeflobakk force-pushed the select-enums-from-bits-n-bools branch from cd52ab5 to 93ba670 Compare March 27, 2026 12:20
@runeflobakk runeflobakk merged commit c3a42d8 into main Mar 27, 2026
3 checks passed
@runeflobakk runeflobakk deleted the select-enums-from-bits-n-bools branch March 27, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants