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

net.yetamine.lang.containers.tuples.Tuple3 Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Yetamine
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.yetamine.lang.containers.tuples;

import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;

import net.yetamine.lang.collections.Iterators;

/**
 * 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 implements Tuple {

    /** 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;
    }

    // Core construction methods

    /**
     * Creates a new instance.
     *
     * 

* This method is an alias for {@link #of(Object, Object, Object)} and it is * meant mainly as a support for static imports. * * @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 tuple3(T1 t1, T2 t2, T3 t3) { return of(t1, t2, 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; } /** * Narrows a widened type performing a safe type cast (thanks to the safe * covariant changes for immutable types). * * @param * the type of element #1 * @param * the type of element #2 * @param * the type of element #3 * @param instance * the instance to narrow * * @return the narrowed instance */ @SuppressWarnings("unchecked") public static Tuple3 narrow(Tuple3 instance) { return (Tuple3) instance; } // Common object methods /** * @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); } // Inherited methods /** * @see net.yetamine.lang.containers.tuples.Tuple#arity() */ public int arity() { return 3; } /** * @see net.yetamine.lang.containers.tuples.Tuple#get(int) */ public Object get(int index) { switch (index) { case 0: return get1(); case 1: return get2(); case 2: return get3(); default: throw new IndexOutOfBoundsException(); } } /** * @see net.yetamine.lang.containers.tuples.Tuple#toList() */ public List toList() { return Collections.unmodifiableList(Arrays.asList(value1, value2, value3)); } // Core tuple methods /** * 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); } // Link to Tuple2 /** * 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); } // Functional extensions /** * 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 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 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 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 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 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 consumer) { consumer.accept(value3); return this; } // Factory methods for common types /** * 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 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 source) { return of(source.next(), source.next(), source.next()); } // Zipping /** * 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 source1, Iterable source2, Iterable 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 source1, Iterator source2, Iterator 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 source1, Stream source2, Stream source3) { return Iterators.stream(zip(source1.iterator(), source2.iterator(), source3.iterator())); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy