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

net.yetamine.lang.containers.Tuple2 Maven / Gradle / Ivy

There is a newer version: 1.3.0
Show newest version
package net.yetamine.lang.containers;

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Spliterators;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * A rudimentary tuple implementation consisting of two elements.
 *
 * @param 
 *            the type of element #1
 * @param 
 *            the type of element #2
 */
public final class Tuple2 {

    /** Common shared empty tuple. */
    private static final Tuple2 EMPTY = new Tuple2<>(null, null);

    /** Element #1. */
    private final T1 value1;
    /** Element #2. */
    private final T2 value2;

    /**
     * Creates a new instance.
     *
     * @param t1
     *            element #1
     * @param t2
     *            element #2
     */
    private Tuple2(T1 t1, T2 t2) {
        value1 = t1;
        value2 = t2;
    }

    /**
     * Creates a new instance.
     *
     * @param 
     *            the type of element #1
     * @param 
     *            the type of element #2
     * @param t1
     *            element #1
     * @param t2
     *            element #2
     *
     * @return the new instance
     */
    public static  Tuple2 of(T1 t1, T2 t2) {
        return new Tuple2<>(t1, t2);
    }

    /**
     * Converts an {@link java.util.Map.Entry} instance into a tuple.
     *
     * @param 
     *            the type of the entry's key
     * @param 
     *            the type of the entry's value
     * @param entry
     *            the entry to convert. It must not be {@code null}.
     *
     * @return a tuple containing the entry content
     */
    public static  Tuple2 from(Map.Entry entry) {
        return of(entry.getKey(), entry.getValue());
    }

    /**
     * Makes a tuple from the first two elements provided by the given source.
     *
     * @param 
     *            the type of the source's elements
     * @param source
     *            the source to process. It must provide at least two elements.
     *
     * @return a tuple
     *
     * @throws NoSuchElementException
     *             if the source provides too few elements
     */
    public static  Tuple2 from(Iterable source) {
        return from(source.iterator());
    }

    /**
     * Makes a tuple from the first two elements provided by the given source.
     *
     * @param 
     *            the type of the source's elements
     * @param source
     *            the source to process. It must provide at least two elements.
     *
     * @return a tuple
     *
     * @throws NoSuchElementException
     *             if the source provides too few elements
     */
    public static  Tuple2 from(Iterator source) {
        return of(source.next(), source.next());
    }

    /**
     * Returns an empty tuple (consisting of {@code null} elements).
     *
     * @param 
     *            the type of element #1
     * @param 
     *            the type of element #2
     *
     * @return an empty tuple
     */
    @SuppressWarnings("unchecked")
    public static  Tuple2 empty() {
        return (Tuple2) EMPTY;
    }

