Skip to content

Instantly share code, notes, and snippets.

@gmuller
Forked from gresrun/redisBitSetTests.java
Created June 15, 2012 00:45
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gmuller/2933940 to your computer and use it in GitHub Desktop.
Save gmuller/2933940 to your computer and use it in GitHub Desktop.
Going back and forth between BitSet and redis bit sets in Java
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;
}
}
@vishalseshagiri
Copy link

final BitSet correctedBits = fromByteArrayReverse(redis.get(spoolSieve.getBytes()));
Why did you convert the redis key from string to byte[] ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment