
net.yetamine.lang.containers.Tuple3 Maven / Gradle / Ivy
Show all versions of net.yetamine.lang Show documentation
package net.yetamine.lang.containers;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Spliterators;
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 three elements.
*
* @param
* the type of element #1
* @param
* the type of element #2
* @param
* the type of element #3
*/
public final class Tuple3 {
/** Common shared empty tuple. */
private static final Tuple3, ?, ?> EMPTY = new Tuple3<>(null, null, null);
/** Element #1. */
private final T1 value1;
/** Element #2. */
private final T2 value2;
/** Element #3. */
private final T3 value3;
/**
* Creates a new instance.
*
* @param t1
* element #1
* @param t2
* element #2
* @param t3
* element #3
*/
private Tuple3(T1 t1, T2 t2, T3 t3) {
value1 = t1;
value2 = t2;
value3 = t3;
}
/**
* Creates a new instance.
*
* @param
* the type of element #1
* @param
* the type of element #2
* @param
* the type of element #3
* @param t1
* element #1
* @param t2
* element #2
* @param t3
* element #3
*
* @return the new instance
*/
public static Tuple3 of(T1 t1, T2 t2, T3 t3) {
return new Tuple3<>(t1, t2, t3);
}
/**
* Returns an empty tuple (consisting of {@code null} elements).
*
* @param
* the type of element #1
* @param
* the type of element #2
* @param
* the type of element #3
*
* @return an empty tuple
*/
@SuppressWarnings("unchecked")
public static Tuple3 empty() {
return (Tuple3) EMPTY;
}
/**
* Makes a tuple from the first three 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 three
* elements.
*
* @return a tuple
*
* @throws NoSuchElementException
* if the source provides too few elements
*/
public static Tuple3 from(Iterable extends T> source) {
return from(source.iterator());
}
/**
* Makes a tuple from the first three 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 three
* elements.
*
* @return a tuple
*
* @throws NoSuchElementException
* if the source provides too few elements
*/
public static Tuple3 from(Iterator extends T> source) {
return of(source.next(), source.next(), source.next());
}
/**
* 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
* the type of element #3
* @param source1
* the source of elements. It must not be {@code null}.
* @param source2
* the source of elements. It must not be {@code null}.
* @param source3
* the source of elements. It must not be {@code null}.
*
* @return a zipping iterable
*/
public static Iterable> zip(Iterable extends T1> source1, Iterable extends T2> source2, Iterable extends T3> source3) {
Objects.requireNonNull(source1);
Objects.requireNonNull(source2);
Objects.requireNonNull(source3);
// Rather not make a lambda, it might change
return new Iterable>() {
/**
* @see java.lang.Iterable#iterator()
*/
public Iterator> iterator() {
return Tuple3.zip(source1.iterator(), source2.iterator(), source3.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
* the type of element #3
* @param source1
* the source of elements. It must not be {@code null}.
* @param source2
* the source of elements. It must not be {@code null}.
* @param source3
* the source of elements. It must not be {@code null}.
*
* @return a zipping iterator
*/
public static Iterator> zip(Iterator extends T1> source1, Iterator extends T2> source2, Iterator extends T3> source3) {
Objects.requireNonNull(source1);
Objects.requireNonNull(source2);
Objects.requireNonNull(source3);
return new Iterator>() {
/**
* @see java.util.Iterator#hasNext()
*/
public boolean hasNext() {
return source1.hasNext() && source2.hasNext() && source3.hasNext();
}
/**
* @see java.util.Iterator#next()
*/
public Tuple3 next() {
return Tuple3.of(source1.next(), source2.next(), source3.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
* the type of element #3
* @param source1
* the source of elements. It must not be {@code null}.
* @param source2
* the source of elements. It must not be {@code null}.
* @param source3
* the source of elements. It must not be {@code null}.
*
* @return a zipping stream
*/
public static Stream> zip(Stream extends T1> source1, Stream extends T2> source2, Stream extends T3> source3) {
final Iterator> it = zip(source1.iterator(), source2.iterator(), source3.iterator());
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, 0), false);
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("(%s, %s, %s)", value1, value2, value3);
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Tuple3, ?, ?>) {
final Tuple3, ?, ?> o = (Tuple3, ?, ?>) obj;
return Objects.equals(value1, o.value1) && Objects.equals(value2, o.value2)
&& Objects.equals(value3, o.value3);
}
return false;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return Objects.hash(value1, value2, value3);
}
/**
* Returns element #1.
*
* @return element #1
*/
public T1 get1() {
return value1;
}
/**
* Returns element #2.
*
* @return element #2
*/
public T2 get2() {
return value2;
}
/**
* Returns element #3.
*
* @return element #3
*/
public T3 get3() {
return value3;
}
/**
* 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 Tuple3 set1(V value) {
return of(value, value2, value3);
}
/**
* 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 Tuple3 set2(V value) {
return of(value1, value, value3);
}
/**
* Returns a tuple with element #3 modified to the given value.
*
* @param
* the type of the value
* @param value
* the value to set
*
* @return a tuple with element #3 modified to the given value
*/
public Tuple3 set3(V value) {
return of(value1, value2, 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 Tuple3 map1(Function super T1, ? extends V> mapping) {
return of(mapping.apply(value1), value2, value3);
}
/**
* 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 Tuple3 map2(Function super T2, ? extends V> mapping) {
return of(value1, mapping.apply(value2), value3);
}
/**
* Returns a tuple with element #3 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 #3 mapped with the given function
*/
public Tuple3 map3(Function super T3, ? extends V> mapping) {
return of(value1, value2, mapping.apply(value3));
}
/**
* Passes element #1 to the specified consumer.
*
* @param consumer
* the consumer to call. It must not be {@code null}.
*
* @return this instance
*/
public Tuple3 use1(Consumer super T1> 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 Tuple3 use2(Consumer super T2> consumer) {
consumer.accept(value2);
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 Tuple3 use3(Consumer super T3> consumer) {
consumer.accept(value3);
return this;
}
/**
* Returns the first two elements as a tuple.
*
* @return the first two elements as a tuple
*/
public Tuple2 head() {
return Tuple2.of(value1, value2);
}
/**
* Returns the last two elements as a tuple.
*
* @return the last two elements as a tuple
*/
public Tuple2 tail() {
return Tuple2.of(value2, value3);
}
/**
* Returns the first and the last elements as a tuple.
*
* @return the first and the last elements as a tuple
*/
public Tuple2 outer() {
return Tuple2.of(value1, value3);
}
}