docs: @Override
      public Map<Integer, Integer> pPredecessors(int partition) {
          Map<Integer, Integer> predecessors = new TreeMap<Integer, Integer>();
          UnmodifiableIterator<Map.Entry<Integer,Integer>> iter = m_tokensMap.get().entrySet().iterator();
          Set<Integer> pTokens = new HashSet<Integer>();
          while (iter.hasNext()) {
              Map.Entry<Integer, Integer> next = iter.next();
              if (next.getValue() == partition) {
                  pTokens.add(next.getKey());
              }
          }
  
          for (Integer token : pTokens) {
              Map.Entry<Integer, Integer> predecessor = null;
              if (token != null) {
                  predecessor = m_tokensMap.get().headMap(token).lastEntry();
                  // If null, it means partition is the first one on the ring, so predecessor
                  // should be the last entry on the ring because it wraps around.
                  if (predecessor == null) {
                      predecessor = m_tokensMap.get().lastEntry();
                  }
              }
  
              if (predecessor != null && predecessor.getValue() != partition) {
                  predecessors.put(predecessor.getKey(), predecessor.getValue());
              }
          }
  
          return predecessors;
      }