code: public static AssociativeArray optimumSampleSize(int n, AssociativeArray populationNh, AssociativeArray populationStdh) {
          AssociativeArray nh = new AssociativeArray();
          
          double sumNhSh = 0.0;
          for(Map.Entry<Object, Object> entry : populationNh.entrySet()) {
              Object strata = entry.getKey();
              Integer populationInStrata = ((Number)entry.getValue()).intValue();
              Double populationStd = populationStdh.getDouble(strata);
              
              if(populationStd == null || populationInStrata <=0.0) {
                  throw new IllegalArgumentException("Invalid strata population or strata std.");
              }
              
              double NhSh = populationInStrata*populationStd;
              
              sumNhSh+=NhSh;
  
              nh.put(strata, n*NhSh);
          }
          
          if(sumNhSh<=0) {
              throw new IllegalArgumentException("Invalid strata populations.");
          }
          
          for(Map.Entry<Object, Object> entry : nh.entrySet()) {
              Object strata = entry.getKey();
              nh.put(strata, TypeInference.toDouble(entry.getValue())/sumNhSh);
          }
          
          return nh;
      }
docs: Returns the optimum sample size per strata under Neyman Allocation
  
  @param n
  @param populationNh
  @param populationStdh
  @return