    /**
     * Returns an iterable zipping the elements from given source iterables.
     *
     * 

* The resulting iterables returns tuples from the elements provided by the * source iterables and returns as many elements as the shorter of the * source iterables. * * @param * the type of element #1 * @param * the type of element #2 * @param source1 * the source of elements. It must not be {@code null}. * @param source2 * the source of elements. It must not be {@code null}. * * @return a zipping iterable */ public static Iterable> zip(Iterable source1, Iterable source2) { Objects.requireNonNull(source1); Objects.requireNonNull(source2); // Rather not make a lambda, it might change return new Iterable>() { /** * @see java.lang.Iterable#iterator() */ public Iterator> iterator() { return Tuple2.zip(source1.iterator(), source2.iterator()); } }; } /** * Returns an iterator zipping the elements from given source iterators. * *

* The resulting iterator returns tuples from the elements provided by the * source iterators and returns as many elements as the shorter of the * source iterators. * * @param * the type of element #1 * @param * the type of element #2 * @param source1 * the source of elements. It must not be {@code null}. * @param source2 * the source of elements. It must not be {@code null}. * * @return a zipping iterator */ public static Iterator> zip(Iterator source1, Iterator source2) { Objects.requireNonNull(source1); Objects.requireNonNull(source2); return new Iterator>() { /** * @see java.util.Iterator#hasNext() */ public boolean hasNext() { return source1.hasNext() && source2.hasNext(); } /** * @see java.util.Iterator#next() */ public Tuple2 next() { return Tuple2.of(source1.next(), source2.next()); } }; } /** * Returns a stream zipping the elements from given source streams. * *

* The resulting stream returns tuples from the elements provided by the * source streams and returns as many elements as the shorter of the source * streams. * * @param * the type of element #1 * @param * the type of element #2 * @param source1 * the source of elements. It must not be {@code null}. * @param source2 * the source of elements. It must not be {@code null}. * * @return a zipping stream */ public static Stream> zip(Stream source1, Stream source2) { final Iterator> it = zip(source1.iterator(), source2.iterator()); return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, 0), false); } /** * @see java.lang.Object#toString() */ @Override public String toString() { return String.format("(%s, %s)", value1, value2); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof Tuple2) { final Tuple2 o = (Tuple2) obj; return Objects.equals(value1, o.value1) && Objects.equals(value2, o.value2); } return false; } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return Objects.hash(value1, value2); } /** * Returns element #1. * * @return element #1 */ public T1 get1() { return value1; } /** * Returns element #2. * * @return element #2 */ public T2 get2() { return value2; } /** * Returns a tuple with element #1 modified to the given value. * * @param * the type of the value * @param value * the value to set * * @return a tuple with element #1 modified to the given value */ public Tuple2 set1(V value) { return of(value, value2); } /** * Returns a tuple with element #2 modified to the given value. * * @param * the type of the value * @param value * the value to set * * @return a tuple with element #2 modified to the given value */ public Tuple2 set2(V value) { return of(value1, value); } /** * Returns a tuple with element #1 mapped with the given function. * * @param * the type of the function result * @param mapping * the function to apply. It must not be {@code null}. * * @return a tuple with element #1 mapped with the given function */ public Tuple2 map1(Function mapping) { return of(mapping.apply(value1), value2); } /** * Returns a tuple with element #2 mapped with the given function. * * @param * the type of the function result * @param mapping * the function to apply. It must not be {@code null}. * * @return a tuple with element #2 mapped with the given function */ public Tuple2 map2(Function mapping) { return of(value1, mapping.apply(value2)); } /** * Passes element #1 to the specified consumer. * * @param consumer * the consumer to call. It must not be {@code null}. * * @return this instance */ public Tuple2 use1(Consumer consumer) { consumer.accept(value1); return this; } /** * Passes element #2 to the specified consumer. * * @param consumer * the consumer to call. It must not be {@code null}. * * @return this instance */ public Tuple2 use2(Consumer consumer) { consumer.accept(value2); return this; } /** * Returns a tuple with swapped elements. * * @return a tuple with swapped elements */ public Tuple2 swap() { return (this == EMPTY) ? empty() : of(value2, value1); } /** * Passes the elements of this tuple to the given {@link Consumer}. * * @param consumer * the consumer to apply on the elements. It must not be * {@code null}. */ public void accept(BiConsumer consumer) { consumer.accept(value1, value2); } /** * Applies the given function on the elements of this tuple and returns its * result. * * @param * the type of the result * @param reduction * the function to apply on the elements. It must not be * {@code null}. * * @return the result of the given function */ public V reduce(BiFunction reduction) { return reduction.apply(value1, value2); } /** * Makes a tuple with the given value prepended to this tuple. * * @param * the type of the value * @param value * the value to prepend * * @return a tuple with the given value prepended to this tuple */ public Tuple3 prepend(V value) { return Tuple3.of(value, value1, value2); } /** * Makes a tuple with the given value appended to this tuple. * * @param * the type of the value * @param value * the value to append * * @return a tuple with the given value appended to this tuple */ public Tuple3 append(V value) { return Tuple3.of(value1, value2, value); } /** * Makes a tuple with the given value inserted between the elements of this * tuple. * * @param * the type of the value * @param value * the value to insert * * @return a tuple with the given value inserted between the elements of * this tuple */ public Tuple3 insert(V value) { return Tuple3.of(value1, value, value2); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy