public class BytesKey implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = -6296965387124592707L; private byte[] data; public BytesKey(byte[] data) { this.data = data; } /** * @return the data */ public byte[] getData() { return data; } /** * @param data the data to set */ public void setData(byte[] data) { this.data = data; } @Override public int hashCode() { int h = 0; if (null != this.data) { for (int i = 0; i < this.data.length; i++) { h = 31*h + data[i++]; } } return h; } @Override public boolean equals(Object o) { if (null == o || !(o instanceof BytesKey)) { return false; } BytesKey k = (BytesKey)o; if (null == k.getData() && null == this.getData()) { return true; } if (null == k.getData() || null == this.getData()) { return false; } if (k.getData().length != this.getData().length) { return false; } for (int i = 0; i < this.data.length; ++i) { if (this.data[i] != k.getData()[i]) { return false; } } return true; } }
顺带使用BytesKey实现的简单Memory KV缓存
public class MemStore implements Store { private Map<BytesKey, byte[]> datas = new ConcurrentHashMap<BytesKey, byte[]>(); /* * (non-Javadoc) * * @see com.taobao.common.store.Store#add(byte[], byte[]) */ public void add(byte[] key, byte[] data) throws IOException { datas.put(new BytesKey(key), data); } /* * (non-Javadoc) * * @see com.taobao.common.store.Store#get(byte[]) */ public byte[] get(byte[] key) throws IOException { return datas.get(new BytesKey(key)); } /* * (non-Javadoc) * * @see com.taobao.common.store.Store#iterator() */ public Iterator<byte[]> iterator() throws IOException { final Iterator<BytesKey> it = datas.keySet().iterator(); return new Iterator<byte[]>() { public boolean hasNext() { return it.hasNext(); } public byte[] next() { BytesKey key = it.next(); if (null == key) { return null; } return key.getData(); } public void remove() { it.remove(); } }; } /* * (non-Javadoc) * * @see com.taobao.common.store.Store#remove(byte[]) */ public boolean remove(byte[] key) throws IOException { return null != datas.remove(new BytesKey(key)); } /* * (non-Javadoc) * * @see com.taobao.common.store.Store#size() */ public int size() { return datas.size(); } /* * (non-Javadoc) * * @see com.taobao.common.store.Store#update(byte[], byte[]) */ public boolean update(byte[] key, byte[] data) throws IOException { datas.put(new BytesKey(key), data); return true; } public void close() throws IOException { // nodo } public long getMaxFileCount() { return Long.MAX_VALUE; } public void setMaxFileCount(long maxFileCount) { } }
使用双重hash算key,
private int hash(int keyHash, int i) { return abs(hash1(keyHash) + i * hash2(keyHash)) % table.length; // 双重散列 }
使用BitSet进行快速判定key是否存在,存在的话进行下一轮的双重hash算key
while (this.table[j] != null && !isEntryDeleted(j) && this.bitSet.get(offset) && i < m) { j = hash(keyHash, i++); offset = calcOffset(j); }