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

org.nerd4j.utils.tuple.ComparablePair Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * Nerd4j Core
 * %%
 * Copyright (C) 2011 - 2013 Nerd4j
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nerd4j.utils.tuple;

import org.nerd4j.utils.lang.Comparative;
import org.nerd4j.utils.lang.Emptily;
import org.nerd4j.utils.lang.Require;
import org.nerd4j.utils.math.CU;

import java.util.Comparator;


/**
 * Represents an immutable and comparable pair of values.
 *
 * 

* The values of the pair can be mutable but the relation, * created by this class, between two instances cannot change. * *

* The values of the pair can be addressed as: *

    *
  • {@code left} and {@code right} or
  • *
  • {@code key} and {@code value}
  • *
* depending on the intended usage. * *

* This class implements {@link Comparable} * so either the values are {@link Comparable} or a * suitable {@link Comparator} should be provided. * *

* This class implements {@link Emptily}. * A pair is considered to be empty if both * of its values are {@code null}. * *

* There are several factory methods that cover all the * most common use cases but, if you need to se up a custom * combination of {@code comparable} and {@code non comparable} * values, you can use the {@link ComparablePair.Builder}. * * @param type of the {@code left} element. * @param type of the {@code right} element. * * @author Massimo Coluzzi * @since 2.0.0 */ public class ComparablePair extends Pair implements Comparative> { /** Il serial version UUID. */ private static final long serialVersionUID = 1L; /** Singleton instance of an empty pair. */ private static final ComparablePair EMPTY = new ComparablePair<>( null, CU.nullFirstNaturalOrderComparator(), null, CU.nullFirstNaturalOrderComparator() ); /** The comparator for the left value. */ private Comparator leftComparator; /** The comparator for the right value. */ private Comparator rightComparator; /* * IMPORTANT NOTE * * There is no default constructor for this * class because this class cannot be serialized! * * When serialized and deserialized again, in the * best case a missing-no-arg constructor exception * will be thrown for the Comparators.NullComparator, * in the worst case the original pair and the * deserialized one will be similar but slightly * different and this may generate sneaky bugs. * * If you need to use pairs in objects intended to * be serialized use the parent class Pair. * To compare those classes you can write your own * comparator or you can use the factory methods * to convert them into ComparablePairs when needed. */ /** * Constructor with parameters. *

* This constructor is intended to be used * by extending classes only. *

* To create a new pair use the factory methods. * * @param left the {@code left} element of the pair. * @param leftComparator the {@link Comparator} for the left element. * @param right the {@code right} element of the pair. * @param rightComparator the {@link Comparator} for the right element. */ protected ComparablePair( L left, Comparator leftComparator, R right, Comparator rightComparator ) { super( left, right ); this.leftComparator = Require.nonNull( leftComparator, "The comparator for the left value is mandatory" ); this.rightComparator = Require.nonNull( rightComparator, "The comparator for the right value is mandatory" ); } /* ***************** */ /* FACTORY METHODS */ /* ***************** */ /** * Returns the singleton instance of an empty {@link ComparablePair}. * * @param type of the element {@code left}. * @param type of the element {@code right}. * @return singleton instance of an empty {@link ComparablePair}. */ @SuppressWarnings("unchecked") public static ComparablePair empty() { return (ComparablePair) EMPTY; } /** * Creates a new {@link ComparablePair} with * the given {@link Comparable} values. *

* This implementation considers {@code null} to be * less than {@code non-null}. Using this method is * the same as invoking * {@code ComparablePair.of(left,false,right,false)}. * * @param type of the {@code left} element. * @param type of the {@code right} element. * @param left the {@code left} element of the pair. * @param right the {@code right} element of the pair. * @return a new comparable pair with the given values. */ public static ,R extends Comparable> ComparablePair of( L left, R right ) { return of( left, false, right, false ); } /** * Creates a new {@link ComparablePair} starting * from the given {@link Pair} of {@link Comparable} * values. *

* This implementation considers {@code null} to be * less than {@code non-null}. Using this method is * the same as invoking * {@code ComparablePair.of(pair,false,false)}. *

* This factory method is {@code null-safe}, if the * given pair is {@code null}, then this method will * return {@code null}. * * @param type of the {@code left} element. * @param type of the {@code right} element. * @param pair the source pair to make {@link Comparable}. * @return a new comparable pair with the given values. */ public static ,R extends Comparable> ComparablePair of( Pair pair ) { return pair != null ? of( pair.left, false, pair.right, false ) : null; } /** * Creates a new {@link ComparablePair} with * the given values. * * @param type of the {@code left} element. * @param type of the {@code right} element. * @param left the {@code left} element of the pair. * @param leftNullLast tells to consider {@code null} to be greater than {@code non-null}. * @param right the {@code right} element of the pair. * @param rightNullLast tells to consider {@code null} to be greater than {@code non-null}. * @return a new comparable pair with the given values. */ public static ,R extends Comparable> ComparablePair of( L left, boolean leftNullLast, R right, boolean rightNullLast ) { return of( left, CU.nullSafeNaturalOrderComparator(leftNullLast), right, CU.nullSafeNaturalOrderComparator(rightNullLast) ); } /** * Creates a new {@link ComparablePair} starting * from the given {@link Pair} of {@link Comparable} * values and applies the given behavior for {@code null} * values. *

* This factory method is {@code null-safe}, if the * given pair is {@code null}, then this method will * return {@code null}. * * @param type of the {@code left} element. * @param type of the {@code right} element. * @param pair the source pair to make {@link Comparable}. * @param leftNullLast tells to consider {@code null} to be greater than {@code non-null}. * @param rightNullLast tells to consider {@code null} to be greater than {@code non-null}. * @return a new comparable pair with the given values. */ public static ,R extends Comparable> ComparablePair of( Pair pair, boolean leftNullLast, boolean rightNullLast ) { return pair != null ? of( pair.left, CU.nullSafeNaturalOrderComparator(leftNullLast), pair.right, CU.nullSafeNaturalOrderComparator(rightNullLast) ) : null; } /** * Creates a new {@link ComparablePair} with * the given values. * * @param type of the {@code left} element. * @param type of the {@code right} element. * @param left the {@code left} element of the pair. * @param leftComparator comparator for values of type {@code }. * @param right the {@code right} element of the pair. * @param rightComparator comparator for values of type {@code }. * @return a new comparable pair with the given values. */ public static ComparablePair of( L left, Comparator leftComparator, R right, Comparator rightComparator ) { return left == null && right == null ? empty() : new ComparablePair<>( left, leftComparator, right, rightComparator ); } /** * Creates a new {@link ComparablePair} starting * from the given {@link Pair} of {@link Comparable} * values and applies the given value comparators. *

* This factory method is {@code null-safe}, if the * given pair is {@code null}, then this method will * return {@code null}. * * @param type of the {@code left} element. * @param type of the {@code right} element. * @param pair the source pair to make {@link Comparable}. * @param leftComparator comparator for values of type {@code }. * @param rightComparator comparator for values of type {@code }. * @return a new comparable pair with the given values. */ public static ComparablePair of( Pair pair, Comparator leftComparator, Comparator rightComparator ) { return pair != null ? of( pair.left, leftComparator, pair.right, rightComparator ) : null; } /** * Creates a new {@link ComparablePair.Builder} with * the given {@code left} value. *

* This implementation considers {@code null} to be * less than {@code non-null}. Using this method is * the same as invoking * {@code ComparablePair.left(value,false)}. * * @param type of the {@code left} element. * @param value the {@code left} element of the pair. * @return a new {@link ComparablePair.Builder} */ public static > ComparablePair.Builder withLeft( L value ) { return withLeft( value, false ); } /** * Creates a new {@link ComparablePair.Builder} with * the given {@code left} values. * * @param type of the {@code left} element. * @param value the {@code left} element of the pair. * @param nullLast tells to consider {@code null} to be greater than {@code non-null}. * @return a new {@link ComparablePair.Builder} */ public static > ComparablePair.Builder withLeft( L value, boolean nullLast ) { return withLeft( value, CU.nullSafeNaturalOrderComparator(nullLast) ); } /** * Creates a new {@link ComparablePair.Builder} with * the given {@code left} values. * * @param type of the {@code left} element. * @param value the {@code left} element of the pair. * @param comparator comparator for values of type {@code }. * @return a new {@link ComparablePair.Builder} */ public static ComparablePair.Builder withLeft( L value, Comparator comparator ) { return new Builder<>( value, comparator ); } /* ********************* */ /* INTERFACE METHODS */ /* ********************* */ /** * {@inheritDoc} */ @Override public int compareTo( ComparablePair other ) { final int value = leftComparator.compare( this.left, other.left ); return value != 0 ? value : rightComparator.compare( this.right, other.right ); } /* *********************** */ /* CONFIGURATION METHODS */ /* *********************** */ /** * Returns the comparator for values of type {@code }. * * @return comparator for values of type {@code }. */ public Comparator getLeftComparator() { return leftComparator; } /** * Returns the comparator for values of type {@code }. * * @return comparator for values of type {@code }. */ public Comparator getRightComparator() { return rightComparator; } /* ***************** */ /* INNER CLASSES */ /* ***************** */ /** * Implementation of the {@code pattern builder} intended to be used * to create {@link ComparablePair}s with custom combination of * {@code comparable} and {@code non comparable} values. * * @param type of the {@code left} element. * * @author Massimo Coluzzi * @since 2.0.0 */ public static class Builder { /** The {@code left} value of the pair. */ private L left; /** Comparator for the {@code left} value of the pair. */ private Comparator leftComparator; /** * Constructor with parameters. *

* This constructor is intended to be used * internaly of by extending classes. * * @param left the {@code left} element of the pair. * @param leftComparator the {@link Comparator} for the left element. */ protected Builder( L left, Comparator leftComparator ) { super(); this.left = left; this.leftComparator = leftComparator; } /* **************** */ /* PUBLIC METHODS */ /* **************** */ /** * Creates a new {@link ComparablePair} with * the given {@code right} value. *

* This implementation considers {@code null} to be * less than {@code non-null}. Using this method is * the same as invoking * {@code Builder.right(value,false)}. * * @param type of the {@code right} element. * @param value the {@code right} element of the pair. * @return a new comparable pair with the given values. */ public > ComparablePair andRight( R value ) { return andRight( value, false ); } /** * Creates a new {@link ComparablePair} with * the given {@code right} values. * * @param type of the {@code right} element. * @param value the {@code right} element of the pair. * @param nullLast tells to consider {@code null} to be greater than {@code non-null}. * @return a new comparable pair with the given values. */ public > ComparablePair andRight( R value, boolean nullLast ) { return andRight( value, CU.nullSafeNaturalOrderComparator(nullLast) ); } /** * Creates a new {@link ComparablePair} with * the given {@code right} values. * * @param type of the {@code right} element. * @param value the {@code right} element of the pair. * @param comparator comparator for values of type {@code }. * @return a new comparable pair with the given values. */ public ComparablePair andRight( R value, Comparator comparator ) { return of( left, leftComparator, value, comparator ); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy