public static Cluster swapRandomPartitionsWithinZone(final Cluster nextCandidateCluster,
                                                         final int zoneId) {
        Cluster returnCluster = Cluster.cloneCluster(nextCandidateCluster);
        Random r = new Random();

        List<Integer> nodeIdsInZone = new ArrayList<Integer>(nextCandidateCluster.getNodeIdsInZone(zoneId));

        if(nodeIdsInZone.size() == 0) {
            return returnCluster;
        }

        // Select random stealer node
        int stealerNodeOffset = r.nextInt(nodeIdsInZone.size());
        Integer stealerNodeId = nodeIdsInZone.get(stealerNodeOffset);

        // Select random stealer partition
        List<Integer> stealerPartitions = returnCluster.getNodeById(stealerNodeId)
                                                       .getPartitionIds();
        if(stealerPartitions.size() == 0) {
            return nextCandidateCluster;
        }
        int stealerPartitionOffset = r.nextInt(stealerPartitions.size());
        int stealerPartitionId = stealerPartitions.get(stealerPartitionOffset);

        // Select random donor node
        List<Integer> donorNodeIds = new ArrayList<Integer>();
        donorNodeIds.addAll(nodeIdsInZone);
        donorNodeIds.remove(stealerNodeId);

        if(donorNodeIds.isEmpty()) { // No donor nodes!
            return returnCluster;
        }
        int donorIdOffset = r.nextInt(donorNodeIds.size());
        Integer donorNodeId = donorNodeIds.get(donorIdOffset);

        // Select random donor partition
        List<Integer> donorPartitions = returnCluster.getNodeById(donorNodeId).getPartitionIds();
        int donorPartitionOffset = r.nextInt(donorPartitions.size());
        int donorPartitionId = donorPartitions.get(donorPartitionOffset);

        return swapPartitions(returnCluster,
                              stealerNodeId,
                              stealerPartitionId,
                              donorNodeId,
                              donorPartitionId);
    }
public static Cluster swapRandomPartitionsWithinZone ( final Cluster nextCandidateCluster , final int zoneId ) { Cluster returnCluster = Cluster . cloneCluster ( nextCandidateCluster ) ; Random r = new Random ( ) ; List < Integer > nodeIdsInZone = new ArrayList < Integer > ( nextCandidateCluster . getNodeIdsInZone ( zoneId ) ) ; if ( nodeIdsInZone . size ( ) == 0 ) { return returnCluster ; } int stealerNodeOffset = r . nextInt ( nodeIdsInZone . size ( ) ) ; Integer stealerNodeId = nodeIdsInZone . get ( stealerNodeOffset ) ; List < Integer > stealerPartitions = returnCluster . getNodeById ( stealerNodeId ) . getPartitionIds ( ) ; if ( stealerPartitions . size ( ) == 0 ) { return nextCandidateCluster ; } int stealerPartitionOffset = r . nextInt ( stealerPartitions . size ( ) ) ; int stealerPartitionId = stealerPartitions . get ( stealerPartitionOffset ) ; List < Integer > donorNodeIds = new ArrayList < Integer > ( ) ; donorNodeIds . addAll ( nodeIdsInZone ) ; donorNodeIds . remove ( stealerNodeId ) ; if ( donorNodeIds . isEmpty ( ) ) { return returnCluster ; } int donorIdOffset = r . nextInt ( donorNodeIds . size ( ) ) ; Integer donorNodeId = donorNodeIds . get ( donorIdOffset ) ; List < Integer > donorPartitions = returnCluster . getNodeById ( donorNodeId ) . getPartitionIds ( ) ; int donorPartitionOffset = r . nextInt ( donorPartitions . size ( ) ) ; int donorPartitionId = donorPartitions . get ( donorPartitionOffset ) ; return swapPartitions ( returnCluster , stealerNodeId , stealerPartitionId , donorNodeId , donorPartitionId ) ; }
Within a single zone, swaps one random partition on one random node with
another random partition on different random node.

@param nextCandidateCluster
@param zoneId Zone ID within which to shuffle partitions
@return updated cluster