-
-
Save gmuller/2933940 to your computer and use it in GitHub Desktop.
Going back and forth between BitSet and redis bit sets in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.BitSet; | |
import redis.clients.jedis.Jedis; | |
public class SieveOfEratosthenes { | |
private static String sieveSetKeyCorrected = "correct_sieve"; | |
private static String sieveSetKeyDefaultJava = "wrong_sieve"; | |
private static String spoolSieve = "sieve_set_bits"; | |
/** | |
* @param args | |
*/ | |
public static void main(final String[] args) { | |
// Initialize my redis client values | |
final Jedis redis = new Jedis("localhost"); | |
System.out.println("Alright, let's create a sieve of primes, Eratosthenes style!"); | |
final int length = 20; | |
final BitSet primes = new BitSet(length); | |
primes.flip(2, length); | |
for (int i = 0; i < length; i++) { | |
if (primes.get(i)) { | |
for (int j = i * 2; j < length; j += i) { | |
primes.set(j, false); | |
} | |
} | |
} | |
System.out.println("Let's set the bits in redis the ol' fashioned way"); | |
System.out.println("One at a time using redis.setbit"); | |
for (int i = 0; i < primes.length(); i++) { | |
if (primes.get(i)) { | |
redis.setbit(spoolSieve, i, true); | |
} | |
} | |
System.out.println("And then read the bitset out, just like the example"); | |
final BitSet spoolWaySieve = BitSet.valueOf(redis.get(spoolSieve.getBytes())); | |
System.out.println("And compare the values"); | |
System.out.println("Original Sieve: " + primes); | |
System.out.println("Read via BitSet.valueOf(): " + spoolWaySieve); | |
System.out.println("\nWhat The? Thats not right at all!"); | |
System.out.println("Let's try reversing the bits in the bytes"); | |
final BitSet correctedBits = fromByteArrayReverse(redis.get(spoolSieve.getBytes())); | |
System.out.println("And compare the values"); | |
System.out.println("Original Sieve: " + primes); | |
System.out.println("Read via helper method: " + correctedBits); | |
System.out.println("\nThat's better."); | |
System.out.println("Now what happens if I try to write the entire BitSet into Redis"); | |
System.out.println("Using the BitSet.toByteArray() method built-in"); | |
System.out.println("Then pull the values back out"); | |
redis.set(sieveSetKeyDefaultJava.getBytes(), primes.toByteArray()); | |
final BitSet defaultJava = | |
BitSet.valueOf(redis.get(sieveSetKeyDefaultJava.getBytes())); | |
System.out.println("Original Sieve: " + primes); | |
System.out | |
.println("Stored via BitSet.toByteArray() and retrieved via BitSet.valueOf: " | |
+ defaultJava); | |
System.out.println("\nThat appears to work...but there is a catch"); | |
System.out.println("If you try to read the values out using getBit"); | |
System.out | |
.println("They are mangled because we effectively used Java's byte ordering"); | |
System.out.println("Look. redis.getbit(4) -> " | |
+ redis.getbit(sieveSetKeyDefaultJava, 4)); | |
System.out.println("Last I checked, 4 is not prime"); | |
System.out.println("\nThis also means calls to getbit from another language"); | |
System.out.println("and especially redis-cli, will be incorrect"); | |
System.out | |
.println("\nSo, let's write another helper method to reverse the bits on the way in"); | |
System.out.println("And write the sieve of primes"); | |
System.out.println("And check to make sure the native calls to getBit still work"); | |
System.out.println("And use our helper method to get the BitSet in one call"); | |
redis.set(sieveSetKeyCorrected.getBytes(), toByteArrayReverse(primes)); | |
final BitSet correctedSieve = | |
fromByteArrayReverse(redis.get(sieveSetKeyCorrected.getBytes())); | |
System.out.println("Original Sieve: " + primes); | |
System.out.println("Stored via helper method and retrieved via helper method: " | |
+ correctedSieve); | |
System.out | |
.println("Look. redis.getbit(4) -> " + redis.getbit(sieveSetKeyCorrected, 4)); | |
System.out | |
.println("\nThere we go. Use a help method to reverse the bits on the way in or out"); | |
System.out.println("To make sure your native calls still work"); | |
} | |
public static BitSet fromByteArrayReverse(final byte[] bytes) { | |
final BitSet bits = new BitSet(); | |
for (int i = 0; i < bytes.length * 8; i++) { | |
if ((bytes[i / 8] & (1 << (7 - (i % 8)))) != 0) { | |
bits.set(i); | |
} | |
} | |
return bits; | |
} | |
public static byte[] toByteArrayReverse(final BitSet bits) { | |
final byte[] bytes = new byte[bits.length() / 8 + 1]; | |
for (int i = 0; i < bits.length(); i++) { | |
if (bits.get(i)) { | |
final int value = bytes[i / 8] | (1 << (7 - (i % 8))); | |
bytes[i / 8] = (byte) value; | |
} | |
} | |
return bytes; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
final BitSet correctedBits = fromByteArrayReverse(redis.get(spoolSieve.getBytes()));
Why did you convert the redis key from string to byte[] ?