@Override
 public InetSocketAddress route(byte[] key, int partition) {
   TreeMap<Integer, InetSocketAddress> circle = circleMap.get(partition);
   if (circle == null || circle.isEmpty()) {
     return null;
   }
   int hash = (int) hashProvider.hash(key);
   if (!circle.containsKey(hash)) {
     SortedMap<Integer, InetSocketAddress> tailMap = circle.tailMap(hash);
     hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
   }
   return circle.get(hash);
 }
  @Override
  public void clusterChanged(Map<Integer, ArrayList<InetSocketAddress>> clusterView) {
    Map<Integer, TreeMap<Integer, InetSocketAddress>> tmpMap =
        new HashMap<Integer, TreeMap<Integer, InetSocketAddress>>();

    for (Entry<Integer, ArrayList<InetSocketAddress>> entry : clusterView.entrySet()) {
      Integer partition = entry.getKey();
      TreeMap<Integer, InetSocketAddress> circle = new TreeMap<Integer, InetSocketAddress>();
      tmpMap.put(partition, circle);
      for (InetSocketAddress newNode : entry.getValue()) {
        for (int count = 0; count < numberOfReplicas; ++count) {
          String key = newNode.toString() + count;
          circle.put((int) hashProvider.hash(key.getBytes()), newNode);
        }
      }
    }
    circleMap = tmpMap;
  }