ReducingBindings.java
0001 /*
0002  * Copyright 2008-2017 the original author or authors.
0003  *
0004  * Licensed under the Apache License, Version 2.0 (the "License");
0005  * you may not use this file except in compliance with the License.
0006  * You may obtain a copy of the License at
0007  *
0008  *     http://www.apache.org/licenses/LICENSE-2.0
0009  *
0010  * Unless required by applicable law or agreed to in writing, software
0011  * distributed under the License is distributed on an "AS IS" BASIS,
0012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013  * See the License for the specific language governing permissions and
0014  * limitations under the License.
0015  */
0016 package griffon.javafx.beans.binding;
0017 
0018 import javafx.beans.binding.BooleanBinding;
0019 import javafx.beans.binding.DoubleBinding;
0020 import javafx.beans.binding.FloatBinding;
0021 import javafx.beans.binding.IntegerBinding;
0022 import javafx.beans.binding.LongBinding;
0023 import javafx.beans.binding.NumberBinding;
0024 import javafx.beans.binding.ObjectBinding;
0025 import javafx.beans.binding.StringBinding;
0026 import javafx.beans.value.ObservableValue;
0027 import javafx.collections.ObservableList;
0028 import javafx.collections.ObservableMap;
0029 import javafx.collections.ObservableSet;
0030 
0031 import javax.annotation.Nonnull;
0032 import javax.annotation.Nullable;
0033 import java.util.function.BinaryOperator;
0034 import java.util.function.Function;
0035 import java.util.function.Supplier;
0036 
0037 import static java.util.Objects.requireNonNull;
0038 import static javafx.beans.binding.Bindings.createBooleanBinding;
0039 import static javafx.beans.binding.Bindings.createDoubleBinding;
0040 import static javafx.beans.binding.Bindings.createFloatBinding;
0041 import static javafx.beans.binding.Bindings.createIntegerBinding;
0042 import static javafx.beans.binding.Bindings.createLongBinding;
0043 import static javafx.beans.binding.Bindings.createObjectBinding;
0044 import static javafx.beans.binding.Bindings.createStringBinding;
0045 
0046 /**
0047  @author Andres Almiray
0048  @since 2.10.0
0049  */
0050 public final class ReducingBindings {
0051     private static final String ERROR_ITEMS_NULL = "Argument 'items' must not be null";
0052     private static final String ERROR_MAPPER_NULL = "Argument 'mapper' must not be null";
0053     private static final String ERROR_REDUCER_NULL = "Argument 'reducer' must not be null";
0054     private static final String ERROR_SUPPLIER_NULL = "Argument 'supplier' must not be null";
0055 
0056     private ReducingBindings() {
0057         // prevent instantiation
0058     }
0059 
0060     /**
0061      * Returns an object binding whose value is the reduction of all values in the map.
0062      *
0063      @param items        the observable map.
0064      @param defaultValue the value to be returned if there is no value present, may be null.
0065      @param reducer      an associative, non-interfering, stateless function for combining two values.
0066      *
0067      @return an object binding
0068      */
0069     @Nonnull
0070     public static <K, V> ObjectBinding<V> reduce(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer) {
0071         requireNonNull(items, ERROR_ITEMS_NULL);
0072         requireNonNull(reducer, ERROR_REDUCER_NULL);
0073         return createObjectBinding(() -> items.values().stream().reduce(reducer).orElse(defaultValue), items);
0074     }
0075 
0076     /**
0077      * Returns an object binding whose value is the reduction of all values in the map.
0078      *
0079      @param items    the observable map.
0080      @param supplier a {@code Supplier} whose result is returned if no value is present.
0081      @param reducer  an associative, non-interfering, stateless function for combining two values.
0082      *
0083      @return an object binding
0084      */
0085     @Nonnull
0086     public static <K, V> ObjectBinding<V> reduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer) {
0087         requireNonNull(items, ERROR_ITEMS_NULL);
0088         requireNonNull(reducer, ERROR_REDUCER_NULL);
0089         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0090         return createObjectBinding(() -> items.values().stream().reduce(reducer).orElseGet(supplier), items);
0091     }
0092 
0093     /**
0094      * Returns an object binding whose value is the reduction of all values in the map.
0095      *
0096      @param items        the observable map.
0097      @param defaultValue the value to be returned if there is no value present, may be null.
0098      @param reducer      an associative, non-interfering, stateless function for combining two values.
0099      *
0100      @return an object binding
0101      */
0102     @Nonnull
0103     public static <K, V> ObjectBinding<V> reduce(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer) {
0104         requireNonNull(reducer, ERROR_REDUCER_NULL);
0105         return createObjectBinding(() -> {
0106             BinaryOperator<V> operator = reducer.getValue();
0107             requireNonNull(operator, ERROR_REDUCER_NULL);
0108             return items.values().stream().reduce(operator).orElse(defaultValue);
0109         }, items, reducer);
0110     }
0111 
0112     /**
0113      * Returns an object binding whose value is the reduction of all values in the map.
0114      *
0115      @param items    the observable map.
0116      @param supplier a {@code Supplier} whose result is returned if no value is present.
0117      @param reducer  an associative, non-interfering, stateless function for combining two values.
0118      *
0119      @return an object binding
0120      */
0121     @Nonnull
0122     public static <K, V> ObjectBinding<V> reduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer) {
0123         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0124         requireNonNull(reducer, ERROR_REDUCER_NULL);
0125         return createObjectBinding(() -> {
0126             BinaryOperator<V> operator = reducer.getValue();
0127             requireNonNull(operator, ERROR_REDUCER_NULL);
0128             return items.values().stream().reduce(operator).orElseGet(supplier);
0129         }, items, reducer);
0130     }
0131 
0132     /**
0133      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0134      *
0135      @param items        the observable map.
0136      @param defaultValue the value to be returned if there is no value present, may be null.
0137      @param reducer      an associative, non-interfering, stateless function for combining two values.
0138      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0139      *
0140      @return a boolean binding
0141      */
0142     @Nonnull
0143     public static <K, V> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Boolean> mapper) {
0144         requireNonNull(items, ERROR_ITEMS_NULL);
0145         requireNonNull(reducer, ERROR_REDUCER_NULL);
0146         requireNonNull(mapper, ERROR_MAPPER_NULL);
0147         return createBooleanBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
0148     }
0149 
0150     /**
0151      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0152      *
0153      @param items    the observable map.
0154      @param supplier a {@code Supplier} whose result is returned if no value is present.
0155      @param reducer  an associative, non-interfering, stateless function for combining two values.
0156      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0157      *
0158      @return a boolean binding
0159      */
0160     @Nonnull
0161     public static <K, V> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Boolean> mapper) {
0162         requireNonNull(items, ERROR_ITEMS_NULL);
0163         requireNonNull(reducer, ERROR_REDUCER_NULL);
0164         requireNonNull(mapper, ERROR_MAPPER_NULL);
0165         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0166         return createBooleanBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
0167     }
0168 
0169     /**
0170      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0171      *
0172      @param items        the observable map.
0173      @param defaultValue the value to be returned if there is no value present, may be null.
0174      @param reducer      an associative, non-interfering, stateless function for combining two values.
0175      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0176      *
0177      @return a boolean binding
0178      */
0179     @Nonnull
0180     public static <K, V> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Boolean>> mapper) {
0181         requireNonNull(reducer, ERROR_REDUCER_NULL);
0182         requireNonNull(mapper, ERROR_MAPPER_NULL);
0183         return createBooleanBinding(() -> {
0184             BinaryOperator<V> operator = reducer.getValue();
0185             requireNonNull(operator, ERROR_REDUCER_NULL);
0186             Function<? super V, Boolean> mapperValue = mapper.getValue();
0187             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0188             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
0189         }, items, reducer, mapper);
0190     }
0191 
0192     /**
0193      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0194      *
0195      @param items    the observable map.
0196      @param reducer  an associative, non-interfering, stateless function for combining two values.
0197      @param supplier a {@code Supplier} whose result is returned if no value is present.
0198      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0199      *
0200      @return a boolean binding
0201      */
0202     @Nonnull
0203     public static <K, V> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Boolean>> mapper) {
0204         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0205         requireNonNull(mapper, ERROR_MAPPER_NULL);
0206         return createBooleanBinding(() -> {
0207             BinaryOperator<V> operator = reducer.getValue();
0208             requireNonNull(operator, ERROR_REDUCER_NULL);
0209             Function<? super V, Boolean> mapperValue = mapper.getValue();
0210             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0211             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
0212         }, items, reducer, mapper);
0213     }
0214 
0215     /**
0216      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0217      *
0218      @param items        the observable map.
0219      @param defaultValue the value to be returned if there is no value present, may be null.
0220      @param reducer      an associative, non-interfering, stateless function for combining two values.
0221      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0222      *
0223      @return an integer binding
0224      */
0225     @Nonnull
0226     public static <K, V> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Integer> mapper) {
0227         requireNonNull(items, ERROR_ITEMS_NULL);
0228         requireNonNull(reducer, ERROR_REDUCER_NULL);
0229         requireNonNull(mapper, ERROR_MAPPER_NULL);
0230         return createIntegerBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
0231     }
0232 
0233     /**
0234      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0235      *
0236      @param items    the observable map.
0237      @param supplier a {@code Supplier} whose result is returned if no value is present.
0238      @param reducer  an associative, non-interfering, stateless function for combining two values.
0239      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0240      *
0241      @return an integer binding
0242      */
0243     @Nonnull
0244     public static <K, V> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Integer> mapper) {
0245         requireNonNull(items, ERROR_ITEMS_NULL);
0246         requireNonNull(reducer, ERROR_REDUCER_NULL);
0247         requireNonNull(mapper, ERROR_MAPPER_NULL);
0248         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0249         return createIntegerBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
0250     }
0251 
0252     /**
0253      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0254      *
0255      @param items        the observable map.
0256      @param defaultValue the value to be returned if there is no value present, may be null.
0257      @param reducer      an associative, non-interfering, stateless function for combining two values.
0258      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0259      *
0260      @return an integer binding
0261      */
0262     @Nonnull
0263     public static <K, V> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Integer>> mapper) {
0264         requireNonNull(reducer, ERROR_REDUCER_NULL);
0265         requireNonNull(mapper, ERROR_MAPPER_NULL);
0266         return createIntegerBinding(() -> {
0267             BinaryOperator<V> operator = reducer.getValue();
0268             requireNonNull(operator, ERROR_REDUCER_NULL);
0269             Function<? super V, Integer> mapperValue = mapper.getValue();
0270             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0271             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
0272         }, items, reducer, mapper);
0273     }
0274 
0275     /**
0276      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0277      *
0278      @param items    the observable map.
0279      @param supplier a {@code Supplier} whose result is returned if no value is present.
0280      @param reducer  an associative, non-interfering, stateless function for combining two values.
0281      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0282      *
0283      @return an integer binding
0284      */
0285     @Nonnull
0286     public static <K, V> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Integer>> mapper) {
0287         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0288         requireNonNull(mapper, ERROR_MAPPER_NULL);
0289         return createIntegerBinding(() -> {
0290             BinaryOperator<V> operator = reducer.getValue();
0291             requireNonNull(operator, ERROR_REDUCER_NULL);
0292             Function<? super V, Integer> mapperValue = mapper.getValue();
0293             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0294             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
0295         }, items, reducer, mapper);
0296     }
0297 
0298     /**
0299      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0300      *
0301      @param items        the observable map.
0302      @param defaultValue the value to be returned if there is no value present, may be null.
0303      @param reducer      an associative, non-interfering, stateless function for combining two values.
0304      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0305      *
0306      @return a long binding
0307      */
0308     @Nonnull
0309     public static <K, V> LongBinding reduceThenMapToLong(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Long> mapper) {
0310         requireNonNull(items, ERROR_ITEMS_NULL);
0311         requireNonNull(reducer, ERROR_REDUCER_NULL);
0312         requireNonNull(mapper, ERROR_MAPPER_NULL);
0313         return createLongBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
0314     }
0315 
0316     /**
0317      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0318      *
0319      @param items    the observable map.
0320      @param supplier a {@code Supplier} whose result is returned if no value is present.
0321      @param reducer  an associative, non-interfering, stateless function for combining two values.
0322      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0323      *
0324      @return a long binding
0325      */
0326     @Nonnull
0327     public static <K, V> LongBinding reduceThenMapToLong(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Long> mapper) {
0328         requireNonNull(items, ERROR_ITEMS_NULL);
0329         requireNonNull(reducer, ERROR_REDUCER_NULL);
0330         requireNonNull(mapper, ERROR_MAPPER_NULL);
0331         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0332         return createLongBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
0333     }
0334 
0335     /**
0336      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0337      *
0338      @param items        the observable map.
0339      @param defaultValue the value to be returned if there is no value present, may be null.
0340      @param reducer      an associative, non-interfering, stateless function for combining two values.
0341      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0342      *
0343      @return a long binding
0344      */
0345     @Nonnull
0346     public static <K, V> LongBinding reduceThenMapToLong(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Long>> mapper) {
0347         requireNonNull(reducer, ERROR_REDUCER_NULL);
0348         requireNonNull(mapper, ERROR_MAPPER_NULL);
0349         return createLongBinding(() -> {
0350             BinaryOperator<V> operator = reducer.getValue();
0351             requireNonNull(operator, ERROR_REDUCER_NULL);
0352             Function<? super V, Long> mapperValue = mapper.getValue();
0353             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0354             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
0355         }, items, reducer, mapper);
0356     }
0357 
0358     /**
0359      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0360      *
0361      @param items    the observable map.
0362      @param supplier a {@code Supplier} whose result is returned if no value is present.
0363      @param reducer  an associative, non-interfering, stateless function for combining two values.
0364      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0365      *
0366      @return a long binding
0367      */
0368     @Nonnull
0369     public static <K, V> LongBinding reduceThenMapToLong(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Long>> mapper) {
0370         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0371         requireNonNull(mapper, ERROR_MAPPER_NULL);
0372         return createLongBinding(() -> {
0373             BinaryOperator<V> operator = reducer.getValue();
0374             requireNonNull(operator, ERROR_REDUCER_NULL);
0375             Function<? super V, Long> mapperValue = mapper.getValue();
0376             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0377             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
0378         }, items, reducer, mapper);
0379     }
0380 
0381     /**
0382      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0383      *
0384      @param items        the observable map.
0385      @param defaultValue the value to be returned if there is no value present, may be null.
0386      @param reducer      an associative, non-interfering, stateless function for combining two values.
0387      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0388      *
0389      @return a float binding
0390      */
0391     @Nonnull
0392     public static <K, V> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Float> mapper) {
0393         requireNonNull(items, ERROR_ITEMS_NULL);
0394         requireNonNull(reducer, ERROR_REDUCER_NULL);
0395         requireNonNull(mapper, ERROR_MAPPER_NULL);
0396         return createFloatBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
0397     }
0398 
0399     /**
0400      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0401      *
0402      @param items    the observable map.
0403      @param supplier a {@code Supplier} whose result is returned if no value is present.
0404      @param reducer  an associative, non-interfering, stateless function for combining two values.
0405      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0406      *
0407      @return a float binding
0408      */
0409     @Nonnull
0410     public static <K, V> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Float> mapper) {
0411         requireNonNull(items, ERROR_ITEMS_NULL);
0412         requireNonNull(reducer, ERROR_REDUCER_NULL);
0413         requireNonNull(mapper, ERROR_MAPPER_NULL);
0414         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0415         return createFloatBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
0416     }
0417 
0418     /**
0419      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0420      *
0421      @param items        the observable map.
0422      @param defaultValue the value to be returned if there is no value present, may be null.
0423      @param reducer      an associative, non-interfering, stateless function for combining two values.
0424      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0425      *
0426      @return a float binding
0427      */
0428     @Nonnull
0429     public static <K, V> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Float>> mapper) {
0430         requireNonNull(reducer, ERROR_REDUCER_NULL);
0431         requireNonNull(mapper, ERROR_MAPPER_NULL);
0432         return createFloatBinding(() -> {
0433             BinaryOperator<V> operator = reducer.getValue();
0434             requireNonNull(operator, ERROR_REDUCER_NULL);
0435             Function<? super V, Float> mapperValue = mapper.getValue();
0436             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0437             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
0438         }, items, reducer, mapper);
0439     }
0440 
0441     /**
0442      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0443      *
0444      @param items    the observable map.
0445      @param supplier a {@code Supplier} whose result is returned if no value is present.
0446      @param reducer  an associative, non-interfering, stateless function for combining two values.
0447      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0448      *
0449      @return a float binding
0450      */
0451     @Nonnull
0452     public static <K, V> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Float>> mapper) {
0453         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0454         requireNonNull(mapper, ERROR_MAPPER_NULL);
0455         return createFloatBinding(() -> {
0456             BinaryOperator<V> operator = reducer.getValue();
0457             requireNonNull(operator, ERROR_REDUCER_NULL);
0458             Function<? super V, Float> mapperValue = mapper.getValue();
0459             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0460             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
0461         }, items, reducer, mapper);
0462     }
0463 
0464     /**
0465      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0466      *
0467      @param items        the observable map.
0468      @param defaultValue the value to be returned if there is no value present, may be null.
0469      @param reducer      an associative, non-interfering, stateless function for combining two values.
0470      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0471      *
0472      @return a double binding
0473      */
0474     @Nonnull
0475     public static <K, V> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Double> mapper) {
0476         requireNonNull(items, ERROR_ITEMS_NULL);
0477         requireNonNull(reducer, ERROR_REDUCER_NULL);
0478         requireNonNull(mapper, ERROR_MAPPER_NULL);
0479         return createDoubleBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
0480     }
0481 
0482     /**
0483      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0484      *
0485      @param items    the observable map.
0486      @param supplier a {@code Supplier} whose result is returned if no value is present.
0487      @param reducer  an associative, non-interfering, stateless function for combining two values.
0488      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0489      *
0490      @return a double binding
0491      */
0492     @Nonnull
0493     public static <K, V> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, Double> mapper) {
0494         requireNonNull(items, ERROR_ITEMS_NULL);
0495         requireNonNull(reducer, ERROR_REDUCER_NULL);
0496         requireNonNull(mapper, ERROR_MAPPER_NULL);
0497         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0498         return createDoubleBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
0499     }
0500 
0501     /**
0502      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0503      *
0504      @param items        the observable map.
0505      @param defaultValue the value to be returned if there is no value present, may be null.
0506      @param reducer      an associative, non-interfering, stateless function for combining two values.
0507      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0508      *
0509      @return a double binding
0510      */
0511     @Nonnull
0512     public static <K, V> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Double>> mapper) {
0513         requireNonNull(reducer, ERROR_REDUCER_NULL);
0514         requireNonNull(mapper, ERROR_MAPPER_NULL);
0515         return createDoubleBinding(() -> {
0516             BinaryOperator<V> operator = reducer.getValue();
0517             requireNonNull(operator, ERROR_REDUCER_NULL);
0518             Function<? super V, Double> mapperValue = mapper.getValue();
0519             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0520             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
0521         }, items, reducer, mapper);
0522     }
0523 
0524     /**
0525      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0526      *
0527      @param items    the observable map.
0528      @param supplier a {@code Supplier} whose result is returned if no value is present.
0529      @param reducer  an associative, non-interfering, stateless function for combining two values.
0530      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0531      *
0532      @return a double binding
0533      */
0534     @Nonnull
0535     public static <K, V> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, Double>> mapper) {
0536         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0537         requireNonNull(mapper, ERROR_MAPPER_NULL);
0538         return createDoubleBinding(() -> {
0539             BinaryOperator<V> operator = reducer.getValue();
0540             requireNonNull(operator, ERROR_REDUCER_NULL);
0541             Function<? super V, Double> mapperValue = mapper.getValue();
0542             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0543             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
0544         }, items, reducer, mapper);
0545     }
0546 
0547     /**
0548      * Returns a String binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0549      *
0550      @param items        the observable map.
0551      @param defaultValue the value to be returned if there is no value present, may be null.
0552      @param reducer      an associative, non-interfering, stateless function for combining two values.
0553      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0554      *
0555      @return a String binding
0556      */
0557     @Nonnull
0558     public static <K, V> StringBinding reduceThenMapToString(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, String> mapper) {
0559         requireNonNull(items, ERROR_ITEMS_NULL);
0560         requireNonNull(reducer, ERROR_REDUCER_NULL);
0561         requireNonNull(mapper, ERROR_MAPPER_NULL);
0562         return createStringBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
0563     }
0564 
0565     /**
0566      * Returns a String binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0567      *
0568      @param items    the observable map.
0569      @param supplier a {@code Supplier} whose result is returned if no value is present.
0570      @param reducer  an associative, non-interfering, stateless function for combining two values.
0571      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0572      *
0573      @return a String binding
0574      */
0575     @Nonnull
0576     public static <K, V> StringBinding reduceThenMapToString(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, String> mapper) {
0577         requireNonNull(items, ERROR_ITEMS_NULL);
0578         requireNonNull(reducer, ERROR_REDUCER_NULL);
0579         requireNonNull(mapper, ERROR_MAPPER_NULL);
0580         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0581         return createStringBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
0582     }
0583 
0584     /**
0585      * Returns a String binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0586      *
0587      @param items        the observable map.
0588      @param defaultValue the value to be returned if there is no value present, may be null.
0589      @param reducer      an associative, non-interfering, stateless function for combining two values.
0590      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0591      *
0592      @return a String binding
0593      */
0594     @Nonnull
0595     public static <K, V> StringBinding reduceThenMapToString(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, String>> mapper) {
0596         requireNonNull(reducer, ERROR_REDUCER_NULL);
0597         requireNonNull(mapper, ERROR_MAPPER_NULL);
0598         return createStringBinding(() -> {
0599             BinaryOperator<V> operator = reducer.getValue();
0600             requireNonNull(operator, ERROR_REDUCER_NULL);
0601             Function<? super V, String> mapperValue = mapper.getValue();
0602             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0603             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
0604         }, items, reducer, mapper);
0605     }
0606 
0607     /**
0608      * Returns a String binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
0609      *
0610      @param items    the observable map.
0611      @param supplier a {@code Supplier} whose result is returned if no value is present.
0612      @param reducer  an associative, non-interfering, stateless function for combining two values.
0613      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0614      *
0615      @return a String binding
0616      */
0617     @Nonnull
0618     public static <K, V> StringBinding reduceThenMapToString(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, String>> mapper) {
0619         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0620         requireNonNull(mapper, ERROR_MAPPER_NULL);
0621         return createStringBinding(() -> {
0622             BinaryOperator<V> operator = reducer.getValue();
0623             requireNonNull(operator, ERROR_REDUCER_NULL);
0624             Function<? super V, String> mapperValue = mapper.getValue();
0625             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0626             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
0627         }, items, reducer, mapper);
0628     }
0629 
0630     /**
0631      * Returns an object binding whose value is the reduction of all elements in the list.
0632      *
0633      @param items        the observable list of elements.
0634      @param defaultValue the value to be returned if there is no value present, may be null.
0635      @param reducer      an associative, non-interfering, stateless function for combining two values.
0636      *
0637      @return an object binding
0638      */
0639     @Nonnull
0640     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer) {
0641         requireNonNull(items, ERROR_ITEMS_NULL);
0642         requireNonNull(reducer, ERROR_REDUCER_NULL);
0643         return createObjectBinding(() -> items.stream().reduce(reducer).orElse(defaultValue), items);
0644     }
0645 
0646     /**
0647      * Returns an object binding whose value is the reduction of all elements in the list.
0648      *
0649      @param items    the observable list of elements.
0650      @param reducer  an associative, non-interfering, stateless function for combining two values.
0651      @param supplier a {@code Supplier} whose result is returned if no value is present.
0652      *
0653      @return an object binding
0654      */
0655     @Nonnull
0656     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer) {
0657         requireNonNull(items, ERROR_ITEMS_NULL);
0658         requireNonNull(reducer, ERROR_REDUCER_NULL);
0659         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0660         return createObjectBinding(() -> items.stream().reduce(reducer).orElseGet(supplier), items);
0661     }
0662 
0663     /**
0664      * Returns an object binding whose value is the reduction of all elements in the list.
0665      *
0666      @param items        the observable list of elements.
0667      @param defaultValue the value to be returned if there is no value present, may be null.
0668      @param reducer      an associative, non-interfering, stateless function for combining two values.
0669      *
0670      @return an object binding
0671      */
0672     @Nonnull
0673     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer) {
0674         requireNonNull(reducer, ERROR_REDUCER_NULL);
0675         return createObjectBinding(() -> {
0676             BinaryOperator<T> operator = reducer.getValue();
0677             requireNonNull(operator, ERROR_REDUCER_NULL);
0678             return items.stream().reduce(operator).orElse(defaultValue);
0679         }, items, reducer);
0680     }
0681 
0682     /**
0683      * Returns an object binding whose value is the reduction of all elements in the list.
0684      *
0685      @param items    the observable list of elements.
0686      @param reducer  an associative, non-interfering, stateless function for combining two values.
0687      @param supplier a {@code Supplier} whose result is returned if no value is present.
0688      *
0689      @return an object binding
0690      */
0691     @Nonnull
0692     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer) {
0693         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0694         requireNonNull(reducer, ERROR_REDUCER_NULL);
0695         return createObjectBinding(() -> {
0696             BinaryOperator<T> operator = reducer.getValue();
0697             requireNonNull(operator, ERROR_REDUCER_NULL);
0698             return items.stream().reduce(operator).orElseGet(supplier);
0699         }, items, reducer);
0700     }
0701 
0702     /**
0703      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0704      *
0705      @param items        the observable list of elements.
0706      @param defaultValue the value to be returned if there is no value present, may be null.
0707      @param reducer      an associative, non-interfering, stateless function for combining two values.
0708      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0709      *
0710      @return a string binding
0711      */
0712     @Nonnull
0713     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, String> mapper) {
0714         requireNonNull(items, ERROR_ITEMS_NULL);
0715         requireNonNull(reducer, ERROR_REDUCER_NULL);
0716         final Function<? super T, String> mapperValue = mapper != null ? mapper : String::valueOf;
0717         return createStringBinding(() -> mapperValue.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
0718     }
0719 
0720     /**
0721      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0722      *
0723      @param items    the observable list of elements.
0724      @param supplier a {@code Supplier} whose result is returned if no value is present.
0725      @param reducer  an associative, non-interfering, stateless function for combining two values.
0726      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0727      *
0728      @return a string binding
0729      */
0730     @Nonnull
0731     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, String> mapper) {
0732         requireNonNull(items, ERROR_ITEMS_NULL);
0733         requireNonNull(reducer, ERROR_REDUCER_NULL);
0734         final Function<? super T, String> mapperValue = mapper != null ? mapper : String::valueOf;
0735         return createStringBinding(() -> mapperValue.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
0736     }
0737 
0738     /**
0739      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0740      *
0741      @param items        the observable list of elements.
0742      @param defaultValue the value to be returned if there is no value present, may be null.
0743      @param reducer      an associative, non-interfering, stateless function for combining two values.
0744      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0745      *
0746      @return a string binding
0747      */
0748     @Nonnull
0749     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, String>> mapper) {
0750         requireNonNull(items, ERROR_ITEMS_NULL);
0751         requireNonNull(reducer, ERROR_REDUCER_NULL);
0752         requireNonNull(mapper, ERROR_MAPPER_NULL);
0753         return createStringBinding(() -> {
0754             BinaryOperator<T> operator = reducer.getValue();
0755             requireNonNull(operator, ERROR_REDUCER_NULL);
0756             final Function<? super T, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : String::valueOf;
0757             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
0758         }, items, reducer, mapper);
0759     }
0760 
0761     /**
0762      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0763      *
0764      @param items    the observable list of elements.
0765      @param supplier a {@code Supplier} whose result is returned if no value is present.
0766      @param reducer  an associative, non-interfering, stateless function for combining two values.
0767      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0768      *
0769      @return a string binding
0770      */
0771     @Nonnull
0772     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, String>> mapper) {
0773         requireNonNull(items, ERROR_ITEMS_NULL);
0774         requireNonNull(reducer, ERROR_REDUCER_NULL);
0775         requireNonNull(mapper, ERROR_MAPPER_NULL);
0776         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0777         return createStringBinding(() -> {
0778             BinaryOperator<T> operator = reducer.getValue();
0779             requireNonNull(operator, ERROR_REDUCER_NULL);
0780             final Function<? super T, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : String::valueOf;
0781             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
0782         }, items, reducer, mapper);
0783     }
0784 
0785     /**
0786      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0787      *
0788      @param items        the observable list of elements.
0789      @param defaultValue the value to be returned if there is no value present, may be null.
0790      @param reducer      an associative, non-interfering, stateless function for combining two values.
0791      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0792      *
0793      @return an integer binding
0794      */
0795     @Nonnull
0796     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Integer> mapper) {
0797         requireNonNull(items, ERROR_ITEMS_NULL);
0798         requireNonNull(reducer, ERROR_REDUCER_NULL);
0799         requireNonNull(mapper, ERROR_MAPPER_NULL);
0800         return createIntegerBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
0801     }
0802 
0803     /**
0804      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0805      *
0806      @param items    the observable list of elements.
0807      @param supplier a {@code Supplier} whose result is returned if no value is present.
0808      @param reducer  an associative, non-interfering, stateless function for combining two values.
0809      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0810      *
0811      @return an integer binding
0812      */
0813     @Nonnull
0814     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Integer> mapper) {
0815         requireNonNull(items, ERROR_ITEMS_NULL);
0816         requireNonNull(reducer, ERROR_REDUCER_NULL);
0817         requireNonNull(mapper, ERROR_MAPPER_NULL);
0818         return createIntegerBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
0819     }
0820 
0821     /**
0822      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0823      *
0824      @param items        the observable list of elements.
0825      @param defaultValue the value to be returned if there is no value present, may be null.
0826      @param reducer      an associative, non-interfering, stateless function for combining two values.
0827      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0828      *
0829      @return an integer binding
0830      */
0831     @Nonnull
0832     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper) {
0833         requireNonNull(items, ERROR_ITEMS_NULL);
0834         requireNonNull(reducer, ERROR_REDUCER_NULL);
0835         requireNonNull(mapper, ERROR_MAPPER_NULL);
0836         return createIntegerBinding(() -> {
0837             BinaryOperator<T> operator = reducer.getValue();
0838             requireNonNull(operator, ERROR_REDUCER_NULL);
0839             final Function<? super T, Integer> mapperValue = mapper.getValue();
0840             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0841             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
0842         }, items, reducer, mapper);
0843     }
0844 
0845     /**
0846      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0847      *
0848      @param items    the observable list of elements.
0849      @param supplier a {@code Supplier} whose result is returned if no value is present.
0850      @param reducer  an associative, non-interfering, stateless function for combining two values.
0851      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0852      *
0853      @return an integer binding
0854      */
0855     @Nonnull
0856     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper) {
0857         requireNonNull(items, ERROR_ITEMS_NULL);
0858         requireNonNull(reducer, ERROR_REDUCER_NULL);
0859         requireNonNull(mapper, ERROR_MAPPER_NULL);
0860         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0861         return createIntegerBinding(() -> {
0862             BinaryOperator<T> operator = reducer.getValue();
0863             requireNonNull(operator, ERROR_REDUCER_NULL);
0864             final Function<? super T, Integer> mapperValue = mapper.getValue();
0865             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0866             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
0867         }, items, reducer, mapper);
0868     }
0869 
0870     /**
0871      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0872      *
0873      @param items        the observable list of elements.
0874      @param defaultValue the value to be returned if there is no value present, may be null.
0875      @param reducer      an associative, non-interfering, stateless function for combining two values.
0876      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0877      *
0878      @return a long binding
0879      */
0880     @Nonnull
0881     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Long> mapper) {
0882         requireNonNull(items, ERROR_ITEMS_NULL);
0883         requireNonNull(reducer, ERROR_REDUCER_NULL);
0884         requireNonNull(mapper, ERROR_MAPPER_NULL);
0885         return createLongBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
0886     }
0887 
0888     /**
0889      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0890      *
0891      @param items    the observable list of elements.
0892      @param supplier a {@code Supplier} whose result is returned if no value is present.
0893      @param reducer  an associative, non-interfering, stateless function for combining two values.
0894      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0895      *
0896      @return a long binding
0897      */
0898     @Nonnull
0899     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Long> mapper) {
0900         requireNonNull(items, ERROR_ITEMS_NULL);
0901         requireNonNull(reducer, ERROR_REDUCER_NULL);
0902         requireNonNull(mapper, ERROR_MAPPER_NULL);
0903         return createLongBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
0904     }
0905 
0906     /**
0907      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0908      *
0909      @param items        the observable list of elements.
0910      @param defaultValue the value to be returned if there is no value present, may be null.
0911      @param reducer      an associative, non-interfering, stateless function for combining two values.
0912      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0913      *
0914      @return a long binding
0915      */
0916     @Nonnull
0917     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Long>> mapper) {
0918         requireNonNull(items, ERROR_ITEMS_NULL);
0919         requireNonNull(reducer, ERROR_REDUCER_NULL);
0920         requireNonNull(mapper, ERROR_MAPPER_NULL);
0921         return createLongBinding(() -> {
0922             BinaryOperator<T> operator = reducer.getValue();
0923             requireNonNull(operator, ERROR_REDUCER_NULL);
0924             final Function<? super T, Long> mapperValue = mapper.getValue();
0925             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0926             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
0927         }, items, reducer, mapper);
0928     }
0929 
0930     /**
0931      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0932      *
0933      @param items    the observable list of elements.
0934      @param supplier a {@code Supplier} whose result is returned if no value is present.
0935      @param reducer  an associative, non-interfering, stateless function for combining two values.
0936      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0937      *
0938      @return a long binding
0939      */
0940     @Nonnull
0941     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Long>> mapper) {
0942         requireNonNull(items, ERROR_ITEMS_NULL);
0943         requireNonNull(reducer, ERROR_REDUCER_NULL);
0944         requireNonNull(mapper, ERROR_MAPPER_NULL);
0945         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
0946         return createLongBinding(() -> {
0947             BinaryOperator<T> operator = reducer.getValue();
0948             requireNonNull(operator, ERROR_REDUCER_NULL);
0949             final Function<? super T, Long> mapperValue = mapper.getValue();
0950             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
0951             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
0952         }, items, reducer, mapper);
0953     }
0954 
0955     /**
0956      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0957      *
0958      @param items        the observable list of elements.
0959      @param defaultValue the value to be returned if there is no value present, may be null.
0960      @param reducer      an associative, non-interfering, stateless function for combining two values.
0961      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0962      *
0963      @return a float binding
0964      */
0965     @Nonnull
0966     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Float> mapper) {
0967         requireNonNull(items, ERROR_ITEMS_NULL);
0968         requireNonNull(reducer, ERROR_REDUCER_NULL);
0969         requireNonNull(mapper, ERROR_MAPPER_NULL);
0970         return createFloatBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
0971     }
0972 
0973     /**
0974      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0975      *
0976      @param items    the observable list of elements.
0977      @param supplier a {@code Supplier} whose result is returned if no value is present.
0978      @param reducer  an associative, non-interfering, stateless function for combining two values.
0979      @param mapper   a non-interfering, stateless function to apply to the reduced value.
0980      *
0981      @return a float binding
0982      */
0983     @Nonnull
0984     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Float> mapper) {
0985         requireNonNull(items, ERROR_ITEMS_NULL);
0986         requireNonNull(reducer, ERROR_REDUCER_NULL);
0987         requireNonNull(mapper, ERROR_MAPPER_NULL);
0988         return createFloatBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
0989     }
0990 
0991     /**
0992      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
0993      *
0994      @param items        the observable list of elements.
0995      @param defaultValue the value to be returned if there is no value present, may be null.
0996      @param reducer      an associative, non-interfering, stateless function for combining two values.
0997      @param mapper       a non-interfering, stateless function to apply to the reduced value.
0998      *
0999      @return a float binding
1000      */
1001     @Nonnull
1002     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Float>> mapper) {
1003         requireNonNull(items, ERROR_ITEMS_NULL);
1004         requireNonNull(reducer, ERROR_REDUCER_NULL);
1005         requireNonNull(mapper, ERROR_MAPPER_NULL);
1006         return createFloatBinding(() -> {
1007             BinaryOperator<T> operator = reducer.getValue();
1008             requireNonNull(operator, ERROR_REDUCER_NULL);
1009             final Function<? super T, Float> mapperValue = mapper.getValue();
1010             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1011             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1012         }, items, reducer, mapper);
1013     }
1014 
1015     /**
1016      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1017      *
1018      @param items    the observable list of elements.
1019      @param supplier a {@code Supplier} whose result is returned if no value is present.
1020      @param reducer  an associative, non-interfering, stateless function for combining two values.
1021      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1022      *
1023      @return a float binding
1024      */
1025     @Nonnull
1026     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Float>> mapper) {
1027         requireNonNull(items, ERROR_ITEMS_NULL);
1028         requireNonNull(reducer, ERROR_REDUCER_NULL);
1029         requireNonNull(mapper, ERROR_MAPPER_NULL);
1030         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1031         return createFloatBinding(() -> {
1032             BinaryOperator<T> operator = reducer.getValue();
1033             requireNonNull(operator, ERROR_REDUCER_NULL);
1034             final Function<? super T, Float> mapperValue = mapper.getValue();
1035             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1036             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1037         }, items, reducer, mapper);
1038     }
1039 
1040     /**
1041      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1042      *
1043      @param items        the observable list of elements.
1044      @param defaultValue the value to be returned if there is no value present, may be null.
1045      @param reducer      an associative, non-interfering, stateless function for combining two values.
1046      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1047      *
1048      @return a double binding
1049      */
1050     @Nonnull
1051     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Double> mapper) {
1052         requireNonNull(items, ERROR_ITEMS_NULL);
1053         requireNonNull(reducer, ERROR_REDUCER_NULL);
1054         requireNonNull(mapper, ERROR_MAPPER_NULL);
1055         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1056     }
1057 
1058     /**
1059      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1060      *
1061      @param items    the observable list of elements.
1062      @param supplier a {@code Supplier} whose result is returned if no value is present.
1063      @param reducer  an associative, non-interfering, stateless function for combining two values.
1064      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1065      *
1066      @return a double binding
1067      */
1068     @Nonnull
1069     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Double> mapper) {
1070         requireNonNull(items, ERROR_ITEMS_NULL);
1071         requireNonNull(reducer, ERROR_REDUCER_NULL);
1072         requireNonNull(mapper, ERROR_MAPPER_NULL);
1073         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1074     }
1075 
1076     /**
1077      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1078      *
1079      @param items        the observable list of elements.
1080      @param defaultValue the value to be returned if there is no value present, may be null.
1081      @param reducer      an associative, non-interfering, stateless function for combining two values.
1082      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1083      *
1084      @return a double binding
1085      */
1086     @Nonnull
1087     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Double>> mapper) {
1088         requireNonNull(items, ERROR_ITEMS_NULL);
1089         requireNonNull(reducer, ERROR_REDUCER_NULL);
1090         requireNonNull(mapper, ERROR_MAPPER_NULL);
1091         return createDoubleBinding(() -> {
1092             BinaryOperator<T> operator = reducer.getValue();
1093             requireNonNull(operator, ERROR_REDUCER_NULL);
1094             final Function<? super T, Double> mapperValue = mapper.getValue();
1095             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1096             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1097         }, items, reducer, mapper);
1098     }
1099 
1100     /**
1101      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1102      *
1103      @param items    the observable list of elements.
1104      @param supplier a {@code Supplier} whose result is returned if no value is present.
1105      @param reducer  an associative, non-interfering, stateless function for combining two values.
1106      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1107      *
1108      @return a double binding
1109      */
1110     @Nonnull
1111     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Double>> mapper) {
1112         requireNonNull(items, ERROR_ITEMS_NULL);
1113         requireNonNull(reducer, ERROR_REDUCER_NULL);
1114         requireNonNull(mapper, ERROR_MAPPER_NULL);
1115         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1116         return createDoubleBinding(() -> {
1117             BinaryOperator<T> operator = reducer.getValue();
1118             requireNonNull(operator, ERROR_REDUCER_NULL);
1119             final Function<? super T, Double> mapperValue = mapper.getValue();
1120             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1121             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1122         }, items, reducer, mapper);
1123     }
1124 
1125     /**
1126      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1127      *
1128      @param items        the observable list of elements.
1129      @param defaultValue the value to be returned if there is no value present, may be null.
1130      @param reducer      an associative, non-interfering, stateless function for combining two values.
1131      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1132      *
1133      @return a boolean binding
1134      */
1135     @Nonnull
1136     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Boolean> mapper) {
1137         requireNonNull(items, ERROR_ITEMS_NULL);
1138         requireNonNull(reducer, ERROR_REDUCER_NULL);
1139         requireNonNull(mapper, ERROR_MAPPER_NULL);
1140         return createBooleanBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1141     }
1142 
1143     /**
1144      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1145      *
1146      @param items    the observable list of elements.
1147      @param supplier a {@code Supplier} whose result is returned if no value is present.
1148      @param reducer  an associative, non-interfering, stateless function for combining two values.
1149      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1150      *
1151      @return a boolean binding
1152      */
1153     @Nonnull
1154     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Boolean> mapper) {
1155         requireNonNull(items, ERROR_ITEMS_NULL);
1156         requireNonNull(reducer, ERROR_REDUCER_NULL);
1157         requireNonNull(mapper, ERROR_MAPPER_NULL);
1158         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1159         return createBooleanBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1160     }
1161 
1162     /**
1163      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1164      *
1165      @param items        the observable list of elements.
1166      @param defaultValue the value to be returned if there is no value present, may be null.
1167      @param reducer      an associative, non-interfering, stateless function for combining two values.
1168      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1169      *
1170      @return a boolean binding
1171      */
1172     @Nonnull
1173     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper) {
1174         requireNonNull(items, ERROR_ITEMS_NULL);
1175         requireNonNull(reducer, ERROR_REDUCER_NULL);
1176         requireNonNull(mapper, ERROR_MAPPER_NULL);
1177         return createBooleanBinding(() -> {
1178             BinaryOperator<T> operator = reducer.getValue();
1179             requireNonNull(operator, ERROR_REDUCER_NULL);
1180             final Function<? super T, Boolean> mapperValue = mapper.getValue();
1181             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1182             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1183         }, items, reducer, mapper);
1184     }
1185 
1186     /**
1187      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1188      *
1189      @param items    the observable list of elements.
1190      @param supplier a {@code Supplier} whose result is returned if no value is present.
1191      @param reducer  an associative, non-interfering, stateless function for combining two values.
1192      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1193      *
1194      @return a boolean binding
1195      */
1196     @Nonnull
1197     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper) {
1198         requireNonNull(items, ERROR_ITEMS_NULL);
1199         requireNonNull(reducer, ERROR_REDUCER_NULL);
1200         requireNonNull(mapper, ERROR_MAPPER_NULL);
1201         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1202         return createBooleanBinding(() -> {
1203             BinaryOperator<T> operator = reducer.getValue();
1204             requireNonNull(operator, ERROR_REDUCER_NULL);
1205             final Function<? super T, Boolean> mapperValue = mapper.getValue();
1206             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1207             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1208         }, items, reducer, mapper);
1209     }
1210 
1211     /**
1212      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1213      *
1214      @param items        the observable list of elements.
1215      @param defaultValue the value to be returned if there is no value present, may be null.
1216      @param reducer      an associative, non-interfering, stateless function for combining two values.
1217      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1218      *
1219      @return a number binding
1220      */
1221     @Nonnull
1222     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, ? extends Number> mapper) {
1223         requireNonNull(items, ERROR_ITEMS_NULL);
1224         requireNonNull(reducer, ERROR_REDUCER_NULL);
1225         requireNonNull(mapper, ERROR_MAPPER_NULL);
1226         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)).doubleValue(), items);
1227     }
1228 
1229     /**
1230      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1231      *
1232      @param items    the observable list of elements.
1233      @param supplier a {@code Supplier} whose result is returned if no value is present.
1234      @param reducer  an associative, non-interfering, stateless function for combining two values.
1235      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1236      *
1237      @return a number binding
1238      */
1239     @Nonnull
1240     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Number> mapper) {
1241         requireNonNull(items, ERROR_ITEMS_NULL);
1242         requireNonNull(reducer, ERROR_REDUCER_NULL);
1243         requireNonNull(mapper, ERROR_MAPPER_NULL);
1244         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1245         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)).doubleValue(), items);
1246     }
1247 
1248     /**
1249      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1250      *
1251      @param items        the observable list of elements.
1252      @param defaultValue the value to be returned if there is no value present, may be null.
1253      @param reducer      an associative, non-interfering, stateless function for combining two values.
1254      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1255      *
1256      @return a number binding
1257      */
1258     @Nonnull
1259     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, ? extends Number>> mapper) {
1260         requireNonNull(items, ERROR_ITEMS_NULL);
1261         requireNonNull(reducer, ERROR_REDUCER_NULL);
1262         requireNonNull(mapper, ERROR_MAPPER_NULL);
1263         return createDoubleBinding(() -> {
1264             BinaryOperator<T> operator = reducer.getValue();
1265             requireNonNull(operator, ERROR_REDUCER_NULL);
1266             final Function<? super T, ? extends Number> mapperValue = mapper.getValue();
1267             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1268             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue)).doubleValue();
1269         }, items, reducer, mapper);
1270     }
1271 
1272     /**
1273      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1274      *
1275      @param items    the observable list of elements.
1276      @param supplier a {@code Supplier} whose result is returned if no value is present.
1277      @param reducer  an associative, non-interfering, stateless function for combining two values.
1278      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1279      *
1280      @return a number binding
1281      */
1282     @Nonnull
1283     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Number>> mapper) {
1284         requireNonNull(items, ERROR_ITEMS_NULL);
1285         requireNonNull(reducer, ERROR_REDUCER_NULL);
1286         requireNonNull(mapper, ERROR_MAPPER_NULL);
1287         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1288         return createDoubleBinding(() -> {
1289             BinaryOperator<T> operator = reducer.getValue();
1290             requireNonNull(operator, ERROR_REDUCER_NULL);
1291             final Function<? super T, ? extends Number> mapperValue = mapper.getValue();
1292             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1293             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier)).doubleValue();
1294         }, items, reducer, mapper);
1295     }
1296 
1297     /**
1298      * Returns an object binding whose value is the reduction of all elements in the set.
1299      *
1300      @param items        the observable set of elements.
1301      @param defaultValue the value to be returned if there is no value present, may be null.
1302      @param reducer      an associative, non-interfering, stateless function for combining two values.
1303      *
1304      @return an object binding
1305      */
1306     @Nonnull
1307     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer) {
1308         requireNonNull(items, ERROR_ITEMS_NULL);
1309         requireNonNull(reducer, ERROR_REDUCER_NULL);
1310         return createObjectBinding(() -> items.stream().reduce(reducer).orElse(defaultValue), items);
1311     }
1312 
1313     /**
1314      * Returns an object binding whose value is the reduction of all elements in the set.
1315      *
1316      @param items    the observable set of elements.
1317      @param reducer  an associative, non-interfering, stateless function for combining two values.
1318      @param supplier a {@code Supplier} whose result is returned if no value is present.
1319      *
1320      @return an object binding
1321      */
1322     @Nonnull
1323     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer) {
1324         requireNonNull(items, ERROR_ITEMS_NULL);
1325         requireNonNull(reducer, ERROR_REDUCER_NULL);
1326         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1327         return createObjectBinding(() -> items.stream().reduce(reducer).orElseGet(supplier), items);
1328     }
1329 
1330     /**
1331      * Returns an object binding whose value is the reduction of all elements in the set.
1332      *
1333      @param items        the observable set of elements.
1334      @param defaultValue the value to be returned if there is no value present, may be null.
1335      @param reducer      an associative, non-interfering, stateless function for combining two values.
1336      *
1337      @return an object binding
1338      */
1339     @Nonnull
1340     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer) {
1341         requireNonNull(reducer, ERROR_REDUCER_NULL);
1342         return createObjectBinding(() -> {
1343             BinaryOperator<T> operator = reducer.getValue();
1344             requireNonNull(operator, ERROR_REDUCER_NULL);
1345             return items.stream().reduce(operator).orElse(defaultValue);
1346         }, items, reducer);
1347     }
1348 
1349     /**
1350      * Returns an object binding whose value is the reduction of all elements in the set.
1351      *
1352      @param items    the observable set of elements.
1353      @param reducer  an associative, non-interfering, stateless function for combining two values.
1354      @param supplier a {@code Supplier} whose result is returned if no value is present.
1355      *
1356      @return an object binding
1357      */
1358     @Nonnull
1359     public static <T> ObjectBinding<T> reduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer) {
1360         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1361         requireNonNull(reducer, ERROR_REDUCER_NULL);
1362         return createObjectBinding(() -> {
1363             BinaryOperator<T> operator = reducer.getValue();
1364             requireNonNull(operator, ERROR_REDUCER_NULL);
1365             return items.stream().reduce(operator).orElseGet(supplier);
1366         }, items, reducer);
1367     }
1368 
1369     /**
1370      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1371      *
1372      @param items        the observable set of elements.
1373      @param defaultValue the value to be returned if there is no value present, may be null.
1374      @param reducer      an associative, non-interfering, stateless function for combining two values.
1375      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1376      *
1377      @return a string binding
1378      */
1379     @Nonnull
1380     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, String> mapper) {
1381         requireNonNull(items, ERROR_ITEMS_NULL);
1382         requireNonNull(reducer, ERROR_REDUCER_NULL);
1383         final Function<? super T, String> mapperValue = mapper != null ? mapper : String::valueOf;
1384         return createStringBinding(() -> mapperValue.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1385     }
1386 
1387     /**
1388      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1389      *
1390      @param items    the observable set of elements.
1391      @param supplier a {@code Supplier} whose result is returned if no value is present.
1392      @param reducer  an associative, non-interfering, stateless function for combining two values.
1393      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1394      *
1395      @return a string binding
1396      */
1397     @Nonnull
1398     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, String> mapper) {
1399         requireNonNull(items, ERROR_ITEMS_NULL);
1400         requireNonNull(reducer, ERROR_REDUCER_NULL);
1401         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1402         final Function<? super T, String> mapperValue = mapper != null ? mapper : String::valueOf;
1403         return createStringBinding(() -> mapperValue.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1404     }
1405 
1406     /**
1407      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1408      *
1409      @param items        the observable set of elements.
1410      @param defaultValue the value to be returned if there is no value present, may be null.
1411      @param reducer      an associative, non-interfering, stateless function for combining two values.
1412      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1413      *
1414      @return a string binding
1415      */
1416     @Nonnull
1417     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, String>> mapper) {
1418         requireNonNull(items, ERROR_ITEMS_NULL);
1419         requireNonNull(reducer, ERROR_REDUCER_NULL);
1420         requireNonNull(mapper, ERROR_MAPPER_NULL);
1421         return createStringBinding(() -> {
1422             BinaryOperator<T> operator = reducer.getValue();
1423             requireNonNull(operator, ERROR_REDUCER_NULL);
1424             final Function<? super T, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : String::valueOf;
1425             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1426         }, items, reducer, mapper);
1427     }
1428 
1429     /**
1430      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1431      *
1432      @param items    the observable set of elements.
1433      @param supplier a {@code Supplier} whose result is returned if no value is present.
1434      @param reducer  an associative, non-interfering, stateless function for combining two values.
1435      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1436      *
1437      @return a string binding
1438      */
1439     @Nonnull
1440     public static <T> StringBinding reduceThenMapToString(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, String>> mapper) {
1441         requireNonNull(items, ERROR_ITEMS_NULL);
1442         requireNonNull(reducer, ERROR_REDUCER_NULL);
1443         requireNonNull(mapper, ERROR_MAPPER_NULL);
1444         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1445         return createStringBinding(() -> {
1446             BinaryOperator<T> operator = reducer.getValue();
1447             requireNonNull(operator, ERROR_REDUCER_NULL);
1448             final Function<? super T, String> mapperValue = mapper.getValue() != null ? mapper.getValue() : String::valueOf;
1449             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1450         }, items, reducer, mapper);
1451     }
1452 
1453     /**
1454      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1455      *
1456      @param items        the observable set of elements.
1457      @param defaultValue the value to be returned if there is no value present, may be null.
1458      @param reducer      an associative, non-interfering, stateless function for combining two values.
1459      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1460      *
1461      @return an integer binding
1462      */
1463     @Nonnull
1464     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Integer> mapper) {
1465         requireNonNull(items, ERROR_ITEMS_NULL);
1466         requireNonNull(reducer, ERROR_REDUCER_NULL);
1467         requireNonNull(mapper, ERROR_MAPPER_NULL);
1468         return createIntegerBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1469     }
1470 
1471     /**
1472      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1473      *
1474      @param items    the observable set of elements.
1475      @param supplier a {@code Supplier} whose result is returned if no value is present.
1476      @param reducer  an associative, non-interfering, stateless function for combining two values.
1477      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1478      *
1479      @return an integer binding
1480      */
1481     @Nonnull
1482     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Integer> mapper) {
1483         requireNonNull(items, ERROR_ITEMS_NULL);
1484         requireNonNull(reducer, ERROR_REDUCER_NULL);
1485         requireNonNull(mapper, ERROR_MAPPER_NULL);
1486         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1487         return createIntegerBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1488     }
1489 
1490     /**
1491      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1492      *
1493      @param items        the observable set of elements.
1494      @param defaultValue the value to be returned if there is no value present, may be null.
1495      @param reducer      an associative, non-interfering, stateless function for combining two values.
1496      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1497      *
1498      @return an integer binding
1499      */
1500     @Nonnull
1501     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper) {
1502         requireNonNull(items, ERROR_ITEMS_NULL);
1503         requireNonNull(reducer, ERROR_REDUCER_NULL);
1504         requireNonNull(mapper, ERROR_MAPPER_NULL);
1505         return createIntegerBinding(() -> {
1506             BinaryOperator<T> operator = reducer.getValue();
1507             requireNonNull(operator, ERROR_REDUCER_NULL);
1508             final Function<? super T, Integer> mapperValue = mapper.getValue();
1509             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1510             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1511         }, items, reducer, mapper);
1512     }
1513 
1514     /**
1515      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1516      *
1517      @param items    the observable set of elements.
1518      @param supplier a {@code Supplier} whose result is returned if no value is present.
1519      @param reducer  an associative, non-interfering, stateless function for combining two values.
1520      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1521      *
1522      @return an integer binding
1523      */
1524     @Nonnull
1525     public static <T> IntegerBinding reduceThenMapToInteger(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper) {
1526         requireNonNull(items, ERROR_ITEMS_NULL);
1527         requireNonNull(reducer, ERROR_REDUCER_NULL);
1528         requireNonNull(mapper, ERROR_MAPPER_NULL);
1529         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1530         return createIntegerBinding(() -> {
1531             BinaryOperator<T> operator = reducer.getValue();
1532             requireNonNull(operator, ERROR_REDUCER_NULL);
1533             final Function<? super T, Integer> mapperValue = mapper.getValue();
1534             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1535             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1536         }, items, reducer, mapper);
1537     }
1538 
1539     /**
1540      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1541      *
1542      @param items        the observable set of elements.
1543      @param defaultValue the value to be returned if there is no value present, may be null.
1544      @param reducer      an associative, non-interfering, stateless function for combining two values.
1545      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1546      *
1547      @return a long binding
1548      */
1549     @Nonnull
1550     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Long> mapper) {
1551         requireNonNull(items, ERROR_ITEMS_NULL);
1552         requireNonNull(reducer, ERROR_REDUCER_NULL);
1553         requireNonNull(mapper, ERROR_MAPPER_NULL);
1554         return createLongBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1555     }
1556 
1557     /**
1558      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1559      *
1560      @param items    the observable set of elements.
1561      @param supplier a {@code Supplier} whose result is returned if no value is present.
1562      @param reducer  an associative, non-interfering, stateless function for combining two values.
1563      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1564      *
1565      @return a long binding
1566      */
1567     @Nonnull
1568     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Long> mapper) {
1569         requireNonNull(items, ERROR_ITEMS_NULL);
1570         requireNonNull(reducer, ERROR_REDUCER_NULL);
1571         requireNonNull(mapper, ERROR_MAPPER_NULL);
1572         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1573         return createLongBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1574     }
1575 
1576     /**
1577      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1578      *
1579      @param items        the observable set of elements.
1580      @param defaultValue the value to be returned if there is no value present, may be null.
1581      @param reducer      an associative, non-interfering, stateless function for combining two values.
1582      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1583      *
1584      @return a long binding
1585      */
1586     @Nonnull
1587     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Long>> mapper) {
1588         requireNonNull(items, ERROR_ITEMS_NULL);
1589         requireNonNull(reducer, ERROR_REDUCER_NULL);
1590         requireNonNull(mapper, ERROR_MAPPER_NULL);
1591         return createLongBinding(() -> {
1592             BinaryOperator<T> operator = reducer.getValue();
1593             requireNonNull(operator, ERROR_REDUCER_NULL);
1594             final Function<? super T, Long> mapperValue = mapper.getValue();
1595             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1596             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1597         }, items, reducer, mapper);
1598     }
1599 
1600     /**
1601      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1602      *
1603      @param items    the observable set of elements.
1604      @param supplier a {@code Supplier} whose result is returned if no value is present.
1605      @param reducer  an associative, non-interfering, stateless function for combining two values.
1606      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1607      *
1608      @return a long binding
1609      */
1610     @Nonnull
1611     public static <T> LongBinding reduceThenMapToLong(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Long>> mapper) {
1612         requireNonNull(items, ERROR_ITEMS_NULL);
1613         requireNonNull(reducer, ERROR_REDUCER_NULL);
1614         requireNonNull(mapper, ERROR_MAPPER_NULL);
1615         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1616         return createLongBinding(() -> {
1617             BinaryOperator<T> operator = reducer.getValue();
1618             requireNonNull(operator, ERROR_REDUCER_NULL);
1619             final Function<? super T, Long> mapperValue = mapper.getValue();
1620             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1621             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1622         }, items, reducer, mapper);
1623     }
1624 
1625     /**
1626      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1627      *
1628      @param items        the observable set of elements.
1629      @param defaultValue the value to be returned if there is no value present, may be null.
1630      @param reducer      an associative, non-interfering, stateless function for combining two values.
1631      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1632      *
1633      @return a float binding
1634      */
1635     @Nonnull
1636     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Float> mapper) {
1637         requireNonNull(items, ERROR_ITEMS_NULL);
1638         requireNonNull(reducer, ERROR_REDUCER_NULL);
1639         requireNonNull(mapper, ERROR_MAPPER_NULL);
1640         return createFloatBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1641     }
1642 
1643     /**
1644      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1645      *
1646      @param items    the observable set of elements.
1647      @param supplier a {@code Supplier} whose result is returned if no value is present.
1648      @param reducer  an associative, non-interfering, stateless function for combining two values.
1649      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1650      *
1651      @return a float binding
1652      */
1653     @Nonnull
1654     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Float> mapper) {
1655         requireNonNull(items, ERROR_ITEMS_NULL);
1656         requireNonNull(reducer, ERROR_REDUCER_NULL);
1657         requireNonNull(mapper, ERROR_MAPPER_NULL);
1658         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1659         return createFloatBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1660     }
1661 
1662     /**
1663      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1664      *
1665      @param items        the observable set of elements.
1666      @param defaultValue the value to be returned if there is no value present, may be null.
1667      @param reducer      an associative, non-interfering, stateless function for combining two values.
1668      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1669      *
1670      @return a float binding
1671      */
1672     @Nonnull
1673     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Float>> mapper) {
1674         requireNonNull(items, ERROR_ITEMS_NULL);
1675         requireNonNull(reducer, ERROR_REDUCER_NULL);
1676         requireNonNull(mapper, ERROR_MAPPER_NULL);
1677         return createFloatBinding(() -> {
1678             BinaryOperator<T> operator = reducer.getValue();
1679             requireNonNull(operator, ERROR_REDUCER_NULL);
1680             final Function<? super T, Float> mapperValue = mapper.getValue();
1681             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1682             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1683         }, items, reducer, mapper);
1684     }
1685 
1686     /**
1687      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1688      *
1689      @param items    the observable set of elements.
1690      @param supplier a {@code Supplier} whose result is returned if no value is present.
1691      @param reducer  an associative, non-interfering, stateless function for combining two values.
1692      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1693      *
1694      @return a float binding
1695      */
1696     @Nonnull
1697     public static <T> FloatBinding reduceThenMapToFloat(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Float>> mapper) {
1698         requireNonNull(items, ERROR_ITEMS_NULL);
1699         requireNonNull(reducer, ERROR_REDUCER_NULL);
1700         requireNonNull(mapper, ERROR_MAPPER_NULL);
1701         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1702         return createFloatBinding(() -> {
1703             BinaryOperator<T> operator = reducer.getValue();
1704             requireNonNull(operator, ERROR_REDUCER_NULL);
1705             final Function<? super T, Float> mapperValue = mapper.getValue();
1706             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1707             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1708         }, items, reducer, mapper);
1709     }
1710 
1711     /**
1712      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1713      *
1714      @param items        the observable set of elements.
1715      @param defaultValue the value to be returned if there is no value present, may be null.
1716      @param reducer      an associative, non-interfering, stateless function for combining two values.
1717      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1718      *
1719      @return a double binding
1720      */
1721     @Nonnull
1722     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Double> mapper) {
1723         requireNonNull(items, ERROR_ITEMS_NULL);
1724         requireNonNull(reducer, ERROR_REDUCER_NULL);
1725         requireNonNull(mapper, ERROR_MAPPER_NULL);
1726         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1727     }
1728 
1729     /**
1730      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1731      *
1732      @param items    the observable set of elements.
1733      @param supplier a {@code Supplier} whose result is returned if no value is present.
1734      @param reducer  an associative, non-interfering, stateless function for combining two values.
1735      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1736      *
1737      @return a double binding
1738      */
1739     @Nonnull
1740     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Double> mapper) {
1741         requireNonNull(items, ERROR_ITEMS_NULL);
1742         requireNonNull(reducer, ERROR_REDUCER_NULL);
1743         requireNonNull(mapper, ERROR_MAPPER_NULL);
1744         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1745         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1746     }
1747 
1748     /**
1749      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1750      *
1751      @param items        the observable set of elements.
1752      @param defaultValue the value to be returned if there is no value present, may be null.
1753      @param reducer      an associative, non-interfering, stateless function for combining two values.
1754      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1755      *
1756      @return a double binding
1757      */
1758     @Nonnull
1759     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Double>> mapper) {
1760         requireNonNull(items, ERROR_ITEMS_NULL);
1761         requireNonNull(reducer, ERROR_REDUCER_NULL);
1762         requireNonNull(mapper, ERROR_MAPPER_NULL);
1763         return createDoubleBinding(() -> {
1764             BinaryOperator<T> operator = reducer.getValue();
1765             requireNonNull(operator, ERROR_REDUCER_NULL);
1766             final Function<? super T, Double> mapperValue = mapper.getValue();
1767             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1768             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1769         }, items, reducer, mapper);
1770     }
1771 
1772     /**
1773      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1774      *
1775      @param items    the observable set of elements.
1776      @param supplier a {@code Supplier} whose result is returned if no value is present.
1777      @param reducer  an associative, non-interfering, stateless function for combining two values.
1778      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1779      *
1780      @return a double binding
1781      */
1782     @Nonnull
1783     public static <T> DoubleBinding reduceThenMapToDouble(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Double>> mapper) {
1784         requireNonNull(items, ERROR_ITEMS_NULL);
1785         requireNonNull(reducer, ERROR_REDUCER_NULL);
1786         requireNonNull(mapper, ERROR_MAPPER_NULL);
1787         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1788         return createDoubleBinding(() -> {
1789             BinaryOperator<T> operator = reducer.getValue();
1790             requireNonNull(operator, ERROR_REDUCER_NULL);
1791             final Function<? super T, Double> mapperValue = mapper.getValue();
1792             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1793             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1794         }, items, reducer, mapper);
1795     }
1796 
1797     /**
1798      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1799      *
1800      @param items        the observable set of elements.
1801      @param defaultValue the value to be returned if there is no value present, may be null.
1802      @param reducer      an associative, non-interfering, stateless function for combining two values.
1803      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1804      *
1805      @return a boolean binding
1806      */
1807     @Nonnull
1808     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Boolean> mapper) {
1809         requireNonNull(items, ERROR_ITEMS_NULL);
1810         requireNonNull(reducer, ERROR_REDUCER_NULL);
1811         requireNonNull(mapper, ERROR_MAPPER_NULL);
1812         return createBooleanBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1813     }
1814 
1815     /**
1816      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1817      *
1818      @param items    the observable set of elements.
1819      @param supplier a {@code Supplier} whose result is returned if no value is present.
1820      @param reducer  an associative, non-interfering, stateless function for combining two values.
1821      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1822      *
1823      @return a boolean binding
1824      */
1825     @Nonnull
1826     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Boolean> mapper) {
1827         requireNonNull(items, ERROR_ITEMS_NULL);
1828         requireNonNull(reducer, ERROR_REDUCER_NULL);
1829         requireNonNull(mapper, ERROR_MAPPER_NULL);
1830         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1831         return createBooleanBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
1832     }
1833 
1834     /**
1835      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1836      *
1837      @param items        the observable set of elements.
1838      @param defaultValue the value to be returned if there is no value present, may be null.
1839      @param reducer      an associative, non-interfering, stateless function for combining two values.
1840      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1841      *
1842      @return a boolean binding
1843      */
1844     @Nonnull
1845     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper) {
1846         requireNonNull(items, ERROR_ITEMS_NULL);
1847         requireNonNull(reducer, ERROR_REDUCER_NULL);
1848         requireNonNull(mapper, ERROR_MAPPER_NULL);
1849         return createBooleanBinding(() -> {
1850             BinaryOperator<T> operator = reducer.getValue();
1851             requireNonNull(operator, ERROR_REDUCER_NULL);
1852             final Function<? super T, Boolean> mapperValue = mapper.getValue();
1853             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1854             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
1855         }, items, reducer, mapper);
1856     }
1857 
1858     /**
1859      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1860      *
1861      @param items    the observable set of elements.
1862      @param supplier a {@code Supplier} whose result is returned if no value is present.
1863      @param reducer  an associative, non-interfering, stateless function for combining two values.
1864      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1865      *
1866      @return a boolean binding
1867      */
1868     @Nonnull
1869     public static <T> BooleanBinding reduceThenMapToBoolean(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper) {
1870         requireNonNull(items, ERROR_ITEMS_NULL);
1871         requireNonNull(reducer, ERROR_REDUCER_NULL);
1872         requireNonNull(mapper, ERROR_MAPPER_NULL);
1873         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1874         return createBooleanBinding(() -> {
1875             BinaryOperator<T> operator = reducer.getValue();
1876             requireNonNull(operator, ERROR_REDUCER_NULL);
1877             final Function<? super T, Boolean> mapperValue = mapper.getValue();
1878             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1879             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
1880         }, items, reducer, mapper);
1881     }
1882 
1883     /**
1884      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1885      *
1886      @param items        the observable set of elements.
1887      @param defaultValue the value to be returned if there is no value present, may be null.
1888      @param reducer      an associative, non-interfering, stateless function for combining two values.
1889      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1890      *
1891      @return a number binding
1892      */
1893     @Nonnull
1894     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, ? extends Number> mapper) {
1895         requireNonNull(items, ERROR_ITEMS_NULL);
1896         requireNonNull(reducer, ERROR_REDUCER_NULL);
1897         requireNonNull(mapper, ERROR_MAPPER_NULL);
1898         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)).doubleValue(), items);
1899     }
1900 
1901     /**
1902      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1903      *
1904      @param items    the observable set of elements.
1905      @param supplier a {@code Supplier} whose result is returned if no value is present.
1906      @param reducer  an associative, non-interfering, stateless function for combining two values.
1907      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1908      *
1909      @return a number binding
1910      */
1911     @Nonnull
1912     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, Number> mapper) {
1913         requireNonNull(items, ERROR_ITEMS_NULL);
1914         requireNonNull(reducer, ERROR_REDUCER_NULL);
1915         requireNonNull(mapper, ERROR_MAPPER_NULL);
1916         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1917         return createDoubleBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)).doubleValue(), items);
1918     }
1919 
1920     /**
1921      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1922      *
1923      @param items        the observable set of elements.
1924      @param defaultValue the value to be returned if there is no value present, may be null.
1925      @param reducer      an associative, non-interfering, stateless function for combining two values.
1926      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1927      *
1928      @return a number binding
1929      */
1930     @Nonnull
1931     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, ? extends Number>> mapper) {
1932         requireNonNull(items, ERROR_ITEMS_NULL);
1933         requireNonNull(reducer, ERROR_REDUCER_NULL);
1934         requireNonNull(mapper, ERROR_MAPPER_NULL);
1935         return createDoubleBinding(() -> {
1936             BinaryOperator<T> operator = reducer.getValue();
1937             requireNonNull(operator, ERROR_REDUCER_NULL);
1938             final Function<? super T, ? extends Number> mapperValue = mapper.getValue();
1939             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1940             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue)).doubleValue();
1941         }, items, reducer, mapper);
1942     }
1943 
1944     /**
1945      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
1946      *
1947      @param items    the observable set of elements.
1948      @param supplier a {@code Supplier} whose result is returned if no value is present.
1949      @param reducer  an associative, non-interfering, stateless function for combining two values.
1950      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1951      *
1952      @return a number binding
1953      */
1954     @Nonnull
1955     public static <T> NumberBinding reduceThenMapToNumber(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, Number>> mapper) {
1956         requireNonNull(items, ERROR_ITEMS_NULL);
1957         requireNonNull(reducer, ERROR_REDUCER_NULL);
1958         requireNonNull(mapper, ERROR_MAPPER_NULL);
1959         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
1960         return createDoubleBinding(() -> {
1961             BinaryOperator<T> operator = reducer.getValue();
1962             requireNonNull(operator, ERROR_REDUCER_NULL);
1963             final Function<? super T, ? extends Number> mapperValue = mapper.getValue();
1964             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
1965             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier)).doubleValue();
1966         }, items, reducer, mapper);
1967     }
1968 
1969     /**
1970      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1971      *
1972      @param items        the observable list of elements.
1973      @param defaultValue the value to be returned if there is no value present, may be null.
1974      @param reducer      an associative, non-interfering, stateless function for combining two values.
1975      @param mapper       a non-interfering, stateless function to apply to the reduced value.
1976      *
1977      @return an object binding
1978      */
1979     @Nonnull
1980     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, R> mapper) {
1981         requireNonNull(items, ERROR_ITEMS_NULL);
1982         requireNonNull(reducer, ERROR_REDUCER_NULL);
1983         requireNonNull(mapper, ERROR_MAPPER_NULL);
1984         return createObjectBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
1985     }
1986 
1987     /**
1988      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
1989      *
1990      @param items    the observable list of elements.
1991      @param supplier a {@code Supplier} whose result is returned if no value is present.
1992      @param reducer  an associative, non-interfering, stateless function for combining two values.
1993      @param mapper   a non-interfering, stateless function to apply to the reduced value.
1994      *
1995      @return an object binding
1996      */
1997     @Nonnull
1998     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, R> mapper) {
1999         requireNonNull(items, ERROR_ITEMS_NULL);
2000         requireNonNull(reducer, ERROR_REDUCER_NULL);
2001         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2002         requireNonNull(mapper, ERROR_MAPPER_NULL);
2003         return createObjectBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
2004     }
2005 
2006     /**
2007      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
2008      *
2009      @param items        the observable list of elements.
2010      @param defaultValue the value to be returned if there is no value present, may be null.
2011      @param reducer      an associative, non-interfering, stateless function for combining two values.
2012      @param mapper       a non-interfering, stateless function to apply to the reduced value.
2013      *
2014      @return an object binding
2015      */
2016     @Nonnull
2017     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableList<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, R>> mapper) {
2018         requireNonNull(reducer, ERROR_REDUCER_NULL);
2019         requireNonNull(mapper, ERROR_MAPPER_NULL);
2020         return createObjectBinding(() -> {
2021             BinaryOperator<T> operator = reducer.getValue();
2022             requireNonNull(operator, ERROR_REDUCER_NULL);
2023             final Function<? super T, R> mapperValue = mapper.getValue();
2024             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2025             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
2026         }, items, reducer, mapper);
2027     }
2028 
2029     /**
2030      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to the reduced value.
2031      *
2032      @param items    the observable list of elements.
2033      @param supplier a {@code Supplier} whose result is returned if no value is present.
2034      @param reducer  an associative, non-interfering, stateless function for combining two values.
2035      @param mapper   a non-interfering, stateless function to apply to the reduced value.
2036      *
2037      @return an object binding
2038      */
2039     @Nonnull
2040     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, R>> mapper) {
2041         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2042         requireNonNull(reducer, ERROR_REDUCER_NULL);
2043         requireNonNull(mapper, ERROR_MAPPER_NULL);
2044         return createObjectBinding(() -> {
2045             BinaryOperator<T> operator = reducer.getValue();
2046             requireNonNull(operator, ERROR_REDUCER_NULL);
2047             final Function<? super T, R> mapperValue = mapper.getValue();
2048             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2049             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
2050         }, items, reducer, mapper);
2051     }
2052 
2053     /**
2054      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
2055      *
2056      @param items        the observable set of elements.
2057      @param defaultValue the value to be returned if there is no value present, may be null.
2058      @param reducer      an associative, non-interfering, stateless function for combining two values.
2059      @param mapper       a non-interfering, stateless function to apply to the reduced value.
2060      *
2061      @return an object binding
2062      */
2063     @Nonnull
2064     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, R> mapper) {
2065         requireNonNull(items, ERROR_ITEMS_NULL);
2066         requireNonNull(reducer, ERROR_REDUCER_NULL);
2067         return createObjectBinding(() -> mapper.apply(items.stream().reduce(reducer).orElse(defaultValue)), items);
2068     }
2069 
2070     /**
2071      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
2072      *
2073      @param items    the observable set of elements.
2074      @param supplier a {@code Supplier} whose result is returned if no value is present.
2075      @param reducer  an associative, non-interfering, stateless function for combining two values.
2076      @param mapper   a non-interfering, stateless function to apply to the reduced value.
2077      *
2078      @return an object binding
2079      */
2080     @Nonnull
2081     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final BinaryOperator<T> reducer, @Nonnull final Function<? super T, R> mapper) {
2082         requireNonNull(items, ERROR_ITEMS_NULL);
2083         requireNonNull(reducer, ERROR_REDUCER_NULL);
2084         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2085         requireNonNull(mapper, ERROR_MAPPER_NULL);
2086         return createObjectBinding(() -> mapper.apply(items.stream().reduce(reducer).orElseGet(supplier)), items);
2087     }
2088 
2089     /**
2090      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
2091      *
2092      @param items        the observable set of elements.
2093      @param defaultValue the value to be returned if there is no value present, may be null.
2094      @param reducer      an associative, non-interfering, stateless function for combining two values.
2095      @param mapper       a non-interfering, stateless function to apply to the reduced value.
2096      *
2097      @return an object binding
2098      */
2099     @Nonnull
2100     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableSet<T> items, @Nullable final T defaultValue, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, R>> mapper) {
2101         requireNonNull(reducer, ERROR_REDUCER_NULL);
2102         requireNonNull(mapper, ERROR_MAPPER_NULL);
2103         return createObjectBinding(() -> {
2104             BinaryOperator<T> operator = reducer.getValue();
2105             requireNonNull(operator, ERROR_REDUCER_NULL);
2106             final Function<? super T, R> mapperValue = mapper.getValue();
2107             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2108             return mapperValue.apply(items.stream().reduce(operator).orElse(defaultValue));
2109         }, items, reducer, mapper);
2110     }
2111 
2112     /**
2113      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to the reduced value.
2114      *
2115      @param items    the observable set of elements.
2116      @param supplier a {@code Supplier} whose result is returned if no value is present.
2117      @param reducer  an associative, non-interfering, stateless function for combining two values.
2118      @param mapper   a non-interfering, stateless function to apply to the reduced value.
2119      *
2120      @return an object binding
2121      */
2122     @Nonnull
2123     public static <T, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<T> supplier, @Nonnull final ObservableValue<BinaryOperator<T>> reducer, @Nonnull final ObservableValue<Function<? super T, R>> mapper) {
2124         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2125         requireNonNull(reducer, ERROR_REDUCER_NULL);
2126         requireNonNull(mapper, ERROR_MAPPER_NULL);
2127         return createObjectBinding(() -> {
2128             BinaryOperator<T> operator = reducer.getValue();
2129             requireNonNull(operator, ERROR_REDUCER_NULL);
2130             final Function<? super T, R> mapperValue = mapper.getValue();
2131             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2132             return mapperValue.apply(items.stream().reduce(operator).orElseGet(supplier));
2133         }, items, reducer, mapper);
2134     }
2135 
2136     /**
2137      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
2138      *
2139      @param items        the observable map.
2140      @param defaultValue the value to be returned if there is no value present, may be null.
2141      @param reducer      an associative, non-interfering, stateless function for combining two values.
2142      @param mapper       a non-interfering, stateless function to apply to the reduced value.
2143      *
2144      @return an object binding
2145      */
2146     @Nonnull
2147     public static <K, V, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, R> mapper) {
2148         requireNonNull(items, ERROR_ITEMS_NULL);
2149         requireNonNull(reducer, ERROR_REDUCER_NULL);
2150         requireNonNull(mapper, ERROR_MAPPER_NULL);
2151         return createObjectBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElse(defaultValue)), items);
2152     }
2153 
2154     /**
2155      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
2156      *
2157      @param items    the observable map.
2158      @param supplier a {@code Supplier} whose result is returned if no value is present.
2159      @param reducer  an associative, non-interfering, stateless function for combining two values.
2160      @param mapper   a non-interfering, stateless function to apply to the reduced value.
2161      *
2162      @return an object binding
2163      */
2164     @Nonnull
2165     public static <K, V, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final BinaryOperator<V> reducer, @Nonnull final Function<? super V, R> mapper) {
2166         requireNonNull(items, ERROR_ITEMS_NULL);
2167         requireNonNull(reducer, ERROR_REDUCER_NULL);
2168         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2169         requireNonNull(mapper, ERROR_MAPPER_NULL);
2170         return createObjectBinding(() -> mapper.apply(items.values().stream().reduce(reducer).orElseGet(supplier)), items);
2171     }
2172 
2173     /**
2174      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
2175      *
2176      @param items        the observable map.
2177      @param defaultValue the value to be returned if there is no value present, may be null.
2178      @param reducer      an associative, non-interfering, stateless function for combining two values.
2179      @param mapper       a non-interfering, stateless function to apply to the reduced value.
2180      *
2181      @return an object binding
2182      */
2183     @Nonnull
2184     public static <K, V, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableMap<K, V> items, @Nullable final V defaultValue, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, R>> mapper) {
2185         requireNonNull(reducer, ERROR_REDUCER_NULL);
2186         requireNonNull(mapper, ERROR_MAPPER_NULL);
2187         return createObjectBinding(() -> {
2188             BinaryOperator<V> operator = reducer.getValue();
2189             requireNonNull(operator, ERROR_REDUCER_NULL);
2190             final Function<? super V, R> mapperValue = mapper.getValue();
2191             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2192             return mapperValue.apply(items.values().stream().reduce(operator).orElse(defaultValue));
2193         }, items, reducer, mapper);
2194     }
2195 
2196     /**
2197      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to the reduced value.
2198      *
2199      @param items    the observable map.
2200      @param supplier a {@code Supplier} whose result is returned if no value is present.
2201      @param reducer  an associative, non-interfering, stateless function for combining two values.
2202      @param mapper   a non-interfering, stateless function to apply to the reduced value.
2203      *
2204      @return an object binding
2205      */
2206     @Nonnull
2207     public static <K, V, R> ObjectBinding<R> reduceThenMap(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<V> supplier, @Nonnull final ObservableValue<BinaryOperator<V>> reducer, @Nonnull final ObservableValue<Function<? super V, R>> mapper) {
2208         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2209         requireNonNull(reducer, ERROR_REDUCER_NULL);
2210         requireNonNull(mapper, ERROR_MAPPER_NULL);
2211         return createObjectBinding(() -> {
2212             BinaryOperator<V> operator = reducer.getValue();
2213             requireNonNull(operator, ERROR_REDUCER_NULL);
2214             final Function<? super V, R> mapperValue = mapper.getValue();
2215             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2216             return mapperValue.apply(items.values().stream().reduce(operator).orElseGet(supplier));
2217         }, items, reducer, mapper);
2218     }
2219 
2220     /**
2221      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2222      *
2223      @param items        the observable list of elements.
2224      @param defaultValue the value to be returned if there is no value present, may be null.
2225      @param mapper       a non-interfering, stateless function to apply to each element.
2226      @param reducer      an associative, non-interfering, stateless function for combining two values.
2227      *
2228      @return an object binding
2229      */
2230     @Nonnull
2231     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableList<T> items, @Nullable final R defaultValue, @Nonnull final Function<? super T, R> mapper, @Nonnull final BinaryOperator<R> reducer) {
2232         requireNonNull(items, ERROR_ITEMS_NULL);
2233         requireNonNull(reducer, ERROR_REDUCER_NULL);
2234         requireNonNull(mapper, ERROR_MAPPER_NULL);
2235         return createObjectBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2236     }
2237 
2238     /**
2239      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2240      *
2241      @param items    the observable list of elements.
2242      @param supplier a {@code Supplier} whose result is returned if no value is present.
2243      @param mapper   a non-interfering, stateless function to apply to each element.
2244      @param reducer  an associative, non-interfering, stateless function for combining two values.
2245      *
2246      @return an object binding
2247      */
2248     @Nonnull
2249     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<R> supplier, @Nonnull final Function<? super T, R> mapper, @Nonnull final BinaryOperator<R> reducer) {
2250         requireNonNull(items, ERROR_ITEMS_NULL);
2251         requireNonNull(reducer, ERROR_REDUCER_NULL);
2252         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2253         requireNonNull(mapper, ERROR_MAPPER_NULL);
2254         return createObjectBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2255     }
2256 
2257     /**
2258      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2259      *
2260      @param items        the observable list of elements.
2261      @param defaultValue the value to be returned if there is no value present, may be null.
2262      @param mapper       a non-interfering, stateless function to apply to each element.
2263      @param reducer      an associative, non-interfering, stateless function for combining two values.
2264      *
2265      @return an object binding
2266      */
2267     @Nonnull
2268     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableList<T> items, @Nullable final R defaultValue, @Nonnull final ObservableValue<Function<? super T, R>> mapper, @Nonnull final ObservableValue<BinaryOperator<R>> reducer) {
2269         requireNonNull(reducer, ERROR_REDUCER_NULL);
2270         requireNonNull(mapper, ERROR_MAPPER_NULL);
2271         return createObjectBinding(() -> {
2272             BinaryOperator<R> reducerValue = reducer.getValue();
2273             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2274             final Function<? super T, R> mapperValue = mapper.getValue();
2275             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2276             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2277         }, items, reducer, mapper);
2278     }
2279 
2280     /**
2281      * Returns an object binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2282      *
2283      @param items    the observable list of elements.
2284      @param supplier a {@code Supplier} whose result is returned if no value is present.
2285      @param mapper   a non-interfering, stateless function to apply to each element.
2286      @param reducer  an associative, non-interfering, stateless function for combining two values.
2287      *
2288      @return an object binding
2289      */
2290     @Nonnull
2291     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<R> supplier, @Nonnull final ObservableValue<Function<? super T, R>> mapper, @Nonnull final ObservableValue<BinaryOperator<R>> reducer) {
2292         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2293         requireNonNull(reducer, ERROR_REDUCER_NULL);
2294         requireNonNull(mapper, ERROR_MAPPER_NULL);
2295         return createObjectBinding(() -> {
2296             BinaryOperator<R> reducerValue = reducer.getValue();
2297             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2298             final Function<? super T, R> mapperValue = mapper.getValue();
2299             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2300             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2301         }, items, reducer, mapper);
2302     }
2303 
2304     /**
2305      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2306      *
2307      @param items        the observable set of elements.
2308      @param defaultValue the value to be returned if there is no value present, may be null.
2309      @param mapper       a non-interfering, stateless function to apply to each element.
2310      @param reducer      an associative, non-interfering, stateless function for combining two values.
2311      *
2312      @return an object binding
2313      */
2314     @Nonnull
2315     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final R defaultValue, @Nonnull final Function<? super T, R> mapper, @Nonnull final BinaryOperator<R> reducer) {
2316         requireNonNull(items, ERROR_ITEMS_NULL);
2317         requireNonNull(reducer, ERROR_REDUCER_NULL);
2318         return createObjectBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2319     }
2320 
2321     /**
2322      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2323      *
2324      @param items    the observable set of elements.
2325      @param supplier a {@code Supplier} whose result is returned if no value is present.
2326      @param mapper   a non-interfering, stateless function to apply to each element.
2327      @param reducer  an associative, non-interfering, stateless function for combining two values.
2328      *
2329      @return an object binding
2330      */
2331     @Nonnull
2332     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<R> supplier, @Nonnull final Function<? super T, R> mapper, @Nonnull final BinaryOperator<R> reducer) {
2333         requireNonNull(items, ERROR_ITEMS_NULL);
2334         requireNonNull(reducer, ERROR_REDUCER_NULL);
2335         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2336         requireNonNull(mapper, ERROR_MAPPER_NULL);
2337         return createObjectBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2338     }
2339 
2340     /**
2341      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2342      *
2343      @param items        the observable set of elements.
2344      @param defaultValue the value to be returned if there is no value present, may be null.
2345      @param mapper       a non-interfering, stateless function to apply to each element.
2346      @param reducer      an associative, non-interfering, stateless function for combining two values.
2347      *
2348      @return an object binding
2349      */
2350     @Nonnull
2351     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final R defaultValue, @Nonnull final ObservableValue<Function<? super T, R>> mapper, @Nonnull final ObservableValue<BinaryOperator<R>> reducer) {
2352         requireNonNull(reducer, ERROR_REDUCER_NULL);
2353         requireNonNull(mapper, ERROR_MAPPER_NULL);
2354         return createObjectBinding(() -> {
2355             BinaryOperator<R> reducerValue = reducer.getValue();
2356             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2357             final Function<? super T, R> mapperValue = mapper.getValue();
2358             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2359             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2360         }, items, reducer, mapper);
2361     }
2362 
2363     /**
2364      * Returns an object binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2365      *
2366      @param items    the observable set of elements.
2367      @param supplier a {@code Supplier} whose result is returned if no value is present.
2368      @param mapper   a non-interfering, stateless function to apply to each element.
2369      @param reducer  an associative, non-interfering, stateless function for combining two values.
2370      *
2371      @return an object binding
2372      */
2373     @Nonnull
2374     public static <T, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<R> supplier, @Nonnull final ObservableValue<Function<? super T, R>> mapper, @Nonnull final ObservableValue<BinaryOperator<R>> reducer) {
2375         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2376         requireNonNull(reducer, ERROR_REDUCER_NULL);
2377         requireNonNull(mapper, ERROR_MAPPER_NULL);
2378         return createObjectBinding(() -> {
2379             BinaryOperator<R> reducerValue = reducer.getValue();
2380             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2381             final Function<? super T, R> mapperValue = mapper.getValue();
2382             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2383             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2384         }, items, reducer, mapper);
2385     }
2386 
2387     /**
2388      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2389      *
2390      @param items        the observable map.
2391      @param defaultValue the value to be returned if there is no value present, may be null.
2392      @param mapper       a non-interfering, stateless function to apply to each value.
2393      @param reducer      an associative, non-interfering, stateless function for combining two values.
2394      *
2395      @return an object binding
2396      */
2397     @Nonnull
2398     public static <K, V, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final R defaultValue, @Nonnull final Function<? super V, R> mapper, @Nonnull final BinaryOperator<R> reducer) {
2399         requireNonNull(items, ERROR_ITEMS_NULL);
2400         requireNonNull(reducer, ERROR_REDUCER_NULL);
2401         requireNonNull(mapper, ERROR_MAPPER_NULL);
2402         return createObjectBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2403     }
2404 
2405     /**
2406      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2407      *
2408      @param items    the observable map.
2409      @param supplier a {@code Supplier} whose result is returned if no value is present.
2410      @param mapper   a non-interfering, stateless function to apply to each value.
2411      @param reducer  an associative, non-interfering, stateless function for combining two values.
2412      *
2413      @return an object binding
2414      */
2415     @Nonnull
2416     public static <K, V, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<R> supplier, @Nonnull final Function<? super V, R> mapper, @Nonnull final BinaryOperator<R> reducer) {
2417         requireNonNull(items, ERROR_ITEMS_NULL);
2418         requireNonNull(reducer, ERROR_REDUCER_NULL);
2419         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2420         requireNonNull(mapper, ERROR_MAPPER_NULL);
2421         return createObjectBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2422     }
2423 
2424     /**
2425      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2426      *
2427      @param items        the observable map.
2428      @param defaultValue the value to be returned if there is no value present, may be null.
2429      @param mapper       a non-interfering, stateless function to apply to each value.
2430      @param reducer      an associative, non-interfering, stateless function for combining two values.
2431      *
2432      @return an object binding
2433      */
2434     @Nonnull
2435     public static <K, V, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final R defaultValue, @Nonnull final ObservableValue<Function<? super V, R>> mapper, @Nonnull final ObservableValue<BinaryOperator<R>> reducer) {
2436         requireNonNull(reducer, ERROR_REDUCER_NULL);
2437         requireNonNull(mapper, ERROR_MAPPER_NULL);
2438         return createObjectBinding(() -> {
2439             BinaryOperator<R> reducerValue = reducer.getValue();
2440             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2441             final Function<? super V, R> mapperValue = mapper.getValue();
2442             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2443             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2444         }, items, reducer, mapper);
2445     }
2446 
2447     /**
2448      * Returns an object binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2449      *
2450      @param items    the observable map.
2451      @param supplier a {@code Supplier} whose result is returned if no value is present.
2452      @param mapper   a non-interfering, stateless function to apply to each value.
2453      @param reducer  an associative, non-interfering, stateless function for combining two values.
2454      *
2455      @return an object binding
2456      */
2457     @Nonnull
2458     public static <K, V, R> ObjectBinding<R> mapThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<R> supplier, @Nonnull final ObservableValue<Function<? super V, R>> mapper, @Nonnull final ObservableValue<BinaryOperator<R>> reducer) {
2459         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2460         requireNonNull(reducer, ERROR_REDUCER_NULL);
2461         requireNonNull(mapper, ERROR_MAPPER_NULL);
2462         return createObjectBinding(() -> {
2463             BinaryOperator<R> reducerValue = reducer.getValue();
2464             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2465             final Function<? super V, R> mapperValue = mapper.getValue();
2466             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2467             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2468         }, items, reducer, mapper);
2469     }
2470 
2471     /**
2472      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2473      *
2474      @param items        the observable list of elements.
2475      @param defaultValue the value to be returned if there is no value present, may be null.
2476      @param mapper       a non-interfering, stateless function to apply to each element.
2477      @param reducer      an associative, non-interfering, stateless function for combining two values.
2478      *
2479      @return a boolean binding
2480      */
2481     @Nonnull
2482     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Boolean defaultValue, @Nonnull final Function<? super T, Boolean> mapper, @Nonnull final BinaryOperator<Boolean> reducer) {
2483         requireNonNull(items, ERROR_ITEMS_NULL);
2484         requireNonNull(reducer, ERROR_REDUCER_NULL);
2485         requireNonNull(mapper, ERROR_MAPPER_NULL);
2486         return createBooleanBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2487     }
2488 
2489     /**
2490      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2491      *
2492      @param items    the observable list of elements.
2493      @param supplier a {@code Supplier} whose result is returned if no value is present.
2494      @param mapper   a non-interfering, stateless function to apply to each element.
2495      @param reducer  an associative, non-interfering, stateless function for combining two values.
2496      *
2497      @return a boolean binding
2498      */
2499     @Nonnull
2500     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Boolean> supplier, @Nonnull final Function<? super T, Boolean> mapper, @Nonnull final BinaryOperator<Boolean> reducer) {
2501         requireNonNull(items, ERROR_ITEMS_NULL);
2502         requireNonNull(reducer, ERROR_REDUCER_NULL);
2503         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2504         requireNonNull(mapper, ERROR_MAPPER_NULL);
2505         return createBooleanBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2506     }
2507 
2508     /**
2509      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2510      *
2511      @param items        the observable list of elements.
2512      @param defaultValue the value to be returned if there is no value present, may be null.
2513      @param mapper       a non-interfering, stateless function to apply to each element.
2514      @param reducer      an associative, non-interfering, stateless function for combining two values.
2515      *
2516      @return a boolean binding
2517      */
2518     @Nonnull
2519     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Boolean defaultValue, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper, @Nonnull final ObservableValue<BinaryOperator<Boolean>> reducer) {
2520         requireNonNull(reducer, ERROR_REDUCER_NULL);
2521         requireNonNull(mapper, ERROR_MAPPER_NULL);
2522         return createBooleanBinding(() -> {
2523             BinaryOperator<Boolean> reducerValue = reducer.getValue();
2524             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2525             final Function<? super T, Boolean> mapperValue = mapper.getValue();
2526             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2527             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2528         }, items, reducer, mapper);
2529     }
2530 
2531     /**
2532      * Returns a boolean binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2533      *
2534      @param items    the observable list of elements.
2535      @param supplier a {@code Supplier} whose result is returned if no value is present.
2536      @param mapper   a non-interfering, stateless function to apply to each element.
2537      @param reducer  an associative, non-interfering, stateless function for combining two values.
2538      *
2539      @return a boolean binding
2540      */
2541     @Nonnull
2542     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Boolean> supplier, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper, @Nonnull final ObservableValue<BinaryOperator<Boolean>> reducer) {
2543         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2544         requireNonNull(reducer, ERROR_REDUCER_NULL);
2545         requireNonNull(mapper, ERROR_MAPPER_NULL);
2546         return createBooleanBinding(() -> {
2547             BinaryOperator<Boolean> reducerValue = reducer.getValue();
2548             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2549             final Function<? super T, Boolean> mapperValue = mapper.getValue();
2550             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2551             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2552         }, items, reducer, mapper);
2553     }
2554 
2555     /**
2556      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2557      *
2558      @param items        the observable set of elements.
2559      @param defaultValue the value to be returned if there is no value present, may be null.
2560      @param mapper       a non-interfering, stateless function to apply to each element.
2561      @param reducer      an associative, non-interfering, stateless function for combining two values.
2562      *
2563      @return a boolean binding
2564      */
2565     @Nonnull
2566     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Boolean defaultValue, @Nonnull final Function<? super T, Boolean> mapper, @Nonnull final BinaryOperator<Boolean> reducer) {
2567         requireNonNull(items, ERROR_ITEMS_NULL);
2568         requireNonNull(reducer, ERROR_REDUCER_NULL);
2569         return createBooleanBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2570     }
2571 
2572     /**
2573      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2574      *
2575      @param items    the observable set of elements.
2576      @param supplier a {@code Supplier} whose result is returned if no value is present.
2577      @param mapper   a non-interfering, stateless function to apply to each element.
2578      @param reducer  an associative, non-interfering, stateless function for combining two values.
2579      *
2580      @return a boolean binding
2581      */
2582     @Nonnull
2583     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Boolean> supplier, @Nonnull final Function<? super T, Boolean> mapper, @Nonnull final BinaryOperator<Boolean> reducer) {
2584         requireNonNull(items, ERROR_ITEMS_NULL);
2585         requireNonNull(reducer, ERROR_REDUCER_NULL);
2586         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2587         requireNonNull(mapper, ERROR_MAPPER_NULL);
2588         return createBooleanBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2589     }
2590 
2591     /**
2592      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2593      *
2594      @param items        the observable set of elements.
2595      @param defaultValue the value to be returned if there is no value present, may be null.
2596      @param mapper       a non-interfering, stateless function to apply to each element.
2597      @param reducer      an associative, non-interfering, stateless function for combining two values.
2598      *
2599      @return a boolean binding
2600      */
2601     @Nonnull
2602     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Boolean defaultValue, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper, @Nonnull final ObservableValue<BinaryOperator<Boolean>> reducer) {
2603         requireNonNull(reducer, ERROR_REDUCER_NULL);
2604         requireNonNull(mapper, ERROR_MAPPER_NULL);
2605         return createBooleanBinding(() -> {
2606             BinaryOperator<Boolean> reducerValue = reducer.getValue();
2607             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2608             final Function<? super T, Boolean> mapperValue = mapper.getValue();
2609             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2610             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2611         }, items, reducer, mapper);
2612     }
2613 
2614     /**
2615      * Returns a boolean binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2616      *
2617      @param items    the observable set of elements.
2618      @param supplier a {@code Supplier} whose result is returned if no value is present.
2619      @param mapper   a non-interfering, stateless function to apply to each element.
2620      @param reducer  an associative, non-interfering, stateless function for combining two values.
2621      *
2622      @return a boolean binding
2623      */
2624     @Nonnull
2625     public static <T> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Boolean> supplier, @Nonnull final ObservableValue<Function<? super T, Boolean>> mapper, @Nonnull final ObservableValue<BinaryOperator<Boolean>> reducer) {
2626         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2627         requireNonNull(reducer, ERROR_REDUCER_NULL);
2628         requireNonNull(mapper, ERROR_MAPPER_NULL);
2629         return createBooleanBinding(() -> {
2630             BinaryOperator<Boolean> reducerValue = reducer.getValue();
2631             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2632             final Function<? super T, Boolean> mapperValue = mapper.getValue();
2633             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2634             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2635         }, items, reducer, mapper);
2636     }
2637 
2638     /**
2639      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2640      *
2641      @param items        the observable map.
2642      @param defaultValue the value to be returned if there is no value present, may be null.
2643      @param mapper       a non-interfering, stateless function to apply to each value.
2644      @param reducer      an associative, non-interfering, stateless function for combining two values.
2645      *
2646      @return a boolean binding
2647      */
2648     @Nonnull
2649     public static <K, V> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Boolean defaultValue, @Nonnull final Function<? super V, Boolean> mapper, @Nonnull final BinaryOperator<Boolean> reducer) {
2650         requireNonNull(items, ERROR_ITEMS_NULL);
2651         requireNonNull(reducer, ERROR_REDUCER_NULL);
2652         requireNonNull(mapper, ERROR_MAPPER_NULL);
2653         return createBooleanBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2654     }
2655 
2656     /**
2657      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2658      *
2659      @param items    the observable map.
2660      @param supplier a {@code Supplier} whose result is returned if no value is present.
2661      @param mapper   a non-interfering, stateless function to apply to each value.
2662      @param reducer  an associative, non-interfering, stateless function for combining two values.
2663      *
2664      @return a boolean binding
2665      */
2666     @Nonnull
2667     public static <K, V> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Boolean> supplier, @Nonnull final Function<? super V, Boolean> mapper, @Nonnull final BinaryOperator<Boolean> reducer) {
2668         requireNonNull(items, ERROR_ITEMS_NULL);
2669         requireNonNull(reducer, ERROR_REDUCER_NULL);
2670         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2671         requireNonNull(mapper, ERROR_MAPPER_NULL);
2672         return createBooleanBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2673     }
2674 
2675     /**
2676      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2677      *
2678      @param items        the observable map.
2679      @param defaultValue the value to be returned if there is no value present, may be null.
2680      @param mapper       a non-interfering, stateless function to apply to each value.
2681      @param reducer      an associative, non-interfering, stateless function for combining two values.
2682      *
2683      @return a boolean binding
2684      */
2685     @Nonnull
2686     public static <K, V> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Boolean defaultValue, @Nonnull final ObservableValue<Function<? super V, Boolean>> mapper, @Nonnull final ObservableValue<BinaryOperator<Boolean>> reducer) {
2687         requireNonNull(reducer, ERROR_REDUCER_NULL);
2688         requireNonNull(mapper, ERROR_MAPPER_NULL);
2689         return createBooleanBinding(() -> {
2690             BinaryOperator<Boolean> reducerValue = reducer.getValue();
2691             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2692             final Function<? super V, Boolean> mapperValue = mapper.getValue();
2693             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2694             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2695         }, items, reducer, mapper);
2696     }
2697 
2698     /**
2699      * Returns a boolean binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2700      *
2701      @param items    the observable map.
2702      @param supplier a {@code Supplier} whose result is returned if no value is present.
2703      @param mapper   a non-interfering, stateless function to apply to each value.
2704      @param reducer  an associative, non-interfering, stateless function for combining two values.
2705      *
2706      @return a boolean binding
2707      */
2708     @Nonnull
2709     public static <K, V> BooleanBinding mapToBooleanThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Boolean> supplier, @Nonnull final ObservableValue<Function<? super V, Boolean>> mapper, @Nonnull final ObservableValue<BinaryOperator<Boolean>> reducer) {
2710         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2711         requireNonNull(reducer, ERROR_REDUCER_NULL);
2712         requireNonNull(mapper, ERROR_MAPPER_NULL);
2713         return createBooleanBinding(() -> {
2714             BinaryOperator<Boolean> reducerValue = reducer.getValue();
2715             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2716             final Function<? super V, Boolean> mapperValue = mapper.getValue();
2717             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2718             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2719         }, items, reducer, mapper);
2720     }
2721 
2722     /**
2723      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2724      *
2725      @param items        the observable list of elements.
2726      @param defaultValue the value to be returned if there is no value present, may be null.
2727      @param mapper       a non-interfering, stateless function to apply to each element.
2728      @param reducer      an associative, non-interfering, stateless function for combining two values.
2729      *
2730      @return an integer binding
2731      */
2732     @Nonnull
2733     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Integer defaultValue, @Nonnull final Function<? super T, Integer> mapper, @Nonnull final BinaryOperator<Integer> reducer) {
2734         requireNonNull(items, ERROR_ITEMS_NULL);
2735         requireNonNull(reducer, ERROR_REDUCER_NULL);
2736         requireNonNull(mapper, ERROR_MAPPER_NULL);
2737         return createIntegerBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2738     }
2739 
2740     /**
2741      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2742      *
2743      @param items    the observable list of elements.
2744      @param supplier a {@code Supplier} whose result is returned if no value is present.
2745      @param mapper   a non-interfering, stateless function to apply to each element.
2746      @param reducer  an associative, non-interfering, stateless function for combining two values.
2747      *
2748      @return an integer binding
2749      */
2750     @Nonnull
2751     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Integer> supplier, @Nonnull final Function<? super T, Integer> mapper, @Nonnull final BinaryOperator<Integer> reducer) {
2752         requireNonNull(items, ERROR_ITEMS_NULL);
2753         requireNonNull(reducer, ERROR_REDUCER_NULL);
2754         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2755         requireNonNull(mapper, ERROR_MAPPER_NULL);
2756         return createIntegerBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2757     }
2758 
2759     /**
2760      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2761      *
2762      @param items        the observable list of elements.
2763      @param defaultValue the value to be returned if there is no value present, may be null.
2764      @param mapper       a non-interfering, stateless function to apply to each element.
2765      @param reducer      an associative, non-interfering, stateless function for combining two values.
2766      *
2767      @return an integer binding
2768      */
2769     @Nonnull
2770     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Integer defaultValue, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper, @Nonnull final ObservableValue<BinaryOperator<Integer>> reducer) {
2771         requireNonNull(reducer, ERROR_REDUCER_NULL);
2772         requireNonNull(mapper, ERROR_MAPPER_NULL);
2773         return createIntegerBinding(() -> {
2774             BinaryOperator<Integer> reducerValue = reducer.getValue();
2775             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2776             final Function<? super T, Integer> mapperValue = mapper.getValue();
2777             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2778             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2779         }, items, reducer, mapper);
2780     }
2781 
2782     /**
2783      * Returns an integer binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2784      *
2785      @param items    the observable list of elements.
2786      @param supplier a {@code Supplier} whose result is returned if no value is present.
2787      @param mapper   a non-interfering, stateless function to apply to each element.
2788      @param reducer  an associative, non-interfering, stateless function for combining two values.
2789      *
2790      @return an integer binding
2791      */
2792     @Nonnull
2793     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Integer> supplier, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper, @Nonnull final ObservableValue<BinaryOperator<Integer>> reducer) {
2794         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2795         requireNonNull(reducer, ERROR_REDUCER_NULL);
2796         requireNonNull(mapper, ERROR_MAPPER_NULL);
2797         return createIntegerBinding(() -> {
2798             BinaryOperator<Integer> reducerValue = reducer.getValue();
2799             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2800             final Function<? super T, Integer> mapperValue = mapper.getValue();
2801             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2802             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2803         }, items, reducer, mapper);
2804     }
2805 
2806     /**
2807      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2808      *
2809      @param items        the observable set of elements.
2810      @param defaultValue the value to be returned if there is no value present, may be null.
2811      @param mapper       a non-interfering, stateless function to apply to each element.
2812      @param reducer      an associative, non-interfering, stateless function for combining two values.
2813      *
2814      @return an integer binding
2815      */
2816     @Nonnull
2817     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Integer defaultValue, @Nonnull final Function<? super T, Integer> mapper, @Nonnull final BinaryOperator<Integer> reducer) {
2818         requireNonNull(items, ERROR_ITEMS_NULL);
2819         requireNonNull(reducer, ERROR_REDUCER_NULL);
2820         return createIntegerBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2821     }
2822 
2823     /**
2824      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2825      *
2826      @param items    the observable set of elements.
2827      @param supplier a {@code Supplier} whose result is returned if no value is present.
2828      @param mapper   a non-interfering, stateless function to apply to each element.
2829      @param reducer  an associative, non-interfering, stateless function for combining two values.
2830      *
2831      @return an integer binding
2832      */
2833     @Nonnull
2834     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Integer> supplier, @Nonnull final Function<? super T, Integer> mapper, @Nonnull final BinaryOperator<Integer> reducer) {
2835         requireNonNull(items, ERROR_ITEMS_NULL);
2836         requireNonNull(reducer, ERROR_REDUCER_NULL);
2837         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2838         requireNonNull(mapper, ERROR_MAPPER_NULL);
2839         return createIntegerBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2840     }
2841 
2842     /**
2843      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2844      *
2845      @param items        the observable set of elements.
2846      @param defaultValue the value to be returned if there is no value present, may be null.
2847      @param mapper       a non-interfering, stateless function to apply to each element.
2848      @param reducer      an associative, non-interfering, stateless function for combining two values.
2849      *
2850      @return an integer binding
2851      */
2852     @Nonnull
2853     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Integer defaultValue, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper, @Nonnull final ObservableValue<BinaryOperator<Integer>> reducer) {
2854         requireNonNull(reducer, ERROR_REDUCER_NULL);
2855         requireNonNull(mapper, ERROR_MAPPER_NULL);
2856         return createIntegerBinding(() -> {
2857             BinaryOperator<Integer> reducerValue = reducer.getValue();
2858             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2859             final Function<? super T, Integer> mapperValue = mapper.getValue();
2860             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2861             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2862         }, items, reducer, mapper);
2863     }
2864 
2865     /**
2866      * Returns an integer binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
2867      *
2868      @param items    the observable set of elements.
2869      @param supplier a {@code Supplier} whose result is returned if no value is present.
2870      @param mapper   a non-interfering, stateless function to apply to each element.
2871      @param reducer  an associative, non-interfering, stateless function for combining two values.
2872      *
2873      @return an integer binding
2874      */
2875     @Nonnull
2876     public static <T> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Integer> supplier, @Nonnull final ObservableValue<Function<? super T, Integer>> mapper, @Nonnull final ObservableValue<BinaryOperator<Integer>> reducer) {
2877         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2878         requireNonNull(reducer, ERROR_REDUCER_NULL);
2879         requireNonNull(mapper, ERROR_MAPPER_NULL);
2880         return createIntegerBinding(() -> {
2881             BinaryOperator<Integer> reducerValue = reducer.getValue();
2882             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2883             final Function<? super T, Integer> mapperValue = mapper.getValue();
2884             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2885             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2886         }, items, reducer, mapper);
2887     }
2888 
2889     /**
2890      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2891      *
2892      @param items        the observable map.
2893      @param defaultValue the value to be returned if there is no value present, may be null.
2894      @param mapper       a non-interfering, stateless function to apply to each value.
2895      @param reducer      an associative, non-interfering, stateless function for combining two values.
2896      *
2897      @return an integer binding
2898      */
2899     @Nonnull
2900     public static <K, V> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Integer defaultValue, @Nonnull final Function<? super V, Integer> mapper, @Nonnull final BinaryOperator<Integer> reducer) {
2901         requireNonNull(items, ERROR_ITEMS_NULL);
2902         requireNonNull(reducer, ERROR_REDUCER_NULL);
2903         requireNonNull(mapper, ERROR_MAPPER_NULL);
2904         return createIntegerBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2905     }
2906 
2907     /**
2908      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2909      *
2910      @param items    the observable map.
2911      @param supplier a {@code Supplier} whose result is returned if no value is present.
2912      @param mapper   a non-interfering, stateless function to apply to each value.
2913      @param reducer  an associative, non-interfering, stateless function for combining two values.
2914      *
2915      @return an integer binding
2916      */
2917     @Nonnull
2918     public static <K, V> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Integer> supplier, @Nonnull final Function<? super V, Integer> mapper, @Nonnull final BinaryOperator<Integer> reducer) {
2919         requireNonNull(items, ERROR_ITEMS_NULL);
2920         requireNonNull(reducer, ERROR_REDUCER_NULL);
2921         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2922         requireNonNull(mapper, ERROR_MAPPER_NULL);
2923         return createIntegerBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
2924     }
2925 
2926     /**
2927      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2928      *
2929      @param items        the observable map.
2930      @param defaultValue the value to be returned if there is no value present, may be null.
2931      @param mapper       a non-interfering, stateless function to apply to each value.
2932      @param reducer      an associative, non-interfering, stateless function for combining two values.
2933      *
2934      @return an integer binding
2935      */
2936     @Nonnull
2937     public static <K, V> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Integer defaultValue, @Nonnull final ObservableValue<Function<? super V, Integer>> mapper, @Nonnull final ObservableValue<BinaryOperator<Integer>> reducer) {
2938         requireNonNull(reducer, ERROR_REDUCER_NULL);
2939         requireNonNull(mapper, ERROR_MAPPER_NULL);
2940         return createIntegerBinding(() -> {
2941             BinaryOperator<Integer> reducerValue = reducer.getValue();
2942             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2943             final Function<? super V, Integer> mapperValue = mapper.getValue();
2944             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2945             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
2946         }, items, reducer, mapper);
2947     }
2948 
2949     /**
2950      * Returns an integer binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
2951      *
2952      @param items    the observable map.
2953      @param supplier a {@code Supplier} whose result is returned if no value is present.
2954      @param mapper   a non-interfering, stateless function to apply to each value.
2955      @param reducer  an associative, non-interfering, stateless function for combining two values.
2956      *
2957      @return an integer binding
2958      */
2959     @Nonnull
2960     public static <K, V> IntegerBinding mapToIntegerThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Integer> supplier, @Nonnull final ObservableValue<Function<? super V, Integer>> mapper, @Nonnull final ObservableValue<BinaryOperator<Integer>> reducer) {
2961         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
2962         requireNonNull(reducer, ERROR_REDUCER_NULL);
2963         requireNonNull(mapper, ERROR_MAPPER_NULL);
2964         return createIntegerBinding(() -> {
2965             BinaryOperator<Integer> reducerValue = reducer.getValue();
2966             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
2967             final Function<? super V, Integer> mapperValue = mapper.getValue();
2968             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
2969             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
2970         }, items, reducer, mapper);
2971     }
2972 
2973     /**
2974      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2975      *
2976      @param items        the observable list of elements.
2977      @param defaultValue the value to be returned if there is no value present, may be null.
2978      @param mapper       a non-interfering, stateless function to apply to each element.
2979      @param reducer      an associative, non-interfering, stateless function for combining two values.
2980      *
2981      @return a long binding
2982      */
2983     @Nonnull
2984     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Long defaultValue, @Nonnull final Function<? super T, Long> mapper, @Nonnull final BinaryOperator<Long> reducer) {
2985         requireNonNull(items, ERROR_ITEMS_NULL);
2986         requireNonNull(reducer, ERROR_REDUCER_NULL);
2987         requireNonNull(mapper, ERROR_MAPPER_NULL);
2988         return createLongBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
2989     }
2990 
2991     /**
2992      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
2993      *
2994      @param items    the observable list of elements.
2995      @param supplier a {@code Supplier} whose result is returned if no value is present.
2996      @param mapper   a non-interfering, stateless function to apply to each element.
2997      @param reducer  an associative, non-interfering, stateless function for combining two values.
2998      *
2999      @return a long binding
3000      */
3001     @Nonnull
3002     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Long> supplier, @Nonnull final Function<? super T, Long> mapper, @Nonnull final BinaryOperator<Long> reducer) {
3003         requireNonNull(items, ERROR_ITEMS_NULL);
3004         requireNonNull(reducer, ERROR_REDUCER_NULL);
3005         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3006         requireNonNull(mapper, ERROR_MAPPER_NULL);
3007         return createLongBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3008     }
3009 
3010     /**
3011      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3012      *
3013      @param items        the observable list of elements.
3014      @param defaultValue the value to be returned if there is no value present, may be null.
3015      @param mapper       a non-interfering, stateless function to apply to each element.
3016      @param reducer      an associative, non-interfering, stateless function for combining two values.
3017      *
3018      @return a long binding
3019      */
3020     @Nonnull
3021     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Long defaultValue, @Nonnull final ObservableValue<Function<? super T, Long>> mapper, @Nonnull final ObservableValue<BinaryOperator<Long>> reducer) {
3022         requireNonNull(reducer, ERROR_REDUCER_NULL);
3023         requireNonNull(mapper, ERROR_MAPPER_NULL);
3024         return createLongBinding(() -> {
3025             BinaryOperator<Long> reducerValue = reducer.getValue();
3026             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3027             final Function<? super T, Long> mapperValue = mapper.getValue();
3028             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3029             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3030         }, items, reducer, mapper);
3031     }
3032 
3033     /**
3034      * Returns a long binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3035      *
3036      @param items    the observable list of elements.
3037      @param supplier a {@code Supplier} whose result is returned if no value is present.
3038      @param mapper   a non-interfering, stateless function to apply to each element.
3039      @param reducer  an associative, non-interfering, stateless function for combining two values.
3040      *
3041      @return a long binding
3042      */
3043     @Nonnull
3044     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Long> supplier, @Nonnull final ObservableValue<Function<? super T, Long>> mapper, @Nonnull final ObservableValue<BinaryOperator<Long>> reducer) {
3045         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3046         requireNonNull(reducer, ERROR_REDUCER_NULL);
3047         requireNonNull(mapper, ERROR_MAPPER_NULL);
3048         return createLongBinding(() -> {
3049             BinaryOperator<Long> reducerValue = reducer.getValue();
3050             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3051             final Function<? super T, Long> mapperValue = mapper.getValue();
3052             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3053             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3054         }, items, reducer, mapper);
3055     }
3056 
3057     /**
3058      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3059      *
3060      @param items        the observable set of elements.
3061      @param defaultValue the value to be returned if there is no value present, may be null.
3062      @param mapper       a non-interfering, stateless function to apply to each element.
3063      @param reducer      an associative, non-interfering, stateless function for combining two values.
3064      *
3065      @return a long binding
3066      */
3067     @Nonnull
3068     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Long defaultValue, @Nonnull final Function<? super T, Long> mapper, @Nonnull final BinaryOperator<Long> reducer) {
3069         requireNonNull(items, ERROR_ITEMS_NULL);
3070         requireNonNull(reducer, ERROR_REDUCER_NULL);
3071         return createLongBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3072     }
3073 
3074     /**
3075      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3076      *
3077      @param items    the observable set of elements.
3078      @param supplier a {@code Supplier} whose result is returned if no value is present.
3079      @param mapper   a non-interfering, stateless function to apply to each element.
3080      @param reducer  an associative, non-interfering, stateless function for combining two values.
3081      *
3082      @return a long binding
3083      */
3084     @Nonnull
3085     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Long> supplier, @Nonnull final Function<? super T, Long> mapper, @Nonnull final BinaryOperator<Long> reducer) {
3086         requireNonNull(items, ERROR_ITEMS_NULL);
3087         requireNonNull(reducer, ERROR_REDUCER_NULL);
3088         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3089         requireNonNull(mapper, ERROR_MAPPER_NULL);
3090         return createLongBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3091     }
3092 
3093     /**
3094      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3095      *
3096      @param items        the observable set of elements.
3097      @param defaultValue the value to be returned if there is no value present, may be null.
3098      @param mapper       a non-interfering, stateless function to apply to each element.
3099      @param reducer      an associative, non-interfering, stateless function for combining two values.
3100      *
3101      @return a long binding
3102      */
3103     @Nonnull
3104     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Long defaultValue, @Nonnull final ObservableValue<Function<? super T, Long>> mapper, @Nonnull final ObservableValue<BinaryOperator<Long>> reducer) {
3105         requireNonNull(reducer, ERROR_REDUCER_NULL);
3106         requireNonNull(mapper, ERROR_MAPPER_NULL);
3107         return createLongBinding(() -> {
3108             BinaryOperator<Long> reducerValue = reducer.getValue();
3109             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3110             final Function<? super T, Long> mapperValue = mapper.getValue();
3111             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3112             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3113         }, items, reducer, mapper);
3114     }
3115 
3116     /**
3117      * Returns a long binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3118      *
3119      @param items    the observable set of elements.
3120      @param supplier a {@code Supplier} whose result is returned if no value is present.
3121      @param mapper   a non-interfering, stateless function to apply to each element.
3122      @param reducer  an associative, non-interfering, stateless function for combining two values.
3123      *
3124      @return a long binding
3125      */
3126     @Nonnull
3127     public static <T> LongBinding mapToLongThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Long> supplier, @Nonnull final ObservableValue<Function<? super T, Long>> mapper, @Nonnull final ObservableValue<BinaryOperator<Long>> reducer) {
3128         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3129         requireNonNull(reducer, ERROR_REDUCER_NULL);
3130         requireNonNull(mapper, ERROR_MAPPER_NULL);
3131         return createLongBinding(() -> {
3132             BinaryOperator<Long> reducerValue = reducer.getValue();
3133             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3134             final Function<? super T, Long> mapperValue = mapper.getValue();
3135             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3136             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3137         }, items, reducer, mapper);
3138     }
3139 
3140     /**
3141      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3142      *
3143      @param items        the observable map.
3144      @param defaultValue the value to be returned if there is no value present, may be null.
3145      @param mapper       a non-interfering, stateless function to apply to each value.
3146      @param reducer      an associative, non-interfering, stateless function for combining two values.
3147      *
3148      @return a long binding
3149      */
3150     @Nonnull
3151     public static <K, V> LongBinding mapToLongThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Long defaultValue, @Nonnull final Function<? super V, Long> mapper, @Nonnull final BinaryOperator<Long> reducer) {
3152         requireNonNull(items, ERROR_ITEMS_NULL);
3153         requireNonNull(reducer, ERROR_REDUCER_NULL);
3154         requireNonNull(mapper, ERROR_MAPPER_NULL);
3155         return createLongBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3156     }
3157 
3158     /**
3159      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3160      *
3161      @param items    the observable map.
3162      @param supplier a {@code Supplier} whose result is returned if no value is present.
3163      @param mapper   a non-interfering, stateless function to apply to each value.
3164      @param reducer  an associative, non-interfering, stateless function for combining two values.
3165      *
3166      @return a long binding
3167      */
3168     @Nonnull
3169     public static <K, V> LongBinding mapToLongThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Long> supplier, @Nonnull final Function<? super V, Long> mapper, @Nonnull final BinaryOperator<Long> reducer) {
3170         requireNonNull(items, ERROR_ITEMS_NULL);
3171         requireNonNull(reducer, ERROR_REDUCER_NULL);
3172         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3173         requireNonNull(mapper, ERROR_MAPPER_NULL);
3174         return createLongBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3175     }
3176 
3177     /**
3178      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3179      *
3180      @param items        the observable map.
3181      @param defaultValue the value to be returned if there is no value present, may be null.
3182      @param mapper       a non-interfering, stateless function to apply to each value.
3183      @param reducer      an associative, non-interfering, stateless function for combining two values.
3184      *
3185      @return a long binding
3186      */
3187     @Nonnull
3188     public static <K, V> LongBinding mapToLongThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Long defaultValue, @Nonnull final ObservableValue<Function<? super V, Long>> mapper, @Nonnull final ObservableValue<BinaryOperator<Long>> reducer) {
3189         requireNonNull(reducer, ERROR_REDUCER_NULL);
3190         requireNonNull(mapper, ERROR_MAPPER_NULL);
3191         return createLongBinding(() -> {
3192             BinaryOperator<Long> reducerValue = reducer.getValue();
3193             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3194             final Function<? super V, Long> mapperValue = mapper.getValue();
3195             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3196             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3197         }, items, reducer, mapper);
3198     }
3199 
3200     /**
3201      * Returns a long binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3202      *
3203      @param items    the observable map.
3204      @param supplier a {@code Supplier} whose result is returned if no value is present.
3205      @param mapper   a non-interfering, stateless function to apply to each value.
3206      @param reducer  an associative, non-interfering, stateless function for combining two values.
3207      *
3208      @return a long binding
3209      */
3210     @Nonnull
3211     public static <K, V> LongBinding mapToLongThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Long> supplier, @Nonnull final ObservableValue<Function<? super V, Long>> mapper, @Nonnull final ObservableValue<BinaryOperator<Long>> reducer) {
3212         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3213         requireNonNull(reducer, ERROR_REDUCER_NULL);
3214         requireNonNull(mapper, ERROR_MAPPER_NULL);
3215         return createLongBinding(() -> {
3216             BinaryOperator<Long> reducerValue = reducer.getValue();
3217             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3218             final Function<? super V, Long> mapperValue = mapper.getValue();
3219             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3220             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3221         }, items, reducer, mapper);
3222     }
3223 
3224     /**
3225      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3226      *
3227      @param items        the observable list of elements.
3228      @param defaultValue the value to be returned if there is no value present, may be null.
3229      @param mapper       a non-interfering, stateless function to apply to each element.
3230      @param reducer      an associative, non-interfering, stateless function for combining two values.
3231      *
3232      @return a float binding
3233      */
3234     @Nonnull
3235     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Float defaultValue, @Nonnull final Function<? super T, Float> mapper, @Nonnull final BinaryOperator<Float> reducer) {
3236         requireNonNull(items, ERROR_ITEMS_NULL);
3237         requireNonNull(reducer, ERROR_REDUCER_NULL);
3238         requireNonNull(mapper, ERROR_MAPPER_NULL);
3239         return createFloatBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3240     }
3241 
3242     /**
3243      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3244      *
3245      @param items    the observable list of elements.
3246      @param supplier a {@code Supplier} whose result is returned if no value is present.
3247      @param mapper   a non-interfering, stateless function to apply to each element.
3248      @param reducer  an associative, non-interfering, stateless function for combining two values.
3249      *
3250      @return a float binding
3251      */
3252     @Nonnull
3253     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Float> supplier, @Nonnull final Function<? super T, Float> mapper, @Nonnull final BinaryOperator<Float> reducer) {
3254         requireNonNull(items, ERROR_ITEMS_NULL);
3255         requireNonNull(reducer, ERROR_REDUCER_NULL);
3256         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3257         requireNonNull(mapper, ERROR_MAPPER_NULL);
3258         return createFloatBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3259     }
3260 
3261     /**
3262      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3263      *
3264      @param items        the observable list of elements.
3265      @param defaultValue the value to be returned if there is no value present, may be null.
3266      @param mapper       a non-interfering, stateless function to apply to each element.
3267      @param reducer      an associative, non-interfering, stateless function for combining two values.
3268      *
3269      @return a float binding
3270      */
3271     @Nonnull
3272     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Float defaultValue, @Nonnull final ObservableValue<Function<? super T, Float>> mapper, @Nonnull final ObservableValue<BinaryOperator<Float>> reducer) {
3273         requireNonNull(reducer, ERROR_REDUCER_NULL);
3274         requireNonNull(mapper, ERROR_MAPPER_NULL);
3275         return createFloatBinding(() -> {
3276             BinaryOperator<Float> reducerValue = reducer.getValue();
3277             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3278             final Function<? super T, Float> mapperValue = mapper.getValue();
3279             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3280             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3281         }, items, reducer, mapper);
3282     }
3283 
3284     /**
3285      * Returns a float binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3286      *
3287      @param items    the observable list of elements.
3288      @param supplier a {@code Supplier} whose result is returned if no value is present.
3289      @param mapper   a non-interfering, stateless function to apply to each element.
3290      @param reducer  an associative, non-interfering, stateless function for combining two values.
3291      *
3292      @return a float binding
3293      */
3294     @Nonnull
3295     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Float> supplier, @Nonnull final ObservableValue<Function<? super T, Float>> mapper, @Nonnull final ObservableValue<BinaryOperator<Float>> reducer) {
3296         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3297         requireNonNull(reducer, ERROR_REDUCER_NULL);
3298         requireNonNull(mapper, ERROR_MAPPER_NULL);
3299         return createFloatBinding(() -> {
3300             BinaryOperator<Float> reducerValue = reducer.getValue();
3301             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3302             final Function<? super T, Float> mapperValue = mapper.getValue();
3303             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3304             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3305         }, items, reducer, mapper);
3306     }
3307 
3308     /**
3309      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3310      *
3311      @param items        the observable set of elements.
3312      @param defaultValue the value to be returned if there is no value present, may be null.
3313      @param mapper       a non-interfering, stateless function to apply to each element.
3314      @param reducer      an associative, non-interfering, stateless function for combining two values.
3315      *
3316      @return a float binding
3317      */
3318     @Nonnull
3319     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Float defaultValue, @Nonnull final Function<? super T, Float> mapper, @Nonnull final BinaryOperator<Float> reducer) {
3320         requireNonNull(items, ERROR_ITEMS_NULL);
3321         requireNonNull(reducer, ERROR_REDUCER_NULL);
3322         return createFloatBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3323     }
3324 
3325     /**
3326      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3327      *
3328      @param items    the observable set of elements.
3329      @param supplier a {@code Supplier} whose result is returned if no value is present.
3330      @param mapper   a non-interfering, stateless function to apply to each element.
3331      @param reducer  an associative, non-interfering, stateless function for combining two values.
3332      *
3333      @return a float binding
3334      */
3335     @Nonnull
3336     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Float> supplier, @Nonnull final Function<? super T, Float> mapper, @Nonnull final BinaryOperator<Float> reducer) {
3337         requireNonNull(items, ERROR_ITEMS_NULL);
3338         requireNonNull(reducer, ERROR_REDUCER_NULL);
3339         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3340         requireNonNull(mapper, ERROR_MAPPER_NULL);
3341         return createFloatBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3342     }
3343 
3344     /**
3345      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3346      *
3347      @param items        the observable set of elements.
3348      @param defaultValue the value to be returned if there is no value present, may be null.
3349      @param mapper       a non-interfering, stateless function to apply to each element.
3350      @param reducer      an associative, non-interfering, stateless function for combining two values.
3351      *
3352      @return a float binding
3353      */
3354     @Nonnull
3355     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Float defaultValue, @Nonnull final ObservableValue<Function<? super T, Float>> mapper, @Nonnull final ObservableValue<BinaryOperator<Float>> reducer) {
3356         requireNonNull(reducer, ERROR_REDUCER_NULL);
3357         requireNonNull(mapper, ERROR_MAPPER_NULL);
3358         return createFloatBinding(() -> {
3359             BinaryOperator<Float> reducerValue = reducer.getValue();
3360             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3361             final Function<? super T, Float> mapperValue = mapper.getValue();
3362             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3363             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3364         }, items, reducer, mapper);
3365     }
3366 
3367     /**
3368      * Returns a float binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3369      *
3370      @param items    the observable set of elements.
3371      @param supplier a {@code Supplier} whose result is returned if no value is present.
3372      @param mapper   a non-interfering, stateless function to apply to each element.
3373      @param reducer  an associative, non-interfering, stateless function for combining two values.
3374      *
3375      @return a float binding
3376      */
3377     @Nonnull
3378     public static <T> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Float> supplier, @Nonnull final ObservableValue<Function<? super T, Float>> mapper, @Nonnull final ObservableValue<BinaryOperator<Float>> reducer) {
3379         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3380         requireNonNull(reducer, ERROR_REDUCER_NULL);
3381         requireNonNull(mapper, ERROR_MAPPER_NULL);
3382         return createFloatBinding(() -> {
3383             BinaryOperator<Float> reducerValue = reducer.getValue();
3384             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3385             final Function<? super T, Float> mapperValue = mapper.getValue();
3386             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3387             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3388         }, items, reducer, mapper);
3389     }
3390 
3391     /**
3392      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3393      *
3394      @param items        the observable map.
3395      @param defaultValue the value to be returned if there is no value present, may be null.
3396      @param mapper       a non-interfering, stateless function to apply to each value.
3397      @param reducer      an associative, non-interfering, stateless function for combining two values.
3398      *
3399      @return a float binding
3400      */
3401     @Nonnull
3402     public static <K, V> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Float defaultValue, @Nonnull final Function<? super V, Float> mapper, @Nonnull final BinaryOperator<Float> reducer) {
3403         requireNonNull(items, ERROR_ITEMS_NULL);
3404         requireNonNull(reducer, ERROR_REDUCER_NULL);
3405         requireNonNull(mapper, ERROR_MAPPER_NULL);
3406         return createFloatBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3407     }
3408 
3409     /**
3410      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3411      *
3412      @param items    the observable map.
3413      @param supplier a {@code Supplier} whose result is returned if no value is present.
3414      @param mapper   a non-interfering, stateless function to apply to each value.
3415      @param reducer  an associative, non-interfering, stateless function for combining two values.
3416      *
3417      @return a float binding
3418      */
3419     @Nonnull
3420     public static <K, V> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Float> supplier, @Nonnull final Function<? super V, Float> mapper, @Nonnull final BinaryOperator<Float> reducer) {
3421         requireNonNull(items, ERROR_ITEMS_NULL);
3422         requireNonNull(reducer, ERROR_REDUCER_NULL);
3423         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3424         requireNonNull(mapper, ERROR_MAPPER_NULL);
3425         return createFloatBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3426     }
3427 
3428     /**
3429      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3430      *
3431      @param items        the observable map.
3432      @param defaultValue the value to be returned if there is no value present, may be null.
3433      @param mapper       a non-interfering, stateless function to apply to each value.
3434      @param reducer      an associative, non-interfering, stateless function for combining two values.
3435      *
3436      @return a float binding
3437      */
3438     @Nonnull
3439     public static <K, V> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Float defaultValue, @Nonnull final ObservableValue<Function<? super V, Float>> mapper, @Nonnull final ObservableValue<BinaryOperator<Float>> reducer) {
3440         requireNonNull(reducer, ERROR_REDUCER_NULL);
3441         requireNonNull(mapper, ERROR_MAPPER_NULL);
3442         return createFloatBinding(() -> {
3443             BinaryOperator<Float> reducerValue = reducer.getValue();
3444             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3445             final Function<? super V, Float> mapperValue = mapper.getValue();
3446             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3447             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3448         }, items, reducer, mapper);
3449     }
3450 
3451     /**
3452      * Returns a float binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3453      *
3454      @param items    the observable map.
3455      @param supplier a {@code Supplier} whose result is returned if no value is present.
3456      @param mapper   a non-interfering, stateless function to apply to each value.
3457      @param reducer  an associative, non-interfering, stateless function for combining two values.
3458      *
3459      @return a float binding
3460      */
3461     @Nonnull
3462     public static <K, V> FloatBinding mapToFloatThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Float> supplier, @Nonnull final ObservableValue<Function<? super V, Float>> mapper, @Nonnull final ObservableValue<BinaryOperator<Float>> reducer) {
3463         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3464         requireNonNull(reducer, ERROR_REDUCER_NULL);
3465         requireNonNull(mapper, ERROR_MAPPER_NULL);
3466         return createFloatBinding(() -> {
3467             BinaryOperator<Float> reducerValue = reducer.getValue();
3468             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3469             final Function<? super V, Float> mapperValue = mapper.getValue();
3470             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3471             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3472         }, items, reducer, mapper);
3473     }
3474 
3475     /**
3476      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3477      *
3478      @param items        the observable list of elements.
3479      @param defaultValue the value to be returned if there is no value present, may be null.
3480      @param mapper       a non-interfering, stateless function to apply to each element.
3481      @param reducer      an associative, non-interfering, stateless function for combining two values.
3482      *
3483      @return a double binding
3484      */
3485     @Nonnull
3486     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Double defaultValue, @Nonnull final Function<? super T, Double> mapper, @Nonnull final BinaryOperator<Double> reducer) {
3487         requireNonNull(items, ERROR_ITEMS_NULL);
3488         requireNonNull(reducer, ERROR_REDUCER_NULL);
3489         requireNonNull(mapper, ERROR_MAPPER_NULL);
3490         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3491     }
3492 
3493     /**
3494      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3495      *
3496      @param items    the observable list of elements.
3497      @param supplier a {@code Supplier} whose result is returned if no value is present.
3498      @param mapper   a non-interfering, stateless function to apply to each element.
3499      @param reducer  an associative, non-interfering, stateless function for combining two values.
3500      *
3501      @return a double binding
3502      */
3503     @Nonnull
3504     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Double> supplier, @Nonnull final Function<? super T, Double> mapper, @Nonnull final BinaryOperator<Double> reducer) {
3505         requireNonNull(items, ERROR_ITEMS_NULL);
3506         requireNonNull(reducer, ERROR_REDUCER_NULL);
3507         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3508         requireNonNull(mapper, ERROR_MAPPER_NULL);
3509         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3510     }
3511 
3512     /**
3513      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3514      *
3515      @param items        the observable list of elements.
3516      @param defaultValue the value to be returned if there is no value present, may be null.
3517      @param mapper       a non-interfering, stateless function to apply to each element.
3518      @param reducer      an associative, non-interfering, stateless function for combining two values.
3519      *
3520      @return a double binding
3521      */
3522     @Nonnull
3523     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Double defaultValue, @Nonnull final ObservableValue<Function<? super T, Double>> mapper, @Nonnull final ObservableValue<BinaryOperator<Double>> reducer) {
3524         requireNonNull(reducer, ERROR_REDUCER_NULL);
3525         requireNonNull(mapper, ERROR_MAPPER_NULL);
3526         return createDoubleBinding(() -> {
3527             BinaryOperator<Double> reducerValue = reducer.getValue();
3528             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3529             final Function<? super T, Double> mapperValue = mapper.getValue();
3530             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3531             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3532         }, items, reducer, mapper);
3533     }
3534 
3535     /**
3536      * Returns a double binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3537      *
3538      @param items    the observable list of elements.
3539      @param supplier a {@code Supplier} whose result is returned if no value is present.
3540      @param mapper   a non-interfering, stateless function to apply to each element.
3541      @param reducer  an associative, non-interfering, stateless function for combining two values.
3542      *
3543      @return a double binding
3544      */
3545     @Nonnull
3546     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Double> supplier, @Nonnull final ObservableValue<Function<? super T, Double>> mapper, @Nonnull final ObservableValue<BinaryOperator<Double>> reducer) {
3547         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3548         requireNonNull(reducer, ERROR_REDUCER_NULL);
3549         requireNonNull(mapper, ERROR_MAPPER_NULL);
3550         return createDoubleBinding(() -> {
3551             BinaryOperator<Double> reducerValue = reducer.getValue();
3552             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3553             final Function<? super T, Double> mapperValue = mapper.getValue();
3554             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3555             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3556         }, items, reducer, mapper);
3557     }
3558 
3559     /**
3560      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3561      *
3562      @param items        the observable set of elements.
3563      @param defaultValue the value to be returned if there is no value present, may be null.
3564      @param mapper       a non-interfering, stateless function to apply to each element.
3565      @param reducer      an associative, non-interfering, stateless function for combining two values.
3566      *
3567      @return a double binding
3568      */
3569     @Nonnull
3570     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Double defaultValue, @Nonnull final Function<? super T, Double> mapper, @Nonnull final BinaryOperator<Double> reducer) {
3571         requireNonNull(items, ERROR_ITEMS_NULL);
3572         requireNonNull(reducer, ERROR_REDUCER_NULL);
3573         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3574     }
3575 
3576     /**
3577      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3578      *
3579      @param items    the observable set of elements.
3580      @param supplier a {@code Supplier} whose result is returned if no value is present.
3581      @param mapper   a non-interfering, stateless function to apply to each element.
3582      @param reducer  an associative, non-interfering, stateless function for combining two values.
3583      *
3584      @return a double binding
3585      */
3586     @Nonnull
3587     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Double> supplier, @Nonnull final Function<? super T, Double> mapper, @Nonnull final BinaryOperator<Double> reducer) {
3588         requireNonNull(items, ERROR_ITEMS_NULL);
3589         requireNonNull(reducer, ERROR_REDUCER_NULL);
3590         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3591         requireNonNull(mapper, ERROR_MAPPER_NULL);
3592         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3593     }
3594 
3595     /**
3596      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3597      *
3598      @param items        the observable set of elements.
3599      @param defaultValue the value to be returned if there is no value present, may be null.
3600      @param mapper       a non-interfering, stateless function to apply to each element.
3601      @param reducer      an associative, non-interfering, stateless function for combining two values.
3602      *
3603      @return a double binding
3604      */
3605     @Nonnull
3606     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Double defaultValue, @Nonnull final ObservableValue<Function<? super T, Double>> mapper, @Nonnull final ObservableValue<BinaryOperator<Double>> reducer) {
3607         requireNonNull(reducer, ERROR_REDUCER_NULL);
3608         requireNonNull(mapper, ERROR_MAPPER_NULL);
3609         return createDoubleBinding(() -> {
3610             BinaryOperator<Double> reducerValue = reducer.getValue();
3611             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3612             final Function<? super T, Double> mapperValue = mapper.getValue();
3613             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3614             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3615         }, items, reducer, mapper);
3616     }
3617 
3618     /**
3619      * Returns a double binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3620      *
3621      @param items    the observable set of elements.
3622      @param supplier a {@code Supplier} whose result is returned if no value is present.
3623      @param mapper   a non-interfering, stateless function to apply to each element.
3624      @param reducer  an associative, non-interfering, stateless function for combining two values.
3625      *
3626      @return a double binding
3627      */
3628     @Nonnull
3629     public static <T> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Double> supplier, @Nonnull final ObservableValue<Function<? super T, Double>> mapper, @Nonnull final ObservableValue<BinaryOperator<Double>> reducer) {
3630         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3631         requireNonNull(reducer, ERROR_REDUCER_NULL);
3632         requireNonNull(mapper, ERROR_MAPPER_NULL);
3633         return createDoubleBinding(() -> {
3634             BinaryOperator<Double> reducerValue = reducer.getValue();
3635             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3636             final Function<? super T, Double> mapperValue = mapper.getValue();
3637             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3638             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3639         }, items, reducer, mapper);
3640     }
3641 
3642     /**
3643      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3644      *
3645      @param items        the observable map.
3646      @param defaultValue the value to be returned if there is no value present, may be null.
3647      @param mapper       a non-interfering, stateless function to apply to each value.
3648      @param reducer      an associative, non-interfering, stateless function for combining two values.
3649      *
3650      @return a double binding
3651      */
3652     @Nonnull
3653     public static <K, V> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Double defaultValue, @Nonnull final Function<? super V, Double> mapper, @Nonnull final BinaryOperator<Double> reducer) {
3654         requireNonNull(items, ERROR_ITEMS_NULL);
3655         requireNonNull(reducer, ERROR_REDUCER_NULL);
3656         requireNonNull(mapper, ERROR_MAPPER_NULL);
3657         return createDoubleBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3658     }
3659 
3660     /**
3661      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3662      *
3663      @param items    the observable map.
3664      @param supplier a {@code Supplier} whose result is returned if no value is present.
3665      @param mapper   a non-interfering, stateless function to apply to each value.
3666      @param reducer  an associative, non-interfering, stateless function for combining two values.
3667      *
3668      @return a double binding
3669      */
3670     @Nonnull
3671     public static <K, V> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Double> supplier, @Nonnull final Function<? super V, Double> mapper, @Nonnull final BinaryOperator<Double> reducer) {
3672         requireNonNull(items, ERROR_ITEMS_NULL);
3673         requireNonNull(reducer, ERROR_REDUCER_NULL);
3674         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3675         requireNonNull(mapper, ERROR_MAPPER_NULL);
3676         return createDoubleBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
3677     }
3678 
3679     /**
3680      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3681      *
3682      @param items        the observable map.
3683      @param defaultValue the value to be returned if there is no value present, may be null.
3684      @param mapper       a non-interfering, stateless function to apply to each value.
3685      @param reducer      an associative, non-interfering, stateless function for combining two values.
3686      *
3687      @return a double binding
3688      */
3689     @Nonnull
3690     public static <K, V> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Double defaultValue, @Nonnull final ObservableValue<Function<? super V, Double>> mapper, @Nonnull final ObservableValue<BinaryOperator<Double>> reducer) {
3691         requireNonNull(reducer, ERROR_REDUCER_NULL);
3692         requireNonNull(mapper, ERROR_MAPPER_NULL);
3693         return createDoubleBinding(() -> {
3694             BinaryOperator<Double> reducerValue = reducer.getValue();
3695             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3696             final Function<? super V, Double> mapperValue = mapper.getValue();
3697             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3698             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
3699         }, items, reducer, mapper);
3700     }
3701 
3702     /**
3703      * Returns a double binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3704      *
3705      @param items    the observable map.
3706      @param supplier a {@code Supplier} whose result is returned if no value is present.
3707      @param mapper   a non-interfering, stateless function to apply to each value.
3708      @param reducer  an associative, non-interfering, stateless function for combining two values.
3709      *
3710      @return a double binding
3711      */
3712     @Nonnull
3713     public static <K, V> DoubleBinding mapToDoubleThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Double> supplier, @Nonnull final ObservableValue<Function<? super V, Double>> mapper, @Nonnull final ObservableValue<BinaryOperator<Double>> reducer) {
3714         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3715         requireNonNull(reducer, ERROR_REDUCER_NULL);
3716         requireNonNull(mapper, ERROR_MAPPER_NULL);
3717         return createDoubleBinding(() -> {
3718             BinaryOperator<Double> reducerValue = reducer.getValue();
3719             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3720             final Function<? super V, Double> mapperValue = mapper.getValue();
3721             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3722             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
3723         }, items, reducer, mapper);
3724     }
3725 
3726     /**
3727      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3728      *
3729      @param items        the observable list of elements.
3730      @param defaultValue the value to be returned if there is no value present, may be null.
3731      @param mapper       a non-interfering, stateless function to apply to each element.
3732      @param reducer      an associative, non-interfering, stateless function for combining two values.
3733      *
3734      @return a number binding
3735      */
3736     @Nonnull
3737     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Number defaultValue, @Nonnull final Function<? super T, Number> mapper, @Nonnull final BinaryOperator<Number> reducer) {
3738         requireNonNull(items, ERROR_ITEMS_NULL);
3739         requireNonNull(reducer, ERROR_REDUCER_NULL);
3740         requireNonNull(mapper, ERROR_MAPPER_NULL);
3741         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue).doubleValue(), items);
3742     }
3743 
3744     /**
3745      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3746      *
3747      @param items    the observable list of elements.
3748      @param supplier a {@code Supplier} whose result is returned if no value is present.
3749      @param mapper   a non-interfering, stateless function to apply to each element.
3750      @param reducer  an associative, non-interfering, stateless function for combining two values.
3751      *
3752      @return a number binding
3753      */
3754     @Nonnull
3755     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Number> supplier, @Nonnull final Function<? super T, Number> mapper, @Nonnull final BinaryOperator<Number> reducer) {
3756         requireNonNull(items, ERROR_ITEMS_NULL);
3757         requireNonNull(reducer, ERROR_REDUCER_NULL);
3758         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3759         requireNonNull(mapper, ERROR_MAPPER_NULL);
3760         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier).doubleValue(), items);
3761     }
3762 
3763     /**
3764      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3765      *
3766      @param items        the observable list of elements.
3767      @param defaultValue the value to be returned if there is no value present, may be null.
3768      @param mapper       a non-interfering, stateless function to apply to each element.
3769      @param reducer      an associative, non-interfering, stateless function for combining two values.
3770      *
3771      @return a number binding
3772      */
3773     @Nonnull
3774     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableList<T> items, @Nullable final Number defaultValue, @Nonnull final ObservableValue<Function<? super T, Number>> mapper, @Nonnull final ObservableValue<BinaryOperator<Number>> reducer) {
3775         requireNonNull(reducer, ERROR_REDUCER_NULL);
3776         requireNonNull(mapper, ERROR_MAPPER_NULL);
3777         return createDoubleBinding(() -> {
3778             BinaryOperator<Number> reducerValue = reducer.getValue();
3779             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3780             final Function<? super T, Number> mapperValue = mapper.getValue();
3781             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3782             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue).doubleValue();
3783         }, items, reducer, mapper);
3784     }
3785 
3786     /**
3787      * Returns a number binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3788      *
3789      @param items    the observable list of elements.
3790      @param supplier a {@code Supplier} whose result is returned if no value is present.
3791      @param mapper   a non-interfering, stateless function to apply to each element.
3792      @param reducer  an associative, non-interfering, stateless function for combining two values.
3793      *
3794      @return a number binding
3795      */
3796     @Nonnull
3797     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<Number> supplier, @Nonnull final ObservableValue<Function<? super T, Number>> mapper, @Nonnull final ObservableValue<BinaryOperator<Number>> reducer) {
3798         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3799         requireNonNull(reducer, ERROR_REDUCER_NULL);
3800         requireNonNull(mapper, ERROR_MAPPER_NULL);
3801         return createDoubleBinding(() -> {
3802             BinaryOperator<Number> reducerValue = reducer.getValue();
3803             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3804             final Function<? super T, Number> mapperValue = mapper.getValue();
3805             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3806             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier).doubleValue();
3807         }, items, reducer, mapper);
3808     }
3809 
3810     /**
3811      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3812      *
3813      @param items        the observable set of elements.
3814      @param defaultValue the value to be returned if there is no value present, may be null.
3815      @param mapper       a non-interfering, stateless function to apply to each element.
3816      @param reducer      an associative, non-interfering, stateless function for combining two values.
3817      *
3818      @return a number binding
3819      */
3820     @Nonnull
3821     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Number defaultValue, @Nonnull final Function<? super T, Number> mapper, @Nonnull final BinaryOperator<Number> reducer) {
3822         requireNonNull(items, ERROR_ITEMS_NULL);
3823         requireNonNull(reducer, ERROR_REDUCER_NULL);
3824         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue).doubleValue(), items);
3825     }
3826 
3827     /**
3828      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3829      *
3830      @param items    the observable set of elements.
3831      @param supplier a {@code Supplier} whose result is returned if no value is present.
3832      @param mapper   a non-interfering, stateless function to apply to each element.
3833      @param reducer  an associative, non-interfering, stateless function for combining two values.
3834      *
3835      @return a number binding
3836      */
3837     @Nonnull
3838     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Number> supplier, @Nonnull final Function<? super T, Number> mapper, @Nonnull final BinaryOperator<Number> reducer) {
3839         requireNonNull(items, ERROR_ITEMS_NULL);
3840         requireNonNull(reducer, ERROR_REDUCER_NULL);
3841         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3842         requireNonNull(mapper, ERROR_MAPPER_NULL);
3843         return createDoubleBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier).doubleValue(), items);
3844     }
3845 
3846     /**
3847      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3848      *
3849      @param items        the observable set of elements.
3850      @param defaultValue the value to be returned if there is no value present, may be null.
3851      @param mapper       a non-interfering, stateless function to apply to each element.
3852      @param reducer      an associative, non-interfering, stateless function for combining two values.
3853      *
3854      @return a number binding
3855      */
3856     @Nonnull
3857     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final Number defaultValue, @Nonnull final ObservableValue<Function<? super T, Number>> mapper, @Nonnull final ObservableValue<BinaryOperator<Number>> reducer) {
3858         requireNonNull(reducer, ERROR_REDUCER_NULL);
3859         requireNonNull(mapper, ERROR_MAPPER_NULL);
3860         return createDoubleBinding(() -> {
3861             BinaryOperator<Number> reducerValue = reducer.getValue();
3862             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3863             final Function<? super T, Number> mapperValue = mapper.getValue();
3864             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3865             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue).doubleValue();
3866         }, items, reducer, mapper);
3867     }
3868 
3869     /**
3870      * Returns a number binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
3871      *
3872      @param items    the observable set of elements.
3873      @param supplier a {@code Supplier} whose result is returned if no value is present.
3874      @param mapper   a non-interfering, stateless function to apply to each element.
3875      @param reducer  an associative, non-interfering, stateless function for combining two values.
3876      *
3877      @return a number binding
3878      */
3879     @Nonnull
3880     public static <T> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<Number> supplier, @Nonnull final ObservableValue<Function<? super T, Number>> mapper, @Nonnull final ObservableValue<BinaryOperator<Number>> reducer) {
3881         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3882         requireNonNull(reducer, ERROR_REDUCER_NULL);
3883         requireNonNull(mapper, ERROR_MAPPER_NULL);
3884         return createDoubleBinding(() -> {
3885             BinaryOperator<Number> reducerValue = reducer.getValue();
3886             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3887             final Function<? super T, Number> mapperValue = mapper.getValue();
3888             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3889             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier).doubleValue();
3890         }, items, reducer, mapper);
3891     }
3892 
3893     /**
3894      * Returns a number binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3895      *
3896      @param items        the observable map.
3897      @param defaultValue the value to be returned if there is no value present, may be null.
3898      @param mapper       a non-interfering, stateless function to apply to each value.
3899      @param reducer      an associative, non-interfering, stateless function for combining two values.
3900      *
3901      @return a number binding
3902      */
3903     @Nonnull
3904     public static <K, V> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Number defaultValue, @Nonnull final Function<? super V, Number> mapper, @Nonnull final BinaryOperator<Number> reducer) {
3905         requireNonNull(items, ERROR_ITEMS_NULL);
3906         requireNonNull(reducer, ERROR_REDUCER_NULL);
3907         requireNonNull(mapper, ERROR_MAPPER_NULL);
3908         return createDoubleBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue).doubleValue(), items);
3909     }
3910 
3911     /**
3912      * Returns a number binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3913      *
3914      @param items    the observable map.
3915      @param supplier a {@code Supplier} whose result is returned if no value is present.
3916      @param mapper   a non-interfering, stateless function to apply to each value.
3917      @param reducer  an associative, non-interfering, stateless function for combining two values.
3918      *
3919      @return a number binding
3920      */
3921     @Nonnull
3922     public static <K, V> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Number> supplier, @Nonnull final Function<? super V, Number> mapper, @Nonnull final BinaryOperator<Number> reducer) {
3923         requireNonNull(items, ERROR_ITEMS_NULL);
3924         requireNonNull(reducer, ERROR_REDUCER_NULL);
3925         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3926         requireNonNull(mapper, ERROR_MAPPER_NULL);
3927         return createDoubleBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier).doubleValue(), items);
3928     }
3929 
3930     /**
3931      * Returns a number binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3932      *
3933      @param items        the observable map.
3934      @param defaultValue the value to be returned if there is no value present, may be null.
3935      @param mapper       a non-interfering, stateless function to apply to each value.
3936      @param reducer      an associative, non-interfering, stateless function for combining two values.
3937      *
3938      @return a number binding
3939      */
3940     @Nonnull
3941     public static <K, V> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final Number defaultValue, @Nonnull final ObservableValue<Function<? super V, Number>> mapper, @Nonnull final ObservableValue<BinaryOperator<Number>> reducer) {
3942         requireNonNull(reducer, ERROR_REDUCER_NULL);
3943         requireNonNull(mapper, ERROR_MAPPER_NULL);
3944         return createDoubleBinding(() -> {
3945             BinaryOperator<Number> reducerValue = reducer.getValue();
3946             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3947             final Function<? super V, Number> mapperValue = mapper.getValue();
3948             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3949             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue).doubleValue();
3950         }, items, reducer, mapper);
3951     }
3952 
3953     /**
3954      * Returns a number binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
3955      *
3956      @param items    the observable map.
3957      @param supplier a {@code Supplier} whose result is returned if no value is present.
3958      @param mapper   a non-interfering, stateless function to apply to each value.
3959      @param reducer  an associative, non-interfering, stateless function for combining two values.
3960      *
3961      @return a number binding
3962      */
3963     @Nonnull
3964     public static <K, V> NumberBinding mapToNumberThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<Number> supplier, @Nonnull final ObservableValue<Function<? super V, Number>> mapper, @Nonnull final ObservableValue<BinaryOperator<Number>> reducer) {
3965         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
3966         requireNonNull(reducer, ERROR_REDUCER_NULL);
3967         requireNonNull(mapper, ERROR_MAPPER_NULL);
3968         return createDoubleBinding(() -> {
3969             BinaryOperator<Number> reducerValue = reducer.getValue();
3970             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
3971             final Function<? super V, Number> mapperValue = mapper.getValue();
3972             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
3973             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier).doubleValue();
3974         }, items, reducer, mapper);
3975     }
3976 
3977     /**
3978      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3979      *
3980      @param items        the observable list of elements.
3981      @param defaultValue the value to be returned if there is no value present, may be null.
3982      @param mapper       a non-interfering, stateless function to apply to each element.
3983      @param reducer      an associative, non-interfering, stateless function for combining two values.
3984      *
3985      @return a string binding
3986      */
3987     @Nonnull
3988     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableList<T> items, @Nullable final String defaultValue, @Nonnull final Function<? super T, String> mapper, @Nonnull final BinaryOperator<String> reducer) {
3989         requireNonNull(items, ERROR_ITEMS_NULL);
3990         requireNonNull(reducer, ERROR_REDUCER_NULL);
3991         requireNonNull(mapper, ERROR_MAPPER_NULL);
3992         return createStringBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
3993     }
3994 
3995     /**
3996      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
3997      *
3998      @param items    the observable list of elements.
3999      @param supplier a {@code Supplier} whose result is returned if no value is present.
4000      @param mapper   a non-interfering, stateless function to apply to each element.
4001      @param reducer  an associative, non-interfering, stateless function for combining two values.
4002      *
4003      @return a string binding
4004      */
4005     @Nonnull
4006     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<String> supplier, @Nonnull final Function<? super T, String> mapper, @Nonnull final BinaryOperator<String> reducer) {
4007         requireNonNull(items, ERROR_ITEMS_NULL);
4008         requireNonNull(reducer, ERROR_REDUCER_NULL);
4009         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
4010         requireNonNull(mapper, ERROR_MAPPER_NULL);
4011         return createStringBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
4012     }
4013 
4014     /**
4015      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
4016      *
4017      @param items        the observable list of elements.
4018      @param defaultValue the value to be returned if there is no value present, may be null.
4019      @param mapper       a non-interfering, stateless function to apply to each element.
4020      @param reducer      an associative, non-interfering, stateless function for combining two values.
4021      *
4022      @return a string binding
4023      */
4024     @Nonnull
4025     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableList<T> items, @Nullable final String defaultValue, @Nonnull final ObservableValue<Function<? super T, String>> mapper, @Nonnull final ObservableValue<BinaryOperator<String>> reducer) {
4026         requireNonNull(reducer, ERROR_REDUCER_NULL);
4027         requireNonNull(mapper, ERROR_MAPPER_NULL);
4028         return createStringBinding(() -> {
4029             BinaryOperator<String> reducerValue = reducer.getValue();
4030             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
4031             final Function<? super T, String> mapperValue = mapper.getValue();
4032             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
4033             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
4034         }, items, reducer, mapper);
4035     }
4036 
4037     /**
4038      * Returns a string binding whose value is the reduction of all elements in the list. The mapper function is applied to each element before reduction.
4039      *
4040      @param items    the observable list of elements.
4041      @param supplier a {@code Supplier} whose result is returned if no value is present.
4042      @param mapper   a non-interfering, stateless function to apply to each element.
4043      @param reducer  an associative, non-interfering, stateless function for combining two values.
4044      *
4045      @return a string binding
4046      */
4047     @Nonnull
4048     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableList<T> items, @Nonnull final Supplier<String> supplier, @Nonnull final ObservableValue<Function<? super T, String>> mapper, @Nonnull final ObservableValue<BinaryOperator<String>> reducer) {
4049         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
4050         requireNonNull(reducer, ERROR_REDUCER_NULL);
4051         requireNonNull(mapper, ERROR_MAPPER_NULL);
4052         return createStringBinding(() -> {
4053             BinaryOperator<String> reducerValue = reducer.getValue();
4054             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
4055             final Function<? super T, String> mapperValue = mapper.getValue();
4056             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
4057             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
4058         }, items, reducer, mapper);
4059     }
4060 
4061     /**
4062      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
4063      *
4064      @param items        the observable set of elements.
4065      @param defaultValue the value to be returned if there is no value present, may be null.
4066      @param mapper       a non-interfering, stateless function to apply to each element.
4067      @param reducer      an associative, non-interfering, stateless function for combining two values.
4068      *
4069      @return a string binding
4070      */
4071     @Nonnull
4072     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final String defaultValue, @Nonnull final Function<? super T, String> mapper, @Nonnull final BinaryOperator<String> reducer) {
4073         requireNonNull(items, ERROR_ITEMS_NULL);
4074         requireNonNull(reducer, ERROR_REDUCER_NULL);
4075         return createStringBinding(() -> items.stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
4076     }
4077 
4078     /**
4079      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
4080      *
4081      @param items    the observable set of elements.
4082      @param supplier a {@code Supplier} whose result is returned if no value is present.
4083      @param mapper   a non-interfering, stateless function to apply to each element.
4084      @param reducer  an associative, non-interfering, stateless function for combining two values.
4085      *
4086      @return a string binding
4087      */
4088     @Nonnull
4089     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<String> supplier, @Nonnull final Function<? super T, String> mapper, @Nonnull final BinaryOperator<String> reducer) {
4090         requireNonNull(items, ERROR_ITEMS_NULL);
4091         requireNonNull(reducer, ERROR_REDUCER_NULL);
4092         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
4093         requireNonNull(mapper, ERROR_MAPPER_NULL);
4094         return createStringBinding(() -> items.stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
4095     }
4096 
4097     /**
4098      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
4099      *
4100      @param items        the observable set of elements.
4101      @param defaultValue the value to be returned if there is no value present, may be null.
4102      @param mapper       a non-interfering, stateless function to apply to each element.
4103      @param reducer      an associative, non-interfering, stateless function for combining two values.
4104      *
4105      @return a string binding
4106      */
4107     @Nonnull
4108     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableSet<T> items, @Nullable final String defaultValue, @Nonnull final ObservableValue<Function<? super T, String>> mapper, @Nonnull final ObservableValue<BinaryOperator<String>> reducer) {
4109         requireNonNull(reducer, ERROR_REDUCER_NULL);
4110         requireNonNull(mapper, ERROR_MAPPER_NULL);
4111         return createStringBinding(() -> {
4112             BinaryOperator<String> reducerValue = reducer.getValue();
4113             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
4114             final Function<? super T, String> mapperValue = mapper.getValue();
4115             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
4116             return items.stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
4117         }, items, reducer, mapper);
4118     }
4119 
4120     /**
4121      * Returns a string binding whose value is the reduction of all elements in the set. The mapper function is applied to each element before reduction.
4122      *
4123      @param items    the observable set of elements.
4124      @param supplier a {@code Supplier} whose result is returned if no value is present.
4125      @param mapper   a non-interfering, stateless function to apply to each element.
4126      @param reducer  an associative, non-interfering, stateless function for combining two values.
4127      *
4128      @return a string binding
4129      */
4130     @Nonnull
4131     public static <T> StringBinding mapToStringThenReduce(@Nonnull final ObservableSet<T> items, @Nonnull final Supplier<String> supplier, @Nonnull final ObservableValue<Function<? super T, String>> mapper, @Nonnull final ObservableValue<BinaryOperator<String>> reducer) {
4132         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
4133         requireNonNull(reducer, ERROR_REDUCER_NULL);
4134         requireNonNull(mapper, ERROR_MAPPER_NULL);
4135         return createStringBinding(() -> {
4136             BinaryOperator<String> reducerValue = reducer.getValue();
4137             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
4138             final Function<? super T, String> mapperValue = mapper.getValue();
4139             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
4140             return items.stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
4141         }, items, reducer, mapper);
4142     }
4143 
4144     /**
4145      * Returns a string binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
4146      *
4147      @param items        the observable map.
4148      @param defaultValue the value to be returned if there is no value present, may be null.
4149      @param mapper       a non-interfering, stateless function to apply to each value.
4150      @param reducer      an associative, non-interfering, stateless function for combining two values.
4151      *
4152      @return a string binding
4153      */
4154     @Nonnull
4155     public static <K, V> StringBinding mapToStringThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final String defaultValue, @Nonnull final Function<? super V, String> mapper, @Nonnull final BinaryOperator<String> reducer) {
4156         requireNonNull(items, ERROR_ITEMS_NULL);
4157         requireNonNull(reducer, ERROR_REDUCER_NULL);
4158         requireNonNull(mapper, ERROR_MAPPER_NULL);
4159         return createStringBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElse(defaultValue), items);
4160     }
4161 
4162     /**
4163      * Returns a string binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
4164      *
4165      @param items    the observable map.
4166      @param supplier a {@code Supplier} whose result is returned if no value is present.
4167      @param mapper   a non-interfering, stateless function to apply to each value.
4168      @param reducer  an associative, non-interfering, stateless function for combining two values.
4169      *
4170      @return a string binding
4171      */
4172     @Nonnull
4173     public static <K, V> StringBinding mapToStringThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<String> supplier, @Nonnull final Function<? super V, String> mapper, @Nonnull final BinaryOperator<String> reducer) {
4174         requireNonNull(items, ERROR_ITEMS_NULL);
4175         requireNonNull(reducer, ERROR_REDUCER_NULL);
4176         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
4177         requireNonNull(mapper, ERROR_MAPPER_NULL);
4178         return createStringBinding(() -> items.values().stream().map(mapper).reduce(reducer).orElseGet(supplier), items);
4179     }
4180 
4181     /**
4182      * Returns a string binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
4183      *
4184      @param items        the observable map.
4185      @param defaultValue the value to be returned if there is no value present, may be null.
4186      @param mapper       a non-interfering, stateless function to apply to each value.
4187      @param reducer      an associative, non-interfering, stateless function for combining two values.
4188      *
4189      @return a string binding
4190      */
4191     @Nonnull
4192     public static <K, V> StringBinding mapToStringThenReduce(@Nonnull final ObservableMap<K, V> items, @Nullable final String defaultValue, @Nonnull final ObservableValue<Function<? super V, String>> mapper, @Nonnull final ObservableValue<BinaryOperator<String>> reducer) {
4193         requireNonNull(reducer, ERROR_REDUCER_NULL);
4194         requireNonNull(mapper, ERROR_MAPPER_NULL);
4195         return createStringBinding(() -> {
4196             BinaryOperator<String> reducerValue = reducer.getValue();
4197             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
4198             final Function<? super V, String> mapperValue = mapper.getValue();
4199             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
4200             return items.values().stream().map(mapperValue).reduce(reducerValue).orElse(defaultValue);
4201         }, items, reducer, mapper);
4202     }
4203 
4204     /**
4205      * Returns a string binding whose value is the reduction of all values in the map. The mapper function is applied to each value before reduction.
4206      *
4207      @param items    the observable map.
4208      @param supplier a {@code Supplier} whose result is returned if no value is present.
4209      @param mapper   a non-interfering, stateless function to apply to each value.
4210      @param reducer  an associative, non-interfering, stateless function for combining two values.
4211      *
4212      @return a string binding
4213      */
4214     @Nonnull
4215     public static <K, V> StringBinding mapToStringThenReduce(@Nonnull final ObservableMap<K, V> items, @Nonnull final Supplier<String> supplier, @Nonnull final ObservableValue<Function<? super V, String>> mapper, @Nonnull final ObservableValue<BinaryOperator<String>> reducer) {
4216         requireNonNull(supplier, ERROR_SUPPLIER_NULL);
4217         requireNonNull(reducer, ERROR_REDUCER_NULL);
4218         requireNonNull(mapper, ERROR_MAPPER_NULL);
4219         return createStringBinding(() -> {
4220             BinaryOperator<String> reducerValue = reducer.getValue();
4221             requireNonNull(reducerValue, ERROR_REDUCER_NULL);
4222             final Function<? super V, String> mapperValue = mapper.getValue();
4223             requireNonNull(mapperValue, ERROR_MAPPER_NULL);
4224             return items.values().stream().map(mapperValue).reduce(reducerValue).orElseGet(supplier);
4225         }, items, reducer, mapper);
4226     }
4227 }