public static int getWeightedRandom(ArrayList<Float> weights) {
    int i;
    float totalWeight = 0;
    for (i = 0; i < weights.size(); i++) {
      if (weights.get(i) > 0) {
        totalWeight += weights.get(i);
      }
    }
    if (totalWeight == 0) {
      return -1;
    }
    float samplePoint = rand.nextFloat() * totalWeight;
    int lastIndex = 0;
    for (i = 0; i < weights.size(); i++) {
      if (weights.get(i) > 0) {
        if (samplePoint <= weights.get(i)) {
          return i;
        } else {
          lastIndex = i;
          samplePoint -= weights.get(i);
        }
      }
    }
    // This can only happen if samplePoint is very close to totalWeight and
    // float rounding kicks in during subtractions
    return lastIndex;
  }
@Test
  public void testGetWeightedRandom() {
    int i;
    float[] weights =
        new float[] {0, 0.1f, 0.2f, 0.2f, -0.1f, 0.1f, 0.2f, 0.1f, 0.1f};
    float[] expectedWeights =
        new float[] {0, 0.1f, 0.2f, 0.2f, 0, 0.1f, 0.2f, 0.1f, 0.1f};
    int[] result = new int[weights.length];

    ArrayList<Float> weightsList = new ArrayList<>();
    for (float weight : weights) {
      weightsList.add(weight);
    }

    int n = 10000000;
    for (i = 0; i < n; i++) {
      int sample = FederationPolicyUtils.getWeightedRandom(weightsList);
      result[sample]++;
    }
    for (i = 0; i < weights.length; i++) {
      double actualWeight = (float) result[i] / n;
      System.out.println(i + " " + actualWeight);
      Assert.assertTrue(
          "Index " + i + " Actual weight: " + actualWeight
              + " expected weight: " + expectedWeights[i],
          Math.abs(actualWeight - expectedWeights[i]) < 0.01);
    }
  }