bitMap原理 :java
以下: index 從 0 到 9 ,依次對應到一個bit位上,若是index 表明用戶id,bit位上的0 1分表 表明用戶是否登陸;redis
1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
redis數據結構中 string 類型,包含了對bitmap的實現;在redis-cli中,能夠經過setbit getbit 來對bit進行操做;本文經過jedis來對redis進行操做; 數據結構
BitSet工具類:實現對經過jedis.get(key)取出的byte[]值與BitSet的轉換工具
public class BitSetUtils { /** * 將BitSet對象轉化爲ByteArray * @param bitSet * @return */ public static byte[] bitSet2ByteArray(BitSet bitSet) { byte[] bytes = new byte[bitSet.size() / 8]; for (int i = 0; i < bitSet.size(); i++) { int index = i / 8; int offset = 7 - i % 8; bytes[index] |= (bitSet.get(i) ? 1 : 0) << offset; } return bytes; } /** * * @param bytes * @return */ public static BitSet byteArray2BitSet(byte[] bytes) { BitSet bitSet = new BitSet(bytes.length * 8); int index = 0; for (int i = 0; i < bytes.length; i++) { for (int j = 7; j >= 0; j--) { bitSet.set(index++, (bytes[i] & (1 << j)) >> j == 1 ? true : false); } } return bitSet; } }
具體對java中BitSet操做,見http://my.oschina.net/cloudcoder/blog/294810 ,該篇對bitSet用法介紹很詳細;spa
redis工具類:.net
public class RedisUtil { static { initPool(); } private static volatile JedisPool jedisPool; private static ResourceBundle resourceBundle; public static Jedis getResource() { return jedisPool.getResource(); } public static void returnResource(Jedis jedis) { jedisPool.returnResource(jedis); } public static void initPool() { if(jedisPool != null){ return; } loadProperties(); String host = resourceBundle.getString("redis.host"); String passwd= resourceBundle.getString("redis.passwd"); int port = Integer.parseInt(resourceBundle.getString("redis.port")); JedisPoolConfig config = config(); jedisPool = new JedisPool(config,host,port,60,passwd); } private static void loadProperties() { resourceBundle = ResourceBundle.getBundle("config/redis-config"); } private static JedisPoolConfig config() { JedisPoolConfig config = new JedisPoolConfig(); return config; } public static void main(String[]args){ Jedis jedis= RedisUtil.getResource(); RedisUtil.returnResource(jedis); } }
1 統計系統中某天用戶登陸的狀況:以當天日期作爲key ,好比 ‘20150410’ ,對應的 bitMap 的 index 用userId來標示,UserId這裏用 long 型表示,若是id不是以0開頭,能夠加上相應的偏移量就OK了;若是該天用戶登陸,調用activeUser方法,來更改bitMap相應index上的標示;
code
public void activeUser(long userId, String dateKey) { Jedis jedis= RedisUtil.getResource(); try{ jedis.setbit(dateKey,userId,true); }finally { RedisUtil.returnResource(jedis); } }
若是咱們想統計該天用戶登陸的數量,及登陸的用戶id,能夠經過以下方法實現:對象
//該天用戶總數 public long totalCount(String dateKey) { Jedis jedis= RedisUtil.getResource(); try{ return jedis.bitcount(dateKey); }finally { RedisUtil.returnResource(jedis); } } //該天登陸全部的用戶id public List<Long> activeUserIds(String dateKey) { Jedis jedis= RedisUtil.getResource(); try{ if(jedis.get(key)==null){ return null; } BitSet set= BitSetUtils.byteArray2BitSet(jedis.get(key).getBytes()); List<Long>list=new ArrayList<Long>(); for (long i=0;i<set.size();i++){ if(set.get(i)){ list.add(i); } } return list; }finally { RedisUtil.returnResource(jedis); } }
2 若是咱們想統計n天,連續登陸的用戶數,及UserId:
blog
public List<Long> continueActiveUserCount(String... dateKeys) { Jedis jedis= RedisUtil.getResource(); try{ BitSet all = null; for (String key:dateKeys){ if(jedis.get(key)==null){ continue; } BitSet set= BitSetUtils.byteArray2BitSet(jedis.get(key).getBytes()); if(all==null){ all=set; } System.out.println(set.size()); all.and(set); } List<Long>list=new ArrayList<Long>(); for (long i=0;i<all.size();i++){ if(all.get(i)){ list.add(i); } } return list; }finally { RedisUtil.returnResource(jedis); } }
轉載請註明來源:http://my.oschina.net/robinyao/blog/398808get