All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.util.Builder Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

There is a newer version: 5.2.4
Show newest version
/*
 * Copyright (C) 2016 HaiYang Li
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.landawn.abacus.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;

import com.landawn.abacus.util.NoCachingNoUpdating.DisposableObjArray;
import com.landawn.abacus.util.Tuple.Tuple2;
import com.landawn.abacus.util.Tuple.Tuple3;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.stream.Stream;

/**
 *
 * @author haiyangl
 * @param 
 * @since 0.8
 */
public class Builder {

    final T val;

    Builder(T val) {
        N.checkArgNotNull(val);

        this.val = val;
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final BooleanListBuilder of(final BooleanList val) throws IllegalArgumentException {
        return new BooleanListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final CharListBuilder of(final CharList val) throws IllegalArgumentException {
        return new CharListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final ByteListBuilder of(final ByteList val) throws IllegalArgumentException {
        return new ByteListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final ShortListBuilder of(final ShortList val) throws IllegalArgumentException {
        return new ShortListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final IntListBuilder of(final IntList val) throws IllegalArgumentException {
        return new IntListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final LongListBuilder of(final LongList val) throws IllegalArgumentException {
        return new LongListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final FloatListBuilder of(final FloatList val) throws IllegalArgumentException {
        return new FloatListBuilder(val);
    }

    /**
     *
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final DoubleListBuilder of(final DoubleList val) throws IllegalArgumentException {
        return new DoubleListBuilder(val);
    }

    /**
     *
     * @param 
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final > ListBuilder of(L val) throws IllegalArgumentException {
        return new ListBuilder<>(val);
    }

    /**
     *
     * @param 
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final > CollectionBuilder of(C val) throws IllegalArgumentException {
        return new CollectionBuilder<>(val);
    }

    /**
     *
     * @param  the key type
     * @param  the value type
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final > MapBuilder of(M val) throws IllegalArgumentException {
        return new MapBuilder<>(val);
    }

    /**
     *
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final  MultisetBuilder of(Multiset val) throws IllegalArgumentException {
        return new MultisetBuilder<>(val);
    }

    /**
     *
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final  LongMultisetBuilder of(LongMultiset val) throws IllegalArgumentException {
        return new LongMultisetBuilder<>(val);
    }

    /**
     *
     * @param  the key type
     * @param 
     * @param  the value type
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final , M extends Multimap> MultimapBuilder of(M val) throws IllegalArgumentException {
        return new MultimapBuilder<>(val);
    }

    /**
     * 
     *
     * @param val 
     * @return 
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    public static final DataSetBuilder of(final DataSet val) throws IllegalArgumentException {
        return new DataSetBuilder(val);
    }

    @SuppressWarnings("rawtypes")
    private static final Map, Function> creatorMap = new HashMap<>();

    static {
        initCreatorMap();
    }

    @SuppressWarnings("rawtypes")
    private static void initCreatorMap() {
        creatorMap.put(BooleanList.class, val -> Builder.of((BooleanList) val));
        creatorMap.put(CharList.class, val -> Builder.of((CharList) val));
        creatorMap.put(ByteList.class, val -> Builder.of((ByteList) val));
        creatorMap.put(ShortList.class, val -> Builder.of((ShortList) val));
        creatorMap.put(IntList.class, val -> Builder.of((IntList) val));
        creatorMap.put(LongList.class, val -> Builder.of((LongList) val));
        creatorMap.put(FloatList.class, val -> Builder.of((FloatList) val));
        creatorMap.put(DoubleList.class, val -> Builder.of((DoubleList) val));

        creatorMap.put(List.class, val -> Builder.of((List) val));
        creatorMap.put(ArrayList.class, val -> Builder.of((List) val));
        creatorMap.put(LinkedList.class, val -> Builder.of((List) val));

        creatorMap.put(Set.class, val -> Builder.of((Collection) val));
        creatorMap.put(HashSet.class, val -> Builder.of((Collection) val));
        creatorMap.put(LinkedHashSet.class, val -> Builder.of((Collection) val));

        creatorMap.put(Map.class, val -> Builder.of((Map) val));
        creatorMap.put(HashMap.class, val -> Builder.of((Map) val));
        creatorMap.put(LinkedHashMap.class, val -> Builder.of((Map) val));
        creatorMap.put(TreeMap.class, val -> Builder.of((Map) val));

        creatorMap.put(Multiset.class, val -> Builder.of((Multiset) val));
        creatorMap.put(LongMultiset.class, val -> Builder.of((LongMultiset) val));

        creatorMap.put(Multimap.class, val -> Builder.of((Multimap) val));
        creatorMap.put(ListMultimap.class, val -> Builder.of((Multimap) val));
        creatorMap.put(SetMultimap.class, val -> Builder.of((Multimap) val));

        creatorMap.put(DataSet.class, val -> Builder.of((DataSet) val));
        creatorMap.put(RowDataSet.class, val -> Builder.of((DataSet) val));
    }

    /**
     *
     * @param 
     * @param val
     * @return
     * @throws IllegalArgumentException if the specified {@code val} is {@code null}.
     */
    @SuppressWarnings("rawtypes")
    public static final  Builder of(T val) {
        N.checkArgNotNull(val);

        final Function func = creatorMap.get(val.getClass());

        if (func != null) {
            return func.apply(val);
        }

        Builder result = null;

        if (val instanceof List) {
            result = of((List) val);
        } else if (val instanceof Collection) {
            result = of((Collection) val);
        } else if (val instanceof Map) {
            result = of((Map) val);
        } else if (val instanceof Multimap) {
            result = of((Multimap) val);
        } else if (val instanceof DataSet) {
            result = of((DataSet) val);
        } else if (val instanceof Multiset) {
            result = of((Multiset) val);
        } else if (val instanceof LongMultiset) {
            result = of((LongMultiset) val);
        } else {
            result = new Builder<>(val);
        }

        return result;
    }

    //    public static  Builder get(final Supplier supplier) {
    //        return new Builder<>(supplier.get());
    //    }

    /**
     * 
     *
     * @return 
     */
    public T val() {
        return val;
    }

    /**
     *
     * @param 
     * @param 
     * @param mapper
     * @return
     * @throws E the e
     */
    public  Builder map(final Throwables.Function mapper) throws E {
        return of(mapper.apply(val));
    }

    /**
     *
     * @param 
     * @param predicate
     * @return Optional with the value if predicate returns true,
     * otherwise, return an empty Optional
     * @throws E the e
     */
    public  Optional filter(final Throwables.Predicate predicate) throws E {
        return predicate.test(val) ? Optional.of(val) : Optional. empty();
    }

    /**
     *
     * @param 
     * @param consumer
     * @return
     * @throws E the e
     */
    public  Builder accept(final Throwables.Consumer consumer) throws E {
        consumer.accept(val);

        return this;
    }

    /**
     *
     * @param 
     * @param 
     * @param func
     * @return
     * @throws E the e
     */
    public  R apply(final Throwables.Function func) throws E {
        return func.apply(val);
    }

    /**
     * 
     *
     * @return 
     */
    public Stream stream() {
        return Stream.of(val);
    }

    //    /**
    //    * Returns an empty Nullable if {@code val()} is {@code null} while {@code targetType} is primitive or can't be assigned to {@code targetType}.
    //    * Please be aware that {@code null} can be assigned to any {@code Object} type except primitive types: {@code boolean/char/byte/short/int/long/double}.
    //    *
    //    * @param val
    //    * @param targetType
    //    * @return
    //    */
    //    @SuppressWarnings("unchecked")
    //    public  Nullable castIfAssignable(final Class targetType) {
    //        if (N.isPrimitive(targetType)) {
    //            return val != null && N.wrapperOf(targetType).isAssignableFrom(val.getClass()) ? Nullable.of((TT) val) : Nullable. empty();
    //        }
    //
    //        return val == null || targetType.isAssignableFrom(val.getClass()) ? Nullable.of((TT) val) : Nullable. empty();
    //    }
    //
    //    /**
    //     *
    //     * @param b
    //     * @param actionForTrue do nothing if it's {@code null} even {@code b} is true.
    //     * @param actionForFalse do nothing if it's {@code null} even {@code b} is false.
    //     * @throws E1
    //     * @throws E2
    //     */
    //    public  void ifOrElse(final boolean b, final Try.Consumer actionForTrue,
    //            final Try.Consumer actionForFalse) throws E1, E2 {
    //        if (b) {
    //            if (actionForTrue != null) {
    //                actionForTrue.accept(val);
    //            }
    //        } else {
    //            if (actionForFalse != null) {
    //                actionForFalse.accept(val);
    //            }
    //        }
    //    }
    //
    //    /**
    //     *
    //     * @param predicate
    //     * @param actionForTrue do nothing if it's {@code null} even {@code b} is true.
    //     * @param actionForFalse do nothing if it's {@code null} even {@code b} is false.
    //     * @throws E0
    //     * @throws E1
    //     * @throws E2
    //     */
    //    public  void ifOrElse(final Try.Predicate predicate,
    //            final Try.Consumer actionForTrue, final Try.Consumer actionForFalse) throws E0, E1, E2 {
    //        if (predicate.test(val)) {
    //            if (actionForTrue != null) {
    //                actionForTrue.accept(val);
    //            }
    //        } else {
    //            if (actionForFalse != null) {
    //                actionForFalse.accept(val);
    //            }
    //        }
    //    }
    //
    //    /**
    //     * Returns an empty {@code Optional} if {@code cmd} is executed successfully, otherwise a {@code Optional} with the exception threw.
    //     *
    //     * @param cmd
    //     * @return
    //     */
    //    public Optional run(final Try.Consumer cmd) {
    //        try {
    //            cmd.accept(val);
    //            return Optional.empty();
    //        } catch (Exception e) {
    //            return Optional.of(e);
    //        }
    //    }
    //
    //    /**
    //     * Returns a {@code Pair} with {@code left=returnedValue, right=null} if {@code cmd} is executed successfully, otherwise a {@code Pair} with {@code left=null, right=exception}.
    //     *
    //     * @param cmd
    //     * @return
    //     */
    //    public  Pair call(final Try.Function cmd) {
    //        try {
    //            return Pair.of(cmd.apply(val), null);
    //        } catch (Exception e) {
    //            return Pair.of(null, e);
    //        }
    //    }
    //
    //    /**
    //     * Returns a {@code Nullable} with the value returned by {@code action} or an empty {@code Nullable} if exception happens.
    //     *
    //     * @param cmd
    //     * @return
    //     */
    //    public  Nullable tryOrEmpty(final Try.Function cmd) {
    //        try {
    //            return Nullable.of(cmd.apply(val));
    //        } catch (Exception e) {
    //            return Nullable. empty();
    //        }
    //    }

    /**
     * The Class BooleanListBuilder.
     */
    public static final class BooleanListBuilder extends Builder {

        /**
         * Instantiates a new boolean list builder.
         *
         * @param val
         */
        BooleanListBuilder(BooleanList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public BooleanListBuilder set(int index, boolean e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public BooleanListBuilder add(boolean e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public BooleanListBuilder add(int index, boolean e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public BooleanListBuilder addAll(BooleanList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public BooleanListBuilder addAll(int index, BooleanList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public BooleanListBuilder remove(boolean e) {
            val.remove(e);

            return this;
        }

        //        public BooleanListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public BooleanListBuilder removeAll(BooleanList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class CharListBuilder.
     */
    public static final class CharListBuilder extends Builder {

        /**
         * Instantiates a new char list builder.
         *
         * @param val
         */
        CharListBuilder(CharList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public CharListBuilder set(int index, char e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public CharListBuilder add(char e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public CharListBuilder add(int index, char e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public CharListBuilder addAll(CharList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public CharListBuilder addAll(int index, CharList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public CharListBuilder remove(char e) {
            val.remove(e);

            return this;
        }

        //        public CharListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public CharListBuilder removeAll(CharList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class ByteListBuilder.
     */
    public static final class ByteListBuilder extends Builder {

        /**
         * Instantiates a new byte list builder.
         *
         * @param val
         */
        ByteListBuilder(ByteList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public ByteListBuilder set(int index, byte e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public ByteListBuilder add(byte e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public ByteListBuilder add(int index, byte e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public ByteListBuilder addAll(ByteList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public ByteListBuilder addAll(int index, ByteList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public ByteListBuilder remove(byte e) {
            val.remove(e);

            return this;
        }

        //        public ByteListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public ByteListBuilder removeAll(ByteList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class ShortListBuilder.
     */
    public static final class ShortListBuilder extends Builder {

        /**
         * Instantiates a new short list builder.
         *
         * @param val
         */
        ShortListBuilder(ShortList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public ShortListBuilder set(int index, short e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public ShortListBuilder add(short e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public ShortListBuilder add(int index, short e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public ShortListBuilder addAll(ShortList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public ShortListBuilder addAll(int index, ShortList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public ShortListBuilder remove(short e) {
            val.remove(e);

            return this;
        }

        //        public ShortListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public ShortListBuilder removeAll(ShortList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class IntListBuilder.
     */
    public static final class IntListBuilder extends Builder {

        /**
         * Instantiates a new int list builder.
         *
         * @param val
         */
        IntListBuilder(IntList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public IntListBuilder set(int index, int e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public IntListBuilder add(int e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public IntListBuilder add(int index, int e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public IntListBuilder addAll(IntList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public IntListBuilder addAll(int index, IntList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public IntListBuilder remove(int e) {
            val.remove(e);

            return this;
        }

        //        public IntListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public IntListBuilder removeAll(IntList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class LongListBuilder.
     */
    public static final class LongListBuilder extends Builder {

        /**
         * Instantiates a new long list builder.
         *
         * @param val
         */
        LongListBuilder(LongList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public LongListBuilder set(int index, long e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public LongListBuilder add(long e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public LongListBuilder add(int index, long e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public LongListBuilder addAll(LongList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public LongListBuilder addAll(int index, LongList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public LongListBuilder remove(long e) {
            val.remove(e);

            return this;
        }

        //        public LongListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public LongListBuilder removeAll(LongList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class FloatListBuilder.
     */
    public static final class FloatListBuilder extends Builder {

        /**
         * Instantiates a new float list builder.
         *
         * @param val
         */
        FloatListBuilder(FloatList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public FloatListBuilder set(int index, float e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public FloatListBuilder add(float e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public FloatListBuilder add(int index, float e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public FloatListBuilder addAll(FloatList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public FloatListBuilder addAll(int index, FloatList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public FloatListBuilder remove(float e) {
            val.remove(e);

            return this;
        }

        //        public FloatListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public FloatListBuilder removeAll(FloatList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class DoubleListBuilder.
     */
    public static final class DoubleListBuilder extends Builder {

        /**
         * Instantiates a new double list builder.
         *
         * @param val
         */
        DoubleListBuilder(DoubleList val) {
            super(val);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public DoubleListBuilder set(int index, double e) {
            val.set(index, e);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public DoubleListBuilder add(double e) {
            val.add(e);

            return this;
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public DoubleListBuilder add(int index, double e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public DoubleListBuilder addAll(DoubleList c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public DoubleListBuilder addAll(int index, DoubleList c) {
            val.addAll(index, c);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public DoubleListBuilder remove(double e) {
            val.remove(e);

            return this;
        }

        //        public DoubleListBuilder removeAllOccurrences(double e) {
        //            value.removeAllOccurrences(e);
        //
        //            return this;
        //        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public DoubleListBuilder removeAll(DoubleList c) {
            val.removeAll(c);

            return this;
        }
    }

    /**
     * The Class ListBuilder.
     *
     * @param 
     * @param 
     */
    public static final class ListBuilder> extends CollectionBuilder {

        /**
         * Instantiates a new list builder.
         *
         * @param c
         */
        ListBuilder(L c) {
            super(c);
        }

        /**
         *
         * @param index
         * @param e
         * @return
         */
        public ListBuilder add(int index, T e) {
            val.add(index, e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param index
         * @param c
         * @return
         */
        public ListBuilder addAll(int index, Collection c) {
            N.checkIndex(index, val.size());

            if (N.notNullOrEmpty(c)) {
                val.addAll(index, c);
            }

            return this;
        }

        /**
         *
         * @param index
         * @return
         */
        public ListBuilder remove(int index) {
            val.remove(index);

            return this;
        }
    }

    /**
     * The Class CollectionBuilder.
     *
     * @param 
     * @param 
     */
    public static class CollectionBuilder> extends Builder {

        /**
         * Instantiates a new collection builder.
         *
         * @param c
         */
        CollectionBuilder(C c) {
            super(c);
        }

        /**
         *
         * @param e
         * @return
         */
        public CollectionBuilder add(T e) {
            val.add(e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public CollectionBuilder addAll(final Collection c) {
            if (N.notNullOrEmpty(c)) {
                val.addAll(c);
            }

            return this;
        }

        /**
         * Adds the all.
         *
         * @param a
         * @return
         */
        public CollectionBuilder addAll(final T... a) {
            if (N.notNullOrEmpty(a)) {
                val.addAll(Arrays.asList(a));
            }

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public CollectionBuilder remove(Object e) {
            val.remove(e);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public CollectionBuilder removeAll(Collection c) {
            if (N.notNullOrEmpty(c)) {
                val.removeAll(c);
            }

            return this;
        }

        /**
         * Removes the all.
         *
         * @param a
         * @return
         */
        public CollectionBuilder removeAll(final T... a) {
            if (N.notNullOrEmpty(a)) {
                val.removeAll(Arrays.asList(a));
            }

            return this;
        }
    }

    /**
     * The Class MultisetBuilder.
     *
     * @param 
     */
    public static final class MultisetBuilder extends Builder> {

        /**
         * Instantiates a new multiset builder.
         *
         * @param c
         */
        MultisetBuilder(Multiset c) {
            super(c);
        }

        /**
         *
         * @param e
         * @return
         */
        public MultisetBuilder add(T e) {
            val.add(e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public MultisetBuilder addAll(final Collection c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param m
         * @return
         */
        public MultisetBuilder addAll(final Map m) {
            val.addAll(m);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param multiset
         * @return
         */
        public MultisetBuilder addAll(final Multiset multiset) {
            val.addAll(multiset);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public MultisetBuilder remove(Object e) {
            val.remove(e);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public MultisetBuilder removeAll(Collection c) {
            val.removeAll(c);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param m
         * @return
         */
        public MultisetBuilder removeAll(final Map m) {
            val.removeAll(m);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param multiset
         * @return
         */
        public MultisetBuilder removeAll(Multiset multiset) {
            val.removeAll(multiset);

            return this;
        }
    }

    /**
     * The Class LongMultisetBuilder.
     *
     * @param 
     */
    public static final class LongMultisetBuilder extends Builder> {

        /**
         * Instantiates a new long multiset builder.
         *
         * @param c
         */
        LongMultisetBuilder(LongMultiset c) {
            super(c);
        }

        /**
         *
         * @param e
         * @return
         */
        public LongMultisetBuilder add(T e) {
            val.add(e);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param c
         * @return
         */
        public LongMultisetBuilder addAll(final Collection c) {
            val.addAll(c);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param m
         * @return
         */
        public LongMultisetBuilder addAll(final Map m) {
            val.addAll(m);

            return this;
        }

        /**
         * Adds the all.
         *
         * @param multiset
         * @return
         */
        public LongMultisetBuilder addAll(final LongMultiset multiset) {
            val.addAll(multiset);

            return this;
        }

        /**
         *
         * @param e
         * @return
         */
        public LongMultisetBuilder remove(Object e) {
            val.remove(e);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param c
         * @return
         */
        public LongMultisetBuilder removeAll(Collection c) {
            val.removeAll(c);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param m
         * @return
         */
        public LongMultisetBuilder removeAll(final Map m) {
            val.removeAll(m);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param multiset
         * @return
         */
        public LongMultisetBuilder removeAll(LongMultiset multiset) {
            val.removeAll(multiset);

            return this;
        }
    }

    /**
     * The Class MapBuilder.
     *
     * @param  the key type
     * @param  the value type
     * @param 
     */
    public static final class MapBuilder> extends Builder {

        /**
         * Instantiates a new map builder.
         *
         * @param m
         */
        MapBuilder(M m) {
            super(m);
        }

        /**
         *
         * @param k
         * @param v
         * @return
         */
        public MapBuilder put(K k, V v) {
            val.put(k, v);

            return this;
        }

        /**
         *
         * @param m
         * @return
         */
        public MapBuilder putAll(Map m) {
            if (N.notNullOrEmpty(m)) {
                val.putAll(m);
            }

            return this;
        }

        /**
         * Put if absent.
         *
         * @param key
         * @param value
         * @return
         */
        public MapBuilder putIfAbsent(K key, V value) {
            V v = val.get(key);

            if (v == null && val.containsKey(key) == false) {
                val.put(key, value);
            }

            return this;
        }

        /**
         * Put if absent.
         *
         * @param key
         * @param supplier
         * @return
         */
        public MapBuilder putIfAbsent(K key, Supplier supplier) {
            V v = val.get(key);

            if (v == null && val.containsKey(key) == false) {
                val.put(key, supplier.get());
            }

            return this;
        }

        /**
         *
         * @param k
         * @return
         */
        public MapBuilder remove(Object k) {
            val.remove(k);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param keysToRemove
         * @return
         */
        public MapBuilder removeAll(Collection keysToRemove) {
            if (N.notNullOrEmpty(keysToRemove)) {
                for (Object k : keysToRemove) {
                    val.remove(k);
                }
            }

            return this;
        }
    }

    /**
     * The Class MultimapBuilder.
     *
     * @param  the key type
     * @param 
     * @param  the value type
     * @param 
     */
    public static final class MultimapBuilder, M extends Multimap> extends Builder {

        /**
         * Instantiates a new multimap builder.
         *
         * @param m
         */
        MultimapBuilder(M m) {
            super(m);
        }

        /**
         *
         * @param key
         * @param e
         * @return
         */
        public MultimapBuilder put(K key, E e) {
            val.put(key, e);

            return this;
        }

        /**
         *
         * @param k
         * @param c
         * @return
         */
        public MultimapBuilder putAll(final K k, final Collection c) {
            val.putAll(k, c);

            return this;
        }

        /**
         *
         * @param m
         * @return
         */
        public MultimapBuilder putAll(Map m) {
            val.putAll(m);

            return this;
        }

        /**
         *
         * @param m
         * @return
         */
        public MultimapBuilder putAll(Multimap m) {
            val.putAll(m);

            return this;
        }

        /**
         *
         * @param k
         * @param e
         * @return
         */
        public MultimapBuilder remove(Object k, Object e) {
            val.remove(k, e);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param k
         * @return
         */
        public MultimapBuilder removeAll(Object k) {
            val.removeAll(k);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param k
         * @param valuesToRemove
         * @return
         */
        public MultimapBuilder removeAll(Object k, Collection valuesToRemove) {
            val.removeAll(k, valuesToRemove);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param m
         * @return
         */
        public MultimapBuilder removeAll(Map m) {
            val.removeAll(m);

            return this;
        }

        /**
         * Removes the all.
         *
         * @param m
         * @return
         */
        public MultimapBuilder removeAll(Multimap m) {
            val.removeAll(m);

            return this;
        }
    }

    /**
     * The Class DataSetBuilder.
     */
    public static final class DataSetBuilder extends Builder {

        /**
         * Instantiates a new data set builder.
         *
         * @param ds
         */
        DataSetBuilder(DataSet ds) {
            super(ds);
        }

        /**
         *
         * @param columnName
         * @param newColumnName
         * @return
         */
        public DataSetBuilder renameColumn(String columnName, String newColumnName) {
            val.renameColumn(columnName, newColumnName);

            return this;
        }

        /**
         *
         * @param oldNewNames
         * @return
         */
        public DataSetBuilder renameColumns(Map oldNewNames) {
            val.renameColumns(oldNewNames);

            return this;
        }

        /**
         *
         * @param 
         * @param columnName
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder renameColumn(String columnName, Throwables.Function func) throws E {
            val.renameColumn(columnName, func);

            return this;
        }

        /**
         *
         * @param 
         * @param columnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder renameColumns(Collection columnNames, Throwables.Function func) throws E {
            val.renameColumns(columnNames, func);

            return this;
        }

        /**
         *
         * @param 
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder renameColumns(Throwables.Function func) throws E {
            val.renameColumns(func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param columnName
         * @param column
         * @return
         */
        public DataSetBuilder addColumn(String columnName, List column) {
            val.addColumn(columnName, column);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param columnIndex
         * @param columnName
         * @param column
         * @return
         */
        public DataSetBuilder addColumn(int columnIndex, String columnName, List column) {
            val.addColumn(columnIndex, columnName, column);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param 
         * @param newColumnName
         * @param fromColumnName
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(String newColumnName, String fromColumnName, Throwables.Function func) throws E {
            val.addColumn(newColumnName, fromColumnName, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param 
         * @param columnIndex
         * @param newColumnName
         * @param fromColumnName
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(int columnIndex, String newColumnName, String fromColumnName,
                Throwables.Function func) throws E {
            val.addColumn(columnIndex, newColumnName, fromColumnName, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param newColumnName
         * @param fromColumnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(String newColumnName, Collection fromColumnNames,
                Throwables.Function func) throws E {
            val.addColumn(newColumnName, fromColumnNames, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param columnIndex
         * @param newColumnName
         * @param fromColumnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(int columnIndex, String newColumnName, Collection fromColumnNames,
                Throwables.Function func) throws E {
            val.addColumn(columnIndex, newColumnName, fromColumnNames, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param newColumnName
         * @param fromColumnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(String newColumnName, Tuple2 fromColumnNames,
                Throwables.BiFunction func) throws E {
            val.addColumn(newColumnName, fromColumnNames, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param columnIndex
         * @param newColumnName
         * @param fromColumnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(int columnIndex, String newColumnName, Tuple2 fromColumnNames,
                Throwables.BiFunction func) throws E {
            val.addColumn(columnIndex, newColumnName, fromColumnNames, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param newColumnName
         * @param fromColumnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(String newColumnName, Tuple3 fromColumnNames,
                Throwables.TriFunction func) throws E {
            val.addColumn(newColumnName, fromColumnNames, func);

            return this;
        }

        /**
         * Adds the column.
         *
         * @param 
         * @param columnIndex
         * @param newColumnName
         * @param fromColumnNames
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder addColumn(int columnIndex, String newColumnName, Tuple3 fromColumnNames,
                Throwables.TriFunction func) throws E {
            val.addColumn(columnIndex, newColumnName, fromColumnNames, func);

            return this;
        }

        /**
         * Removes the column.
         *
         * @param columnName
         * @return
         */
        public DataSetBuilder removeColumn(String columnName) {
            val.removeColumn(columnName);

            return this;
        }

        /**
         * Removes the columns.
         *
         * @param columnNames
         * @return
         */
        public DataSetBuilder removeColumns(Collection columnNames) {
            val.removeColumns(columnNames);

            return this;
        }

        /**
         * Removes the columns.
         *
         * @param 
         * @param filter
         * @return
         * @throws E the e
         */
        public  DataSetBuilder removeColumns(Throwables.Predicate filter) throws E {
            val.removeColumns(filter);

            return this;
        }

        //        /**
        //         * Removes the columns if.
        //         *
        //         * @param 
        //         * @param filter
        //         * @return
        //         * @throws E the e
        //         * @deprecated replaced by {@code removeColumns}.
        //         */
        //        @Deprecated
        //        public  DataSetBuilder removeColumnsIf(Predicate filter) throws E {
        //            val.removeColumnsIf(filter);
        //
        //            return this;
        //        }

        /**
         *
         * @param 
         * @param 
         * @param columnName
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder updateColumn(String columnName, Throwables.Function func) throws E {
            val.updateColumn(columnName, func);

            return this;
        }

        /**
         * 
         *
         * @param  
         * @param columnNames 
         * @param func 
         * @return 
         * @throws E the e
         */
        public  DataSetBuilder updateColumns(Collection columnNames, Throwables.Function func) throws E {
            val.updateColumns(columnNames, func);

            return this;
        }

        /**
         *
         * @param columnName
         * @param targetType
         * @return
         */
        public DataSetBuilder convertColumn(String columnName, Class targetType) {
            val.convertColumn(columnName, targetType);

            return this;
        }

        /**
         *
         * @param columnTargetTypes
         * @return
         */
        public DataSetBuilder convertColumns(Map> columnTargetTypes) {
            val.convertColumns(columnTargetTypes);

            return this;
        }

        /**
         *
         * @param columnNames
         * @param newColumnName
         * @param newColumnClass
         * @return
         */
        public DataSetBuilder combineColumns(Collection columnNames, String newColumnName, Class newColumnClass) {
            val.combineColumns(columnNames, newColumnName, newColumnClass);

            return this;
        }

        /**
         *
         * @param 
         * @param columnNames
         * @param newColumnName
         * @param combineFunc
         * @return
         * @throws E the e
         */
        public  DataSetBuilder combineColumns(Collection columnNames, String newColumnName,
                Throwables.Function combineFunc) throws E {
            val.combineColumns(columnNames, newColumnName, combineFunc);

            return this;
        }

        /**
         *
         * @param 
         * @param columnNames
         * @param newColumnName
         * @param combineFunc
         * @return
         * @throws E the e
         */
        public  DataSetBuilder combineColumns(Tuple2 columnNames, String newColumnName,
                Throwables.BiFunction combineFunc) throws E {
            val.combineColumns(columnNames, newColumnName, combineFunc);

            return this;
        }

        /**
         *
         * @param 
         * @param columnNames
         * @param newColumnName
         * @param combineFunc
         * @return
         * @throws E the e
         */
        public  DataSetBuilder combineColumns(Tuple3 columnNames, String newColumnName,
                Throwables.TriFunction combineFunc) throws E {
            val.combineColumns(columnNames, newColumnName, combineFunc);

            return this;
        }

        /**
         *
         * @param 
         * @param columnNameFilter
         * @param newColumnName
         * @param newColumnClass
         * @return
         * @throws E the e
         */
        public  DataSetBuilder combineColumns(Throwables.Predicate columnNameFilter, String newColumnName,
                Class newColumnClass) throws E {
            val.combineColumns(columnNameFilter, newColumnName, newColumnClass);

            return this;
        }

        /**
         *
         * @param 
         * @param 
         * @param columnNameFilter
         * @param newColumnName
         * @param combineFunc
         * @return
         * @throws E the e
         * @throws E2 the e2
         */
        public  DataSetBuilder combineColumns(Throwables.Predicate columnNameFilter, String newColumnName,
                Throwables.Function combineFunc) throws E, E2 {
            val.combineColumns(columnNameFilter, newColumnName, combineFunc);

            return this;
        }

        /**
         *
         * @param 
         * @param 
         * @param columnName
         * @param newColumnNames
         * @param divideFunc
         * @return
         * @throws E the e
         */
        public  DataSetBuilder divideColumn(String columnName, Collection newColumnNames,
                Throwables.Function, E> divideFunc) throws E {
            val.divideColumn(columnName, newColumnNames, divideFunc);

            return this;
        }

        /**
         *
         * @param 
         * @param 
         * @param columnName
         * @param newColumnNames
         * @param output
         * @return
         * @throws E the e
         */
        public  DataSetBuilder divideColumn(String columnName, Collection newColumnNames,
                Throwables.BiConsumer output) throws E {
            val.divideColumn(columnName, newColumnNames, output);

            return this;
        }

        /**
         *
         * @param 
         * @param 
         * @param columnName
         * @param newColumnNames
         * @param output
         * @return
         * @throws E the e
         */
        public  DataSetBuilder divideColumn(String columnName, Tuple2 newColumnNames,
                Throwables.BiConsumer, E> output) throws E {
            val.divideColumn(columnName, newColumnNames, output);

            return this;
        }

        /**
         *
         * @param 
         * @param 
         * @param columnName
         * @param newColumnNames
         * @param output
         * @return
         * @throws E the e
         */
        public  DataSetBuilder divideColumn(String columnName, Tuple3 newColumnNames,
                Throwables.BiConsumer, E> output) throws E {
            val.divideColumn(columnName, newColumnNames, output);

            return this;
        }

        /**
         *
         * @param 
         * @param func
         * @return
         * @throws E the e
         */
        public  DataSetBuilder updateAll(Throwables.Function func) throws E {
            val.updateAll(func);

            return this;
        }

        /**
         *
         * @param 
         * @param func
         * @param newValue
         * @return
         * @throws E the e
         */
        public  DataSetBuilder replaceIf(Throwables.Predicate func, Object newValue) throws E {
            val.replaceIf(func, newValue);

            return this;
        }

        /**
         *
         * @param columnName
         * @return
         */
        public DataSetBuilder sortBy(String columnName) {
            val.sortBy(columnName);

            return this;
        }

        /**
         *
         * @param 
         * @param columnName
         * @param cmp
         * @return
         */
        public  DataSetBuilder sortBy(String columnName, Comparator cmp) {
            val.sortBy(columnName, cmp);

            return this;
        }

        /**
         *
         * @param columnNames
         * @return
         */
        public DataSetBuilder sortBy(Collection columnNames) {
            val.sortBy(columnNames);

            return this;
        }

        /**
         *
         * @param columnNames
         * @param cmp
         * @return
         */
        public DataSetBuilder sortBy(Collection columnNames, Comparator cmp) {
            val.sortBy(columnNames, cmp);

            return this;
        }

        /**
         *
         * @param columnNames
         * @param keyMapper
         * @return
         */
        @SuppressWarnings("rawtypes")
        public DataSetBuilder sortBy(Collection columnNames, Function keyMapper) {
            val.sortBy(columnNames, keyMapper);

            return this;
        }

        /**
         * Parallel sort by.
         *
         * @param columnName
         * @return
         */
        public DataSetBuilder parallelSortBy(String columnName) {
            val.parallelSortBy(columnName);

            return this;
        }

        /**
         * Parallel sort by.
         *
         * @param 
         * @param columnName
         * @param cmp
         * @return
         */
        public  DataSetBuilder parallelSortBy(String columnName, Comparator cmp) {
            val.parallelSortBy(columnName, cmp);

            return this;
        }

        /**
         * Parallel sort by.
         *
         * @param columnNames
         * @return
         */
        public DataSetBuilder parallelSortBy(Collection columnNames) {
            val.parallelSortBy(columnNames);

            return this;
        }

        /**
         * Parallel sort by.
         *
         * @param columnNames
         * @param cmp
         * @return
         */
        public DataSetBuilder parallelSortBy(Collection columnNames, Comparator cmp) {
            val.parallelSortBy(columnNames, cmp);

            return this;
        }

        /**
         * Parallel sort by.
         *
         * @param columnNames
         * @param keyMapper
         * @return
         */
        @SuppressWarnings("rawtypes")
        public DataSetBuilder parallelSortBy(Collection columnNames, Function keyMapper) {
            val.parallelSortBy(columnNames, keyMapper);

            return this;
        }
    }

    /**
     * Compares two comparable objects as specified by {@link
     * Comparable#compareTo}, if the result of this comparison chain
     * has not already been determined.
     *
     * @param 
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static > ComparisonBuilder compare(T left, T right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two objects using a comparator, if the result of this
     * comparison chain has not already been determined.
     *
     * @param 
     * @param left
     * @param right
     * @param comparator
     * @return {@code ComparisonChain}
     */
    public static  ComparisonBuilder compare(T left, T right, Comparator comparator) {
        return new ComparisonBuilder().compare(left, right, comparator);
    }

    /**
     *
     * @param 
     * @param left
     * @param right
     * @param func
     * @return
     */
    public static  ComparisonBuilder compare(T left, T right, BiFunction func) {
        return new ComparisonBuilder().compare(left, right, func);
    }

    /**
     * {@code null} is smaller.
     *
     * @param 
     * @param left
     * @param right
     * @return
     */
    public static > ComparisonBuilder compareNullLess(T left, T right) {
        return new ComparisonBuilder().compareNullLess(left, right);
    }

    /**
     * {@code null} is bigger.
     *
     * @param 
     * @param left
     * @param right
     * @return
     */
    public static > ComparisonBuilder compareNullBigger(T left, T right) {
        return new ComparisonBuilder().compareNullBigger(left, right);
    }

    /**
     * Compares two {@code boolean} values, considering {@code false} to be less
     * than {@code true}, if the result of this comparison chain has not
     * already been determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compareFalseLess(boolean left, boolean right) {
        return new ComparisonBuilder().compareFalseLess(left, right);
    }

    /**
     * Compares two {@code boolean} values, considering {@code true} to be less
     * than {@code false}, if the result of this comparison chain has not
     * already been determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compareTrueLess(boolean left, boolean right) {
        return new ComparisonBuilder().compareTrueLess(left, right);
    }

    /**
     * Compares two {@code char} values as specified by {@link N#compare},
     * if the result of this comparison chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(char left, char right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two {@code byte} values as specified by {@link N#compare},
     * if the result of this comparison chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(byte left, byte right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two {@code short} values as specified by {@link N#compare},
     * if the result of this comparison chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(short left, short right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two {@code int} values as specified by {@link N#compare},
     * if the result of this comparison chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(int left, int right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two {@code long} values as specified by {@link N#compare},
     * if the result of this comparison chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(long left, long right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two {@code float} values as specified by {@link
     * Float#compare}, if the result of this comparison chain has not
     * already been determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(float left, float right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two {@code double} values as specified by {@link
     * Double#compare}, if the result of this comparison chain has not
     * already been determined.
     *
     * @param left
     * @param right
     * @return {@code ComparisonChain}
     */
    public static ComparisonBuilder compare(double left, double right) {
        return new ComparisonBuilder().compare(left, right);
    }

    /**
     * Compares two comparable objects as specified by {@link
     * N#equals(Object, Object)}, if the result of this equivalence chain
     * has not already been determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(Object left, Object right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     *
     * @param 
     * @param left
     * @param right
     * @param func
     * @return
     */
    public static  EquivalenceBuilder equals(T left, T right, BiFunction func) {
        return new EquivalenceBuilder().equals(left, right, func);
    }

    /**
     * Compares two {@code boolean} values as specified by {@code left == right},
     * if the result of this equivalence chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(boolean left, boolean right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code char} values as specified by {@code left == right},
     * if the result of this equivalence chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(char left, char right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code byte} values as specified by {@code left == right},
     * if the result of this equivalence chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(byte left, byte right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code short} values as specified by {@code left == right},
     * if the result of this equivalence chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(short left, short right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code int} values as specified by {@code left == right},
     * if the result of this equivalence chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(int left, int right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code long} values as specified by {@code left == right},
     * if the result of this equivalence chain has not already been
     * determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(long left, long right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code float} values as specified by {@link
     * Float#compare}, if the result of this equivalence chain has not
     * already been determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(float left, float right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Compares two {@code double} values as specified by {@link
     * Double#compare}, if the result of this equivalence chain has not
     * already been determined.
     *
     * @param left
     * @param right
     * @return {@code EquivalenceChain}
     */
    public static EquivalenceBuilder equals(double left, double right) {
        return new EquivalenceBuilder().equals(left, right);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(Object value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     *
     * @param 
     * @param value
     * @param func
     * @return
     */
    public static  HashCodeBuilder hash(T value, ToIntFunction func) {
        return new HashCodeBuilder().hash(value, func);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(boolean value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(char value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(byte value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(short value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(int value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(long value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(float value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * Add the hash code of the specified {@code value} to result.
     *
     * @param value
     * @return this
     */
    public static HashCodeBuilder hash(double value) {
        return new HashCodeBuilder().hash(value);
    }

    /**
     * The Class ComparisonChain.
     */
    public static final class ComparisonBuilder {

        /** The result. */
        private int result = 0;

        /**
         * Instantiates a new comparison chain.
         */
        private ComparisonBuilder() {
            // singleton.
        }

        /**
         * Compares two comparable objects as specified by {@link
         * Comparable#compareTo}, if the result of this comparison chain
         * has not already been determined.
         *
         * @param 
         * @param left
         * @param right
         * @return this
         */
        public > ComparisonBuilder compare(T left, T right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two objects using a comparator, if the result of this
         * comparison chain has not already been determined.
         *
         * @param 
         * @param left
         * @param right
         * @param comparator
         * @return this
         */
        public  ComparisonBuilder compare(T left, T right, Comparator comparator) {
            if (result == 0) {
                result = N.compare(left, right, comparator);
            }

            return this;
        }

        /**
         *
         * @param 
         * @param left
         * @param right
         * @param func
         * @return
         */
        public  ComparisonBuilder compare(T left, T right, BiFunction func) {
            N.checkArgNotNull(func, "func");

            if (result == 0) {
                result = func.apply(left, right);
            }

            return this;
        }

        /**
         * {@code null} is smaller.
         *
         * @param 
         * @param left
         * @param right
         * @return
         */
        public > ComparisonBuilder compareNullLess(T left, T right) {
            if (result == 0) {
                result = left == null ? (right == null ? 0 : -1) : (right == null ? 1 : left.compareTo(right));
            }

            return this;
        }

        /**
         * {@code null} is bigger.
         *
         * @param 
         * @param left
         * @param right
         * @return
         */
        public > ComparisonBuilder compareNullBigger(T left, T right) {
            if (result == 0) {
                result = left == null ? (right == null ? 0 : 1) : (right == null ? -1 : left.compareTo(right));
            }

            return this;
        }

        /**
         * Compares two {@code boolean} values, considering {@code false} to be less
         * than {@code true}, if the result of this comparison chain has not
         * already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compareFalseLess(boolean left, boolean right) {
            if (result == 0) {
                result = left == right ? 0 : (left ? -1 : 1);
            }

            return this;
        }

        /**
         * Compares two {@code boolean} values, considering {@code true} to be less
         * than {@code false}, if the result of this comparison chain has not
         * already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compareTrueLess(boolean left, boolean right) {
            if (result == 0) {
                result = left == right ? 0 : (left ? 1 : -1);
            }

            return this;
        }

        /**
         * Compares two {@code char} values as specified by {@link N#compare},
         * if the result of this comparison chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(char left, char right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code byte} values as specified by {@link N#compare},
         * if the result of this comparison chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(byte left, byte right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code short} values as specified by {@link N#compare},
         * if the result of this comparison chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(short left, short right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code int} values as specified by {@link N#compare},
         * if the result of this comparison chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(int left, int right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code long} values as specified by {@link N#compare},
         * if the result of this comparison chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(long left, long right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code float} values as specified by {@link
         * Float#compare}, if the result of this comparison chain has not
         * already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(float left, float right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code double} values as specified by {@link
         * Double#compare}, if the result of this comparison chain has not
         * already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public ComparisonBuilder compare(double left, double right) {
            if (result == 0) {
                result = N.compare(left, right);
            }

            return this;
        }

        /**
         *
         * @return
         */
        public int result() {
            return result;
        }
    }

    /**
     * The Class EquivalenceChain.
     */
    public static final class EquivalenceBuilder {

        /** The result. */
        private boolean result = true;

        /**
         * Instantiates a new equivalence chain.
         */
        private EquivalenceBuilder() {
            // singleton.
        }

        /**
         * Compares two comparable objects as specified by {@link
         * N#equals(Object, Object)}, if the result of this equivalence chain
         * has not already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(Object left, Object right) {
            if (result) {
                result = N.equals(left, right);
            }

            return this;
        }

        /**
         *
         * @param 
         * @param left
         * @param right
         * @param func
         * @return
         */
        public  EquivalenceBuilder equals(T left, T right, BiFunction func) {
            N.checkArgNotNull(func, "func");

            if (result) {
                result = func.apply(left, right);
            }

            return this;
        }

        /**
         * Compares two {@code boolean} values as specified by {@code left == right},
         * if the result of this equivalence chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(boolean left, boolean right) {
            if (result) {
                result = left == right;
            }

            return this;
        }

        /**
         * Compares two {@code char} values as specified by {@code left == right},
         * if the result of this equivalence chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(char left, char right) {
            if (result) {
                result = left == right;
            }

            return this;
        }

        /**
         * Compares two {@code byte} values as specified by {@code left == right},
         * if the result of this equivalence chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(byte left, byte right) {
            if (result) {
                result = left == right;
            }

            return this;
        }

        /**
         * Compares two {@code int} values as specified by {@code left == right},
         * if the result of this equivalence chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(short left, short right) {
            if (result) {
                result = left == right;
            }

            return this;
        }

        /**
         * Compares two {@code int} values as specified by {@code left == right},
         * if the result of this equivalence chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(int left, int right) {
            if (result) {
                result = left == right;
            }

            return this;
        }

        /**
         * Compares two {@code long} values as specified by {@code left == right},
         * if the result of this equivalence chain has not already been
         * determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(long left, long right) {
            if (result) {
                result = left == right;
            }

            return this;
        }

        /**
         * Compares two {@code float} values as specified by {@link
         * Float#compare}, if the result of this equivalence chain has not
         * already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(float left, float right) {
            if (result) {
                result = Float.compare(left, right) == 0;
            }

            return this;
        }

        /**
         * Compares two {@code double} values as specified by {@link
         * Double#compare}, if the result of this equivalence chain has not
         * already been determined.
         *
         * @param left
         * @param right
         * @return this
         */
        public EquivalenceBuilder equals(double left, double right) {
            if (result) {
                result = Double.compare(left, right) == 0;
            }

            return this;
        }

        /**
         *
         * @return
         */
        public boolean result() {
            return result;
        }
    }

    /**
     * The Class HashCodeChain.
     */
    public static final class HashCodeBuilder {

        /** The result. */
        private int result = 0;

        /**
         * Instantiates a new hash code chain.
         */
        private HashCodeBuilder() {
            // singleton.
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(Object value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         *
         * @param 
         * @param value
         * @param func
         * @return
         */
        public  HashCodeBuilder hash(T value, ToIntFunction func) {
            N.checkArgNotNull(func, "func");

            result = result * 31 + func.applyAsInt(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(boolean value) {
            result = result * 31 + (value ? 1231 : 1237);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(char value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(byte value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(short value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(int value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(long value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(float value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         * Add the hash code of the specified {@code value} to result.
         *
         * @param value
         * @return this
         */
        public HashCodeBuilder hash(double value) {
            result = result * 31 + N.hashCode(value);

            return this;
        }

        /**
         *
         * @return
         */
        public int result() {
            return result;
        }
    }

    /**
     * The Class X.
     *
     * @param 
     */
    public static final class X extends Builder {

        /**
         * Instantiates a new x.
         *
         * @param val
         */
        private X(T val) { //NOSONAR
            super(val);
        }

        //        /**
        //         *
        //         * @param output
        //         * @param e
        //         * @return return the specified {@code output}
        //         */
        //        public static > C add(final C output, final E e) {
        //            output.add(e);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param e
        //         * @return return the specified {@code output}
        //         */
        //        public static > C addAll(final C output, final Collection c) {
        //            if (c == null || c.size() == 0) {
        //                return output;
        //            }
        //
        //            output.addAll(c);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param e
        //         * @return return the specified {@code output}
        //         */
        //        public static > C remove(final C output, final Object e) {
        //            if (output == null || output.size() == 0) {
        //                return output;
        //            }
        //
        //            output.remove(e);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param e
        //         * @return return the specified {@code output}
        //         */
        //        public static > C removeAll(final C output, final Collection c) {
        //            if (output == null || output.size() == 0 || c == null || c.size() == 0) {
        //                return output;
        //            }
        //
        //            output.removeAll(c);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @param value
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M put(final M output, K key, final V value) {
        //            output.put(key, value);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param entryToAdd
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M put(final M output, final Map.Entry entryToAdd) {
        //            output.put(entryToAdd.getKey(), entryToAdd.getValue());
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param entriesToAdd
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M putAll(final M output, final Map entriesToAdd) {
        //            if (entriesToAdd == null || entriesToAdd.size() == 0) {
        //                return output;
        //            }
        //
        //            output.putAll(entriesToAdd);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @param value
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M putIfAbsent(final M output, K key, final V value) {
        //            if (!output.containsKey(key)) {
        //                output.put(key, value);
        //            }
        //
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param entryToAdd
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M putIfAbsent(final M output, final Map.Entry entryToAdd) {
        //            if (!output.containsKey(entryToAdd.getKey())) {
        //                output.put(entryToAdd.getKey(), entryToAdd.getValue());
        //            }
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @param oldValue
        //         * @param newValue
        //         * @return return the specified {@code output}
        //         */
        //        public static > M replace(final M output, final K key, final V newValue) {
        //            if (output == null || output.size() == 0) {
        //                return output;
        //            }
        //
        //            final V curValue = output.get(key);
        //
        //            if ((curValue != null || output.containsKey(key))) {
        //                output.put(key, newValue);
        //            }
        //
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @param oldValue
        //         * @param newValue
        //         * @return return the specified {@code output}
        //         */
        //        public static > M replace(final M output, final K key, final V oldValue, final V newValue) {
        //            if (output == null || output.size() == 0) {
        //                return output;
        //            }
        //
        //            final V curValue = output.get(key);
        //
        //            if ((curValue != null || output.containsKey(key)) && N.equals(curValue, oldValue)) {
        //                output.put(key, newValue);
        //            }
        //
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M remove(final M output, final Object key) {
        //            if (output == null || output.size() == 0) {
        //                return output;
        //            }
        //
        //            output.remove(key);
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M remove(final M output, final Map.Entry entryToRemove) {
        //            if (output == null || output.size() == 0) {
        //                return output;
        //            }
        //
        //            if (N.equals(output.get(entryToRemove.getKey()), entryToRemove.getValue())) {
        //                output.remove(entryToRemove.getKey());
        //            }
        //
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param key
        //         * @param value
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M remove(final M output, final Object key, final Object value) {
        //            if (output == null || output.size() == 0) {
        //                return output;
        //            }
        //
        //            if (N.equals(output.get(key), value)) {
        //                output.remove(key);
        //            }
        //
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param keys
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M removeAll(final M output, final Collection keys) {
        //            if (output == null || output.size() == 0 || keys == null || keys.size() == 0) {
        //                return output;
        //            }
        //
        //            for (Object key : keys) {
        //                output.remove(key);
        //            }
        //
        //            return output;
        //        }
        //
        //        /**
        //         *
        //         * @param output
        //         * @param entriesToRemove
        //         * @return
        //         * @return return the specified {@code output}
        //         */
        //        public static > M removeAll(final M output, final Map entriesToRemove) {
        //            if (output == null || output.size() == 0 || entriesToRemove == null || entriesToRemove.size() == 0) {
        //                return output;
        //            }
        //
        //            for (Map.Entry entry : entriesToRemove.entrySet()) {
        //                if (N.equals(output.get(entry.getKey()), entry.getValue())) {
        //                    output.remove(entry.getKey());
        //                }
        //            }
        //
        //            return output;
        //        }
    }
}