com.fuzzylite.Op Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jfuzzylite Show documentation
Show all versions of jfuzzylite Show documentation
jfuzzylite(TM) is a free and open-source fuzzy logic control library
programmed in Java. The goal of jfuzzylite is to easily design and
efficiently operate fuzzy logic controllers following an object-oriented
model without relying on external libraries.
jfuzzylite is the Java equivalent of the fuzzylite(R) library.
jfuzzylite is a trademark of FuzzyLite Limited.
fuzzylite is a registered trademark of FuzzyLite Limited.
The newest version!
/*
jfuzzylite (TM), a fuzzy logic control library in Java.
Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
Author: Juan Rada-Vilela, Ph.D.
This file is part of jfuzzylite.
jfuzzylite is free software: you can redistribute it and/or modify it under
the terms of the FuzzyLite License included with the software.
You should have received a copy of the FuzzyLite License along with
jfuzzylite. If not, see .
jfuzzylite is a trademark of FuzzyLite Limited.
fuzzylite (R) is a registered trademark of FuzzyLite Limited.
*/
package com.fuzzylite;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
The Op class (short for Operation) contains methods for numeric operations,
string manipulation, and other functions.
@author Juan Rada-Vilela, Ph.D.
@since 4.0
*/
public class Op {
/**
Returns the minimum between the two parameters
@param a
@param b
@return `\min(a,b)`
*/
public static double min(double a, double b) {
if (Double.isNaN(a)) {
return b;
}
if (Double.isNaN(b)) {
return a;
}
return a < b ? a : b;
}
/**
Returns the maximum between the two parameters
@param a
@param b
@return `\max(a,b)`
*/
public static double max(double a, double b) {
if (Double.isNaN(a)) {
return b;
}
if (Double.isNaN(b)) {
return a;
}
return a > b ? a : b;
}
/**
Returns `x` bounded in `[\min,\max]`
@param x is the value to be bounded
@param min is the minimum value of the range
@param max is the maximum value of the range
@return ` \begin{cases} \min & \mbox{if $x < \min$} \cr
\max & \mbox{if $x > \max$} \cr x & \mbox{otherwise} \end{cases}
`
*/
public static double bound(double x, double min, double max) {
if (x > max) {
return max;
}
if (x < min) {
return min;
}
return x;
}
/**
Indicates whether `x` is within the closed boundaries
@param x is the value
@param min is the minimum of the range
@param max is the maximum of the range
@return ` \begin{cases} x \in [\min,\max] & \mbox{if $geq \wedge leq$}
\cr x \in (\min,\max] & \mbox{if $geq \wedge \bar{leq}$} \cr x \in [\min,
\max) & \mbox{if $\bar{geq} \wedge leq$} \cr x \in (\min, \max) & \mbox{if
$\bar{geq} \wedge \bar{leq}$} \cr \end{cases}
`
*/
public static boolean in(double x, double min, double max) {
return in(x, min, max, true, true);
}
/**
Indicates whether `x` is within the boundaries (open or closed)
@param x is the value
@param min is the minimum of the range
@param max is the maximum of the range
@param geq determines whether the maximum is a closed interval
@param leq determines whether the minimum is a closed interval
@return ` \begin{cases} x \in [\min,\max] & \mbox{if $geq \wedge leq$}
\cr x \in (\min,\max] & \mbox{if $geq \wedge \bar{leq}$} \cr x \in [\min,
\max) & \mbox{if $\bar{geq} \wedge leq$} \cr x \in (\min, \max) & \mbox{if
$\bar{geq} \wedge \bar{leq}$} \cr \end{cases}
`
*/
public static boolean in(double x, double min, double max, boolean geq,
boolean leq) {
boolean left = geq ? isGE(x, min) : isGt(x, min);
boolean right = leq ? isLE(x, max) : isLt(x, max);
return (left && right);
}
/**
Indicates whether `x` is finite, that is, `x \not\in \{\pm\infty,
\mathrm{NaN}\}`
@param x is the value
@return whether `x` is finite
*/
public static boolean isFinite(double x) {
return !(Double.isNaN(x) || Double.isInfinite(x));
}
/*
* Math Operations
*/
/**
Returns whether `a` is equal to `b` at the default tolerance
@param a
@param b
@return whether `a` is equal to `b` at the default tolerance
*/
public static boolean isEq(double a, double b) {
return a == b || Math.abs(a - b) < FuzzyLite.macheps || (Double.isNaN(a) && Double.isNaN(b));
}
/**
Returns whether `a` is equal to `b` at the given tolerance
@param a
@param b
@param macheps is the minimum difference upon which two floating-point
values are considered equivalent
@return whether `a` is equal to `b` at the given tolerance
*/
public static boolean isEq(double a, double b, double macheps) {
return a == b || Math.abs(a - b) < macheps || (Double.isNaN(a) && Double.isNaN(b));
}
/**
Returns whether `a` is different from `b` at the default tolerance
@param a
@param b
@return whether `a` is different from `b` at the default tolerance
*/
public static boolean isNEq(double a, double b) {
return !(a == b || Math.abs(a - b) < FuzzyLite.macheps || (Double.isNaN(a) && Double.isNaN(b)));
}
/**
Returns whether `a` is different from `b` at the given tolerance
@param a
@param b
@param macheps is the minimum difference upon which two floating-point
values are considered equivalent
@return whether `a` is different from `b` at the given tolerance
*/
public static boolean isNEq(double a, double b, double macheps) {
return !(a == b || Math.abs(a - b) < macheps || (Double.isNaN(a) && Double.isNaN(b)));
}
/**
Returns whether `a` is less than `b` at the default tolerance
@param a
@param b
@return whether `a` is less than `b` at the default tolerance
*/
public static boolean isLt(double a, double b) {
return !(a == b || Math.abs(a - b) < FuzzyLite.macheps || (Double.isNaN(a) && Double.isNaN(b)))
&& a < b;
}
/**
Returns whether `a` is less than `b` at the given tolerance
@param a
@param b
@param macheps is the minimum difference upon which two floating-point
values are considered equivalent
@return whether `a` is less than `b` at the given tolerance
*/
public static boolean isLt(double a, double b, double macheps) {
return !(a == b || Math.abs(a - b) < macheps || (Double.isNaN(a) && Double.isNaN(b)))
&& a < b;
}
/**
Returns whether `a` is less than or equal to `b` at the default
tolerance
@param a
@param b
@return whether `a` is less than or equal to `b` at the default
tolerance
*/
public static boolean isLE(double a, double b) {
return a == b || Math.abs(a - b) < FuzzyLite.macheps || (Double.isNaN(a) && Double.isNaN(b))
|| a < b;
}
/**
Returns whether `a` is less than or equal to `b` at the given
tolerance
@param a
@param b
@param macheps is the minimum difference upon which two floating-point
values are considered equivalent
@return whether `a` is less than or equal to `b` at the given
tolerance
*/
public static boolean isLE(double a, double b, double macheps) {
return a == b || Math.abs(a - b) < macheps || (Double.isNaN(a) && Double.isNaN(b))
|| a < b;
}
/**
Returns whether `a` is greater than `b` at the default tolerance
@param a
@param b
@return whether `a` is greater than `b` at the given tolerance
*/
public static boolean isGt(double a, double b) {
return !(a == b || Math.abs(a - b) < FuzzyLite.macheps || (Double.isNaN(a) && Double.isNaN(b)))
&& a > b;
}
/**
Returns whether `a` is greater than `b` at the given tolerance
@param a
@param b
@param macheps is the minimum difference upon which two floating-point
values are considered equivalent
@return whether `a` is greater than `b` at the given tolerance
*/
public static boolean isGt(double a, double b, double macheps) {
return !(a == b || Math.abs(a - b) < macheps || (Double.isNaN(a) && Double.isNaN(b)))
&& a > b;
}
/**
Returns whether `a` is greater than or equal to `b` at the default
tolerance
@param a
@param b
@return whether `a` is greater than or equal to `b` at the default
tolerance
*/
public static boolean isGE(double a, double b) {
return a == b || Math.abs(a - b) < FuzzyLite.macheps || (Double.isNaN(a) && Double.isNaN(b))
|| a > b;
}
/**
Returns whether `a` is greater than or equal to `b` at the given
tolerance
@param a
@param b
@param macheps is the minimum difference upon which two floating-point
values are considered equivalent
@return whether `a` is greater than or equal to `b` at the given
tolerance
*/
public static boolean isGE(double a, double b, double macheps) {
return a == b || Math.abs(a - b) < macheps || (Double.isNaN(a) && Double.isNaN(b))
|| a > b;
}
/**
Returns whether `a` is equal to `b` at the default tolerance
@param a
@param b
@return whether `a` is equal to `b` at the default tolerance
*/
public static double eq(double a, double b) {
return isEq(a, b) ? 1.0 : 0.0;
}
/**
Returns whether `a` is different from `b` at the default tolerance
@param a
@param b
@return whether `a` is different from `b` at the default tolerance
*/
public static double neq(double a, double b) {
return isNEq(a, b) ? 1.0 : 0.0;
}
/**
Returns whether `a` is less than `b` at the default tolerance
@param a
@param b
@return whether `a` is less than `b` at the default tolerance
*/
public static double lt(double a, double b) {
return isLt(a, b) ? 1.0 : 0.0;
}
/**
Returns whether `a` is less than or equal to `b` at the default
tolerance
@param a
@param b
@return whether `a` is less than or equal to `b` at the default
tolerance
*/
public static double le(double a, double b) {
return isLE(a, b) ? 1.0 : 0.0;
}
/**
Returns whether `a` is greater than or equal to `b` at the default
tolerance
@param a
@param b
@return whether `a` is greater than or equal to `b` at the default
tolerance
*/
public static double gt(double a, double b) {
return isGt(a, b) ? 1.0 : 0.0;
}
/**
Returns whether `a` is greater than or equal to `b` at the default
tolerance
@param a
@param b
@return whether `a` is greater than or equal to `b` at the default
tolerance
*/
public static double ge(double a, double b) {
return isGE(a, b) ? 1.0 : 0.0;
}
/**
Adds two values
@param a
@param b
@return `a+b`
*/
public static double add(double a, double b) {
return a + b;
}
/**
Subtracts two values
@param a
@param b
@return `a-b`
*/
public static double subtract(double a, double b) {
return a - b;
}
/**
Multiplies two values
@param a
@param b
@return `a\times b`
*/
public static double multiply(double a, double b) {
return a * b;
}
/**
Divides two values
@param a
@param b
@return `a/b`
*/
public static double divide(double a, double b) {
return a / b;
}
/**
Computes the modulo
@param a
@param b
@return `a \mod b`
*/
public static double modulo(double a, double b) {
return a % b;
}
/**
Computes the logical AND
@param a
@param b
@return ` \begin{cases} 1.0 & \mbox{if $a=1 \wedge b=1$}\cr 0.0 &
\mbox{otherwise} \end{cases}
`
*/
public static double logicalAnd(double a, double b) {
return (isEq(a, 1.0) && isEq(b, 1.0)) ? 1.0 : 0.0;
}
/**
Computes the logical OR
@param a
@param b
@return ` \begin{cases} 1.0 & \mbox{if $a=1 \vee b=1$}\cr 0.0 &
\mbox{otherwise} \end{cases}
`
*/
public static double logicalOr(double a, double b) {
return (isEq(a, 1.0) || isEq(b, 1.0)) ? 1.0 : 0.0;
}
/**
Returns the complement of the value
@param a
@return ` \begin{cases} 0.0 & \mbox{if $a=1$}\cr 1.0 & \mbox{otherwise}
\end{cases}
`
*/
public static double logicalNot(double a) {
return isEq(a, 1.0) ? 0.0 : 1.0;
}
/**
Negates the value
@param a
@return -a
*/
public static double negate(double a) {
return -a;
}
/**
Linearly interpolates the parameter `x` in range `[fromMin,fromMax]` to
a new value in the range `[toMin,toMax]`
@param x is the source value to interpolate
@param fromMin is the minimum value of the source range
@param fromMax is the maximum value of the source range
@param toMin is the minimum value of the target range
@param toMax is the maximum value of the target range
@return the source value linearly interpolated to the target range:
` y = y_a + (y_b - y_a) \dfrac{x-x_a}{x_b-x_a} `
*/
public static double scale(double x, double fromMin, double fromMax,
double toMin, double toMax) {
return (toMax - toMin) / (fromMax - fromMin) * (x - fromMin) + toMin;
}
/**
Linearly interpolates the parameter `x` in range `[fromMin,fromMax]` to
a new value in the range `[toMin,toMax]`, truncated to the range
`[toMin,toMax]` if bounded is `true`.
@param x is the source value to interpolate
@param fromMin is the minimum value of the source range
@param fromMax is the maximum value of the source range
@param toMin is the minimum value of the target range
@param toMax is the maximum value of the target range
@param bounded determines whether the resulting value is bounded to the
range
@return the source value linearly interpolated to the target range:
` y = y_a + (y_b - y_a) \dfrac{x-x_a}{x_b-x_a} `
*/
public static double scale(double x, double fromMin, double fromMax,
double toMin, double toMax, boolean bounded) {
double result = (toMax - toMin) / (fromMax - fromMin) * (x - fromMin)
+ toMin;
return bounded ? Op.bound(x, toMin, toMax) : result;
}
/**
Computes the sum of the array
@param x is the array of elements
@return the sum of the array
*/
public static double sum(double[] x) {
double result = 0.0;
for (double i : x) {
result += i;
}
return result;
}
/**
Computes the mean of the array
@param x is the array
@return `\dfrac{\sum_i{x_i}}{|x|}`
*/
public static double mean(double[] x) {
return sum(x) / x.length;
}
/**
Computes the variance of the array
@param x is the array
@return ` \sum_i{ (x_i - \bar{x})^2 } / (|x| - 1) `
*/
public static double variance(double[] x) {
return variance(x, mean(x));
}
/**
Computes the variance of the vector using the given mean
@param x is the vector
@param mean is the mean value of the vector
@return ` \sum_i{ (x_i - \bar{x})^2 } / (|x| - 1) `
*/
public static double variance(double[] x, double mean) {
if (x.length == 0) {
return Double.NaN;
}
if (x.length == 1) {
return 0.0;
}
double result = 0.0;
for (double i : x) {
result += (i - mean) * (i - mean);
}
result /= -1 + x.length;
return result;
}
/**
Computes the standard deviation of the vector
@param x
@return ` \sqrt{\mbox{variance}(x, \bar{x})} `
*/
public static double standardDeviation(double[] x) {
return standardDeviation(x, mean(x));
}
/**
Computes the standard deviation of the vector using the given mean
@param x
@param mean is the mean value of x
@return ` \sqrt{\mbox{variance}(x, \bar{x})} `
*/
public static double standardDeviation(double[] x, double mean) {
if (x.length == 0) {
return Double.NaN;
}
if (x.length == 1) {
return 0.0;
}
return Math.sqrt(variance(x, mean));
}
/**
Splits the string around the given delimiter ignoring empty splits
@param string is the string to split
@param delimiter is the substrings on which the string will be split
@return the string split around the given delimiter
*/
public static List split(String string, String delimiter) {
return split(string, delimiter, true);
}
/**
Splits the string around the given delimiter
@param string is the string to split
@param delimiter is the substrings on which the string will be split
@param ignoreEmpty whether the empty strings are discarded
@return the string split around the given delimiter
*/
public static List split(String string, String delimiter,
boolean ignoreEmpty) {
List result = new ArrayList();
if (string.isEmpty() || delimiter.isEmpty()) {
result.add(string);
return result;
}
int position = 0, next = 0;
while (next >= 0) {
next = string.indexOf(delimiter, position);
String token;
if (next < 0) {
token = string.substring(position);
} else {
token = string.substring(position, next);
}
if (!(token.isEmpty() && ignoreEmpty)) {
result.add(token);
}
if (next >= 0) {
position = next + delimiter.length();
}
}
return result;
}
/**
Parses the given string into a scalar value without throwing an exception
@param x is the string to parse
@param alternative is the value to return if the string does not contain a
scalar value
@return the given string into a scalar value or the alternative value if
the string does not contain a scalar value
*/
public static double toDouble(String x, double alternative) {
try {
return toDouble(x);
} catch (Exception ex) {
return alternative;
}
}
/**
Parses the given string into a scalar value
@param x is the string to parse
@return the given string into a scalar value
@throws NumberFormatException if the string does not contain a scalar value
*/
public static double toDouble(String x) throws NumberFormatException {
if ("nan".equals(x)) {
return Double.NaN;
}
if ("inf".equals(x)) {
return Double.POSITIVE_INFINITY;
}
if ("-inf".equals(x)) {
return Double.NEGATIVE_INFINITY;
}
return Double.parseDouble(x);
}
/**
Parses the given string into an array of scalar values
@param x is the string containing space-separated values to parse
@return the vector of scalar values
@throws NumberFormatException if the string contains an invalid scalar
value
*/
public static double[] toDoubles(String x) throws NumberFormatException {
String[] tokens = x.split("\\s+");
double[] result = new double[tokens.length];
for (int i = 0; i < tokens.length; ++i) {
result[i] = Op.toDouble(tokens[i]);
}
return result;
}
/**
Parses the given string into a vector of scalar values
@param x is the string containing space-separated values to parse
@param alternative is the value to use if an invalid value is found
@return the vector of scalar values
*/
public static double[] toDoubles(String x, double alternative) throws NumberFormatException {
String[] tokens = x.split("\\s+");
double[] result = new double[tokens.length];
for (int i = 0; i < tokens.length; ++i) {
result[i] = Op.toDouble(tokens[i], alternative);
}
return result;
}
/**
Indicates whether the string can be converted to a numeric value.
@param x
@return whether the string can be converted to a numeric value
*/
public static boolean isNumeric(String x) {
try {
toDouble(x);
return true;
} catch (Exception ex) {
return false;
}
}
/**
Increments `x` by the unit, treating the entire vector as a number. For
example, incrementing a few times `x_0=\{0,0\}` within boundaries
`[0,1]` results in: `x_1=\{0,1\}`,
`x_2=\{1,0\}`, `x_3=\{1,1\}`, `x_4=\{0,0\}`.
@param array is the array to increment
@param min is the minimum value of the dimension
@param max is the maximum value of the dimension
@return `true` if `x` was incremented, `false` otherwise (e.g.,
incrementing `x_3` returns `false`). In earlier versions to 6.0, the
result was the inverse and indicated whether the counter had overflown
(most sincere apologies for this change).
*/
public static boolean increment(int[] array, int[] min, int[] max) {
return increment(array, array.length - 1, min, max);
}
/**
Increments `x` by the unit at the given position, treating the entire
vector as a number. For example, incrementing
`x_0=\{0,0,0\}` within boundaries `[0,1]` at the second position
results in: `x_1=\{0,1,0\}`, `x_2=\{1,0,0\}`,
`x_3=\{1,1,0\}`, `x_4=\{0,0,0\}`.
@param array is the vector to increment
@param position is the position of the vector to increment, where smaller
values lead to higher significance digits
@param min is the minimum value of the dimension
@param max is the maximum value of the dimension
@return `true` if `x` was incremented, `false` otherwise (e.g.,
incrementing `x_3` returns `false`). In earlier versions to 6.0, the
result was the inverse and indicated whether the counter had overflown
(most sincere apologies for this change).
*/
public static boolean increment(int[] array, int position, int[] min, int[] max) {
if (array.length == 0 || position < 0) {
return false;
}
boolean incremented = true;
if (array[position] < max[position]) {
++array[position];
} else {
incremented = !(position == 0);
array[position] = min[position];
--position;
if (position >= 0) {
incremented = increment(array, position, min, max);
}
}
return incremented;
}
/**
Returns a string representation of the given value
@tparam T determines the class type of the value
@param x is the value
@return a string representation of the given value
*/
public static String str(T x) {
return str(x, FuzzyLite.getFormatter());
}
/**
Returns a string representation of the given value
@tparam T determines the class type of the value
@param x is the value
@param formatter is the decimal formatter of scalar values
@return a string representation of the given value
*/
public static String str(T x, DecimalFormat formatter) {
if (Double.isNaN(x.doubleValue())) {
return "nan";
}
if (Double.isInfinite(x.doubleValue())) {
return isLt(x.doubleValue(), 0.0) ? "-inf" : "inf";
}
return formatter.format(x);
}
/**
Joins an array of elements by the given separator into a single string. The
elements are represented as strings utilizing the Op.str() method on each
element
@tparam T determines the class type of the value
@param x is the array of elements
@param separator is the string to add between the elements
@return a single string joining the array of elements by the given
separator
*/
public static String join(Collection x, String separator) {
StringBuilder result = new StringBuilder();
for (Iterator it = x.iterator(); it.hasNext();) {
T item = it.next();
if (item instanceof Number) {
result.append(Op.str((Number) item));
} else {
result.append(item.toString());
}
if (it.hasNext()) {
result.append(separator);
}
}
return result.toString();
}
/**
Joins an array of elements by the given separator into a single string. The
elements are represented as strings utilizing the Op.str() method on each
element
@param x is the array of elements
@param separator is the string to add between the elements
@return a single string joining the array of elements by the given
separator
*/
public static String join(long[] x, String separator) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < x.length; ++i) {
result.append(str(x[i]));
if (i + 1 < x.length) {
result.append(separator);
}
}
return result.toString();
}
/**
Joins an array of elements by the given separator into a single string. The
elements are represented as strings utilizing the Op.str() method on each
element
@param x is the array of elements
@param separator is the string to add between the elements
@return a single string joining the array of elements by the given
separator
*/
public static String join(int[] x, String separator) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < x.length; ++i) {
result.append(str(x[i]));
if (i + 1 < x.length) {
result.append(separator);
}
}
return result.toString();
}
/**
Joins an array of elements by the given separator into a single string. The
elements are represented as strings utilizing the Op.str() method on each
element
@param x is the array of elements
@param separator is the string to add between the elements
@return a single string joining the array of elements by the given
separator
*/
public static String join(double[] x, String separator) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < x.length; ++i) {
result.append(str(x[i]));
if (i + 1 < x.length) {
result.append(separator);
}
}
return result.toString();
}
/**
Joins an array of elements by the given separator into a single string. The
elements are represented as strings utilizing the Op.str() method on each
element
@param x is the array of elements
@param separator is the string to add between the elements
@return a single string joining the array of elements by the given
separator
*/
public static String join(float[] x, String separator) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < x.length; ++i) {
result.append(str(x[i]));
if (i + 1 < x.length) {
result.append(separator);
}
}
return result.toString();
}
/**
Joins an array of elements by the given separator into a single string.
@param x is the array of elements
@param separator is the string to add between the elements
@return a single string joining the array of elements by the given
separator
*/
public static String join(String[] x, String separator) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < x.length; ++i) {
result.append(x[i]);
if (i + 1 < x.length) {
result.append(separator);
}
}
return result.toString();
}
/**
Joins a variadic number of elements by the given separator into a single
string. The elements are represented as strings utilizing the Op.str()
method on each element
@tparam T determines the type of elements in the array
@param separator is the string to add between the elements
@param items are the elements to join
@return a single string joining the variadic number of elements by the
given separator
*/
@SuppressWarnings("unchecked")
public static String join(String separator, T... items) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < items.length; ++i) {
T item = items[i];
if (item instanceof Number) {
result.append(Op.str((Number) item));
} else {
result.append(item.toString());
}
if (i + 1 < items.length) {
result.append(separator);
}
}
return result.toString();
}
/**
Returns a valid name for variables
@param name
@return an name whose characters are in `[a-zA-Z_0-9.]`
*/
public static String validName(String name) {
if (name == null || name.trim().isEmpty()) {
return "unnamed";
}
StringBuilder result = new StringBuilder();
for (char c : name.toCharArray()) {
if (c == '_' || c == '.' || Character.isLetterOrDigit(c)) {
result.append(c);
}
}
return result.toString();
}
/**
Indicates whether the string is empty
@param string is the string to test
@return true if the string is null or empty, false otherwise
*/
public static boolean isEmpty(String string) {
return string == null || string.length() == 0;
}
/**
Cloneable is an interface that provides a public method to clone
*/
public interface Cloneable extends java.lang.Cloneable {
Object clone() throws CloneNotSupportedException;
}
/**
Pair is a handy class to store pairs of elements of any class type
@param is the class of the first element
@param is the class of the second element
*/
public static class Pair {
private Y first;
private Z second;
public Pair() {
this(null, null);
}
public Pair(Y first, Z second) {
this.first = first;
this.second = second;
}
@Override
public String toString() {
return "{" + this.first + ":" + this.second + "}";
}
/**
Gets the first element stored in the pair
@return the first element stored in the pair
*/
public Y getFirst() {
return first;
}
/**
Sets the first element to store in the pair
@param first is the first element to store in the pair
*/
public void setFirst(Y first) {
this.first = first;
}
/**
Gets the second element stored in the pair
@return the second element stored in the pair
*/
public Z getSecond() {
return second;
}
/**
Sets the second element to store in the pair
@param second is the second element to store in the pair
*/
public void setSecond(Z second) {
this.second = second;
}
}
}