code: public ArrayList<InetAddress> getNaturalEndpoints(RingPosition searchPosition)
      {
          Token searchToken = searchPosition.getToken();
          Token keyToken = TokenMetadata.firstToken(tokenMetadata.sortedTokens(), searchToken);
          ArrayList<InetAddress> endpoints = getCachedEndpoints(keyToken);
          if (endpoints == null)
          {
              TokenMetadata tm = tokenMetadata.cachedOnlyTokenMap();
              // if our cache got invalidated, it's possible there is a new token to account for too
              keyToken = TokenMetadata.firstToken(tm.sortedTokens(), searchToken);
              endpoints = new ArrayList<InetAddress>(calculateNaturalEndpoints(searchToken, tm));
              cachedEndpoints.put(keyToken, endpoints);
          }
  
          return new ArrayList<InetAddress>(endpoints);
      }
docs: get the (possibly cached) endpoints that should store the given Token.
  Note that while the endpoints are conceptually a Set (no duplicates will be included),
  we return a List to avoid an extra allocation when sorting by proximity later
  @param searchPosition the position the natural endpoints are requested for
  @return a copy of the natural endpoints for the given token