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

net.openhft.chronicle.testframework.Product Maven / Gradle / Ivy

There is a newer version: 2.27ea0
Show newest version
package net.openhft.chronicle.testframework;

import net.openhft.chronicle.testframework.internal.ProductUtil;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.function.BiFunction;
import java.util.stream.Stream;

import static java.util.Objects.requireNonNull;

public final class Product {

    // Suppresses default constructor, ensuring non-instantiability.
    private Product() {
    }

    /**
     * Creates and returns a Stream representing the Cartesian product of the given {@code ts} and {@code us} collections.
     * 

* This method returns a Stream of {@link Product2} objects, which pairs each element in {@code ts} with each * element in {@code us}. The order of the product is by {@code T} (most significant factor) and then {@code U}. *

* The provided collections must not be {@code null}, or a {@code NullPointerException} will be thrown. *

* Example: * If {@code ts = ["A", "B"]} and {@code us = [1, 2]}, the method will return a Stream with elements: * {@code [("A", 1), ("A", 2), ("B", 1), ("B", 2)]}. * * @param The element type for the first collection * @param The element type for the second collection * @param ts The first collection of elements (non-null) * @param us The second collection of elements (non-null) * @return the Cartesian product of the given elements, represented as a Stream of {@link Product2} objects * @throws NullPointerException if any of the provided collections are {@code null} */ public static Stream> of(@NotNull final Collection ts, @NotNull final Collection us) { // Ensure that the provided collections are not null requireNonNull(ts, "The first collection (ts) must not be null"); requireNonNull(us, "The second collection (us) must not be null"); // Utilize a helper method from ProductUtil to generate the Cartesian product and return as a stream return of(ts, us, ProductUtil.Product2Impl::new); } /** * Creates and returns the cartesian product of the given elements by applying the provided * {@code constructor} to each tuple (pair of elements). *

* This method calculates the Cartesian product of two collections, {@code ts} and {@code us}, * by pairing each element in {@code ts} with each element in {@code us} and applying the provided * {@code constructor} to each pair. The order of the product is determined first by {@code T} * (most significant factor) and then by {@code U}. *

* Example: * If {@code ts = ["A", "B"]} and {@code us = [1, 2]}, and the constructor concatenates the elements, * the method will return a Stream with elements {@code ["A1", "A2", "B1", "B2"]}. * * @param Element type for the first collection * @param Element type for the second collection * @param Return type after applying the constructor to each tuple * @param ts The first collection of elements (non-null) * @param us The second collection of elements (non-null) * @param constructor A BiFunction to be applied to all pairs, creating the result type {@code R} (non-null) * @return A Stream representing the Cartesian product of the given elements after applying the constructor * @throws NullPointerException if any of the provided parameters are {@code null} */ public static Stream of(@NotNull final Collection ts, @NotNull final Collection us, @NotNull final BiFunction constructor) { // Ensure that the provided collections and constructor are not null requireNonNull(ts, "The first collection (ts) must not be null"); requireNonNull(us, "The second collection (us) must not be null"); requireNonNull(constructor, "The constructor function must not be null"); // Utilize a helper method from ProductUtil to generate the Cartesian product and return as a stream return ProductUtil.of(ts, us, constructor); } /** * Creates and returns the cartesian product of the given elements by applying a default * Product2 constructor to each tuple. *

* The cartesian product is the combination of all possible pairs between the first stream {@code ts} and the second stream {@code us}. * The order of the product is by {@code T} (most significant factor) and then {@code U}. *

* This method applies a default constructor {@code ProductUtil.Product2Impl::new} to create objects of type {@code Product2} * representing each tuple in the product. * * @param element type for the first factor order * @param element type for the second factor order * @param ts the first factor order (non-null) * @param us the second factor order (non-null) * @return a Stream of {@code Product2} representing the cartesian product of the given elements * @throws NullPointerException if any of the provided parameters are {@code null}. */ public static Stream> of(@NotNull final Stream ts, @NotNull final Stream us) { requireNonNull(ts, "The first stream (ts) must not be null"); requireNonNull(us, "The second stream (us) must not be null"); return of(ts, us, ProductUtil.Product2Impl::new); } /** * Creates and returns the cartesian product of the given elements by applying the provided * {@code constructor} to each tuple. *

* Similar to the previous method, this function creates pairs of all possible combinations * between two streams, {@code ts} and {@code us}, and then applies the provided {@code constructor} * to each pair to create objects of type {@code R}. *

* The order of the product is determined first by {@code T} (most significant factor) and then by {@code U}. * The provided stream {@code ts} is consumed lazily, and the other provided streams are not. * * @param Element type for the first stream * @param Element type for the second stream * @param Return type after applying the constructor to each tuple * @param ts The first stream of elements (non-null) * @param us The second stream of elements (non-null) * @param constructor A BiFunction to be applied to all pairs, creating the result type {@code R} (non-null) * @return A Stream representing the Cartesian product of the given elements after applying the constructor * @throws NullPointerException if any of the provided parameters are {@code null} */ public static Stream of(@NotNull final Stream ts, @NotNull final Stream us, @NotNull final BiFunction constructor) { requireNonNull(ts, "The first stream (ts) must not be null"); requireNonNull(us, "The second stream (us) must not be null"); requireNonNull(constructor, "The constructor function must not be null"); return ProductUtil.of(ts, us, constructor); } /** * Creates and returns the cartesian product of the given elements by applying a default * Product3 constructor to each tuple. *

* The cartesian product is formed by creating all possible combinations of the three * collections {@code ts}, {@code us}, and {@code vs}, with the order being determined first * by {@code T} (most significant factor), then by {@code U}, and finally by {@code V}. *

* The default constructor {@code ProductUtil.Product3Impl::new} is used to create objects of type * {@code Product3} representing each tuple in the product. * * @param element type for the first factor order * @param element type for the second factor order * @param element type for the third factor order * @param ts the first factor order (non-null) * @param us the second factor order (non-null) * @param vs the third factor order (non-null) * @return a Stream of {@code Product3} representing the cartesian product of the given elements * @throws NullPointerException if any of the provided parameters are {@code null}. */ public static Stream> of(@NotNull final Collection ts, @NotNull final Collection us, @NotNull final Collection vs) { requireNonNull(ts, "The first collection (ts) must not be null"); requireNonNull(us, "The second collection (us) must not be null"); requireNonNull(vs, "The third collection (vs) must not be null"); return of(ts, us, vs, ProductUtil.Product3Impl::new); } /** * Creates and returns the cartesian product of the given elements by applying the provided * {@code constructor} to each tuple. *

* Similar to the previous method, this function creates all possible combinations between * the three collections {@code ts}, {@code us}, and {@code vs}, and then applies the provided * {@code constructor} to each tuple to create objects of type {@code R}. *

* The order of the product is determined first by {@code T} (most significant factor), then * by {@code U}, and finally by {@code V}. * * @param Element type for the first collection * @param Element type for the second collection * @param Element type for the third collection * @param Return type after applying the constructor to each tuple * @param ts The first collection of elements (non-null) * @param us The second collection of elements (non-null) * @param vs The third collection of elements (non-null) * @param constructor A TriFunction to be applied to all tuples, creating the result type {@code R} (non-null) * @return A Stream representing the Cartesian product of the given elements after applying the constructor * @throws NullPointerException if any of the provided parameters are {@code null} */ public static Stream of(@NotNull final Collection ts, @NotNull final Collection us, @NotNull final Collection vs, @NotNull final TriFunction constructor) { requireNonNull(ts, "The first collection (ts) must not be null"); requireNonNull(us, "The second collection (us) must not be null"); requireNonNull(vs, "The third collection (vs) must not be null"); requireNonNull(constructor, "The constructor function must not be null"); return ProductUtil.of(ts, us, vs, constructor); } /** * Creates and returns the cartesian product of the given elements by applying a default * Product3 constructor to each tuple. *

* The order of the product is by T (most significant factor) and then U and then V. The provided stream * {@code ts} is consumed lazily, and the other provided streams are not, which allows for more efficient * processing of large or infinite streams. *

* The default constructor {@code ProductUtil.Product3Impl::new} is used to represent each tuple in the product. * * @param element type for the first factor order * @param element type for the second factor order * @param element type for the third factor order * @param ts the first factor order (non-null) * @param us the second factor order (non-null) * @param vs the third factor order (non-null) * @return a Stream of {@code Product3} representing the cartesian product of the given elements * @throws NullPointerException if any of the provided parameters are {@code null}. */ public static Stream> of(@NotNull final Stream ts, @NotNull final Stream us, @NotNull final Stream vs) { requireNonNull(ts, "The first stream (ts) must not be null"); requireNonNull(us, "The second stream (us) must not be null"); requireNonNull(vs, "The third stream (vs) must not be null"); return of(ts, us, vs, ProductUtil.Product3Impl::new); } /** * Creates and returns the cartesian product of the given elements by applying the provided * {@code constructor} to each tuple. *

* This function creates all possible combinations between the three streams {@code ts}, {@code us}, * and {@code vs}, and then applies the provided {@code constructor} to each tuple to create objects * of type {@code R}. *

* The order of the product is determined first by {@code T} (most significant factor), then * by {@code U}, and finally by {@code V}. The stream {@code ts} is consumed lazily, while the * others are not. * * @param Element type for the first stream * @param Element type for the second stream * @param Element type for the third stream * @param Return type after applying the constructor to each tuple * @param ts The first stream of elements (non-null) * @param us The second stream of elements (non-null) * @param vs The third stream of elements (non-null) * @param constructor A TriFunction to be applied to all tuples, creating the result type {@code R} (non-null) * @return A Stream representing the cartesian product of the given elements after applying the constructor * @throws NullPointerException if any of the provided parameters are {@code null} */ public static Stream of(@NotNull final Stream ts, @NotNull final Stream us, @NotNull final Stream vs, @NotNull final TriFunction constructor) { requireNonNull(ts, "The first stream (ts) must not be null"); requireNonNull(us, "The second stream (us) must not be null"); requireNonNull(vs, "The third stream (vs) must not be null"); requireNonNull(constructor, "The constructor function must not be null"); return ProductUtil.of(ts, us, vs, constructor); } /** * Function interface representing a function that accepts three arguments and produces a result. * * @param Type of the first argument * @param Type of the second argument * @param Type of the third argument * @param Type of the result */ @FunctionalInterface public interface TriFunction { /** * Applies this function to the given arguments, creating a result of type {@code R}. *

* This functional interface is used to apply custom behavior to tuples within the cartesian * product, allowing for flexible creation of objects to represent those tuples. * * @param t the first function argument * @param u the second function argument * @param v the third function argument * @return the function result, which can be of any type {@code R} */ R apply(T t, U u, V v); } /** * An interface representing an object that has a first component. * This can be used to add functionality to objects that are made up of multiple components. * * @param The type of the first component. */ public interface HasFirst { /** * Returns the first component of the object. * This method should be implemented to return the first component of the multi-component object. * * @return The first component of the object. */ T first(); } /** * An interface representing an object that has a second component. * This can be used to add functionality to objects that are made up of multiple components. * * @param The type of the second component. */ public interface HasSecond { /** * Returns the second component of the object. * This method should be implemented to return the second component of the multi-component object. * * @return The second component of the object. */ U second(); } /** * Interface representing an object that has a third component of type {@code V}. * This can be used to add functionality to objects that are made up of three components. * * @param Type of the third component */ public interface HasThird { /** * Returns the third component of the object. * This method should be implemented to return the third component of the multi-component object. * * @return The third component of the object. */ V third(); } /** * A Product2 is a composite object comprising two components. * It's a part of a tuple-like structure with two elements, extending the HasFirst and HasSecond interfaces. * This provides a way to group two related objects together into a single unit. * * @param Type of the first component * @param Type of the second component */ public interface Product2 extends HasFirst, HasSecond { // Interface doesn't have any additional methods or fields, but inherits those from HasFirst and HasSecond. } /** * A Product3 is a composite object comprising three components. * It's a part of a tuple-like structure with three elements, extending the HasFirst, HasSecond, and HasThird interfaces. * This provides a way to group three related objects together into a single unit. * * @param Type of the first component * @param Type of the second component * @param Type of the third component */ public interface Product3 extends HasFirst, HasSecond, HasThird { // Interface doesn't have any additional methods or fields, but inherits those from HasFirst, HasSecond, and HasThird. } }