bitMap原理 :
如下: index 从 0 到 9 ,依次对应到一个bit位上,如果index 代表用户id,bit位上的0 1分表 代表用户是否登录;
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操作,见 ,该篇对bitSet用法介绍很详细;
redis工具类:
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上的标示;
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); }}//该天登录所有的用户idpublic ListactiveUserIds(String dateKey) { Jedis jedis= RedisUtil.getResource(); try{ if(jedis.get(key)==null){ return null; } BitSet set= BitSetUtils.byteArray2BitSet(jedis.get(key).getBytes()); List list=new ArrayList (); for (long i=0;i
2 如果我们想统计n天,连续登录的用户数,及UserId:
public ListcontinueActiveUserCount(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 list=new ArrayList (); for (long i=0;i
转载请注明来源: