code: public static <T, U> JavaPairRDD<T, U>[] balancedRandomSplit(int totalObjectCount, int numObjectsPerSplit,
                      JavaPairRDD<T, U> data, long rngSeed) {
          JavaPairRDD<T, U>[] splits;
          if (totalObjectCount <= numObjectsPerSplit) {
              splits = (JavaPairRDD<T, U>[]) Array.newInstance(JavaPairRDD.class, 1);
              splits[0] = data;
          } else {
              int numSplits = totalObjectCount / numObjectsPerSplit; //Intentional round down
  
              splits = (JavaPairRDD<T, U>[]) Array.newInstance(JavaPairRDD.class, numSplits);
              for (int i = 0; i < numSplits; i++) {
  
                  //What we really need is a .mapPartitionsToPairWithIndex function
                  //but, of course Spark doesn't provide this
                  //So we need to do a two-step process here...
  
                  JavaRDD<Tuple2<T, U>> split = data.mapPartitionsWithIndex(
                                  new SplitPartitionsFunction2<T, U>(i, numSplits, rngSeed), true);
                  splits[i] = split.mapPartitionsToPair(new MapTupleToPairFlatMap<T, U>(), true);
              }
          }
          return splits;
      }
docs: Equivalent to {@link #balancedRandomSplit(int, int, JavaRDD)} but for pair RDDs, and with control over the RNG seed