class RangeBinner extends AbstractBinner<T> {

    ThreeTuple<Double, Double, Object> getMinMaxBinValueValue(T data)
    {
        ThreeTuple<Double, Double, Object> minMaxBin = null;
        Object sampleValue = myDataToValue.apply(data);
        if (sampleValue != null)
        {
            double sampleDoubleValue = myValueToDouble.applyAsDouble(sampleValue);
            double min = round(Math.floor(round(sampleDoubleValue / myCriteria.getBinWidth())) * myCriteria.getBinWidth());
            double max = round(min + myCriteria.getBinWidth());
            Object binValue = myDoubleToValue.apply(Double.valueOf(min), sampleValue.getClass());
            minMaxBin = new ThreeTuple<>(Double.valueOf(min), Double.valueOf(max), binValue);
        }

        return minMaxBin;
    }

    public  RangeBinner(RangeCriteria criteria, Function<T, ?> dataToValue, ToDoubleFunction<Object> valueToDouble,
            BiFunction<Double, Class<?>, Object> doubleToValue);
    public  RangeBinner(List<Bin<T>> bins);

}