package com.meidusa.amoeba.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; public class ConsistentHash<T> { public static class Entry<T>{ T object; int replicas; Entry(){} Entry(T obj,int replicas){ this.object = obj; this.replicas = replicas; } Entry(T obj){ this.object = obj; this.replicas = 1; } } private final HashFunction hashFunction; private final SortedMap<Long, T> circle = new TreeMap<Long, T>(); private final Map<T,Integer> replicas = new HashMap<T,Integer>(); public ConsistentHash(HashFunction hashFunction) { this.hashFunction = hashFunction; /*for (T node : nodes) { add(node); }*/ } public void addAll(Collection<Entry<T>> collection){ for(Entry<T> entry : collection){ add(entry.object,entry.replicas); } } public void add(T node,int numberOfReplicas) { for (int i = 0; i < numberOfReplicas; i++) { circle.put((long)hashFunction.hash(node.toString()+i), node); } replicas.put(node, numberOfReplicas); } public void remove(T node) { Integer numberOfReplicas = replicas.get(node); if(numberOfReplicas == null){ return; } for (int i = 0; i < numberOfReplicas; i++) { circle.remove(hashFunction.hash(node.toString() + i)); } } public T get(Object key) { if (circle.isEmpty()) { return null; } long hash = hashFunction.hash(key); if (!circle.containsKey(hash)) { SortedMap<Long, T> tailMap = circle.tailMap(hash); hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); } return circle.get(hash); } public static void main(String[] args){ Collection<Entry<Object>> coll = new ArrayList<Entry<Object>>(); coll.add(new Entry("asdfqwer")); coll.add(new Entry("b")); coll.add(new Entry("c")); coll.add(new Entry("d")); coll.add(new Entry("e")); coll.add(new Entry("f")); coll.add(new Entry("g")); coll.add(new Entry("h")); coll.add(new Entry("i")); coll.add(new Entry("j")); coll.add(new Entry("k")); coll.add(new Entry("l")); ConsistentHash<Object> hash = new ConsistentHash<Object>(new HashFunction(){ public long hash(Object string) { return string.hashCode() % 1024; } }); hash.addAll(coll); long start = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ //System.out.println(hash.get(i)); hash.get(i); } System.out.println(System.currentTimeMillis() - start); } }