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