Bit Implementation using Enum (Java and Groovy)

The assumption here is that you have basic knowledge of Enums. Also, I will be writing all Groovy code here, you can simply convert it to Java using Java’s syntax. 

Let’s first understand why and when you can use Bit Implementation in your code. In many of the scenarios, you might need to represent a similar status of any object. Consider any bill, whose status might be pending or paid (you can think of any other status too), in such cases you can create an enum like,

enum BillStatus {

    PENDING(1),

    PAID(2)
 }

The status pending may have many states too, like payment initiated which means the payment is still pending but has been initiated. In this case, we would require designing hierarchy for these statuses. This is where we will find the concept of Bit Implementation useful.

We need to understand some binary operations before we can proceed to actually implement it. The magic of 2 is what we will be using here. Any number that is a power of 2 (2 as its only prime factor) can be used as a root to create hierarchy (Wait, things will get clear as we proceed).

The concept behind using a number that is having 2 as its only prime factor is that it will have only one bit which is set (one) and others are clear (zero) in its binary representation.

Like, 1 can be written as (8-bit representation) 0000_0001,

2 as 0000_0010, similarly 4 as 0000_0100 and so on.

Or Operation on Bits

If we perform an OR operation on any number which is a power of 2, we find that all bits remain unchanged except the one which is set.

Like, 2 | 5 results to 7.

Let us analyse, 2 in binary is: 0000_0010 and 5 in binary is: 0000_0101, so

0000_0010  (2)

0000_0101  (5)  (OR)

0000_0111  (7)  (ans)

Thus, the OR operation will set the bit if it’s clear and will not change anything if that bit is already set.

You might be thinking how this is going to help us in our problem, let us dig deeper to find that out.

What will happen if I consider 2 as PENDING and 7 as INITIATED ??

The answer is that we can easily find that INITIATED status is still a PENDING status at the root level just by reversing the process i.e performing an AND operation.

0000_0111 (7)

0000_0010 (2)  (AND)

0000_0010 (2)  (ans)

The AND operation sets all bits to zero except the one which is set, so if any number whose 2nd bit (from right) is not set and it is ANDed with 2 (PENDING in this case) will result in all zero’s.

Thus, if we have a number with only 2 as its prime factor (say X), we can OR it with any number (say Y) and get a status (say Z) and then perform reverse operation i.e AND to check if that number Z is actually generated from X or not.

Like X | Y = Z

then, Z & X = X.

Now let’s implement that in our code.

enum BillStatus {

    INITIATED(PENDING | 4),

    BILL_AMOUNT_ENTERED(PENDING | 8),

    
    CREDIT_CARD_PAYMENT(PAID | 4),

    NETBANKING_PAYMENT(PAID  | 8)

    static final int PENDING = 1 // 0000_0001

    static final int PAID = 2 // 0000_0010
 }

Note: PENDING and PAID are not enum constants now, though they are constants because we have used “static and final” keywords.

Q. Why to OR with 4 and 8 ?

We could have used any number but using numbers with 2 as the only prime factor will make it easier because now only 2 bits will be set, one for the number itself and one representing either PENDING or PAID.

Now let’s write the code for checking and also make it cleaner and usable.

enum BillStatus {

     // (1 | 4)  = 5
     INITIATED(PENDING | 4)

     // (1 | 8) = 9
     BILL_AMOUNT_ENTERED(PENDING | 8)

     // (2 | 4) = 6
     CREDIT_CARD_PAYMENT(PAID | 4)

     // (2 | 8) = 10
     NETBANKING_PAYMENT(PAID | 8)

     static final int PENDING = 1 // 0000_0001
     static final int PAID = 2 // 0000_0010

     // Constructor
     BillStatus(int id) {
         this.id = id
     }

     // check if Pending
     boolean isPending() {
         return ((this.id & PENDING) == PENDING)   // Z & X = X
     }

     // check if Paid
     boolean isPaid() {
         return ((this.id & PAID) == PAID)
     }
 }

Note: It seems like addition but it is not, it is OR operation and it will show up different results with other numbers.

Enums are actually used to write type-safe code.

Like, instead of writing a code as

if (num == 5) {
    println “BillStatus is INITIATED”
}

it’s preferred to use enums and write it as

if (num == BillStatus.INITIATED) {
    println “BillStatus is INITIATED”
}


Hope you found it useful. Thanks for reading.

 

About CauseCode: We are a technology company specializing in Healthtech related Web and Mobile application development. We collaborate with passionate companies looking to change health and wellness tech for good. If you are a startup, enterprise or generally interested in digital health, we would love to hear from you! Let's connect at bootstrap@causecode.com
Have you subscribed to our blogs and newsletter? If not, what are you waiting for?  Click Here

Leave a Reply

Your email address will not be published. Required fields are marked *

SUBSCRIBE!

Do you want to get articles like these in your inbox?

Email *

Interested groups *
Healthtech
Business
Technical articles

Archives