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

com.landawn.abacus.util.Pair Maven / Gradle / Ivy

There is a newer version: 1.8.1
Show newest version
/*
 * Copyright (c) 2015, Haiyang Li.
 * 
 * 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 com.landawn.abacus.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.landawn.abacus.util.Tuple.Tuple2;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.BiPredicate;
import com.landawn.abacus.util.function.Consumer;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.TriPredicate;
import com.landawn.abacus.util.stream.Stream;

/**
 * 
 * @since 0.8
 * 
 * @author Haiyang Li
 *
 * @param 
 * @param 
 */
public final class Pair implements Map.Entry {
    public volatile L left;
    public volatile R right;

    public Pair() {
    }

    Pair(final L l, final R r) {
        this.left = l;
        this.right = r;
    }

    public static  Pair of(final L l, final R r) {
        return new Pair<>(l, r);
    }

    public static  Pair from(T[] a) {
        if (N.isNullOrEmpty(a)) {
            return new Pair<>(null, null);
        } else if (a.length == 1) {
            return new Pair<>(a[0], null);
        } else {
            return new Pair<>(a[0], a[1]);
        }
    }

    public static  Pair from(Collection c) {
        if (N.isNullOrEmpty(c)) {
            return new Pair<>(null, null);
        }

        final List list = c instanceof List ? (List) c : null;

        if (c.size() == 1) {
            if (list != null) {
                return new Pair(list.get(0), null);
            } else {
                return new Pair(c.iterator().next(), null);
            }
        } else {
            if (list != null) {
                return new Pair(list.get(0), list.get(1));
            } else {
                final Iterator iter = c.iterator();
                return new Pair(iter.next(), iter.next());
            }
        }
    }

    public L left() {
        return left;
    }

    public R right() {
        return right;
    }

    public L getLeft() {
        return left;
    }

    public Pair setLeft(final L left) {
        this.left = left;

        return this;
    }

    public R getRight() {
        return right;
    }

    public Pair setRight(final R right) {
        this.right = right;

        return this;
    }

    public Pair set(final L left, final R right) {
        this.left = left;
        this.right = right;

        return this;
    }

    public L getAndSetLeft(L newLeft) {
        final L res = left;
        left = newLeft;
        return res;
    }

    public L setAndGetLeft(L newLeft) {
        left = newLeft;
        return left;
    }

    public R getAndSetRight(R newRight) {
        final R res = newRight;
        right = newRight;
        return res;
    }

    public R setAndGetRight(R newRight) {
        right = newRight;
        return right;
    }

    /**
     * Set to the specified newLeft and returns true
     * if predicate returns true. Otherwise returns
     * false without setting the value to new value.
     * 
     * @param newLeft
     * @param predicate - the first parameter is current pair, the second
     *        parameter is the newLeft
     * @return
     */
    public boolean setLeftIf(final L newLeft, BiPredicate, ? super L> predicate) {
        if (predicate.test(this, newLeft)) {
            this.left = newLeft;
            return true;
        }

        return false;
    }

    /**
     * Set to the specified newRight and returns true
     * if predicate returns true. Otherwise returns
     * false without setting the value to new value.
     * 
     * @param newRight
     * @param predicate - the first parameter is current pair, the second
     *        parameter is the newRight
     * @return
     */
    public boolean setRightIf(final R newRight, BiPredicate, ? super R> predicate) {
        if (predicate.test(this, newRight)) {
            this.right = newRight;
            return true;
        }

        return false;
    }

    /**
     * Set to the specified newLeft and newRight and returns true
     * if predicate returns true. Otherwise returns
     * false without setting the left/right to new values.
     * 
     * @param newLeft
     * @param newRight
     * @param predicate - the first parameter is current pair, the second
     *        parameter is the newLeft, the third parameter is the newRight.
     * @return
     */
    public boolean setIf(final L newLeft, final R newRight, TriPredicate, ? super L, ? super R> predicate) {
        if (predicate.test(this, newLeft, newRight)) {
            this.left = newLeft;
            this.right = newRight;
            return true;
        }

        return false;
    }

    @Override
    public L getKey() {
        return left;
    }

    @Override
    public R getValue() {
        return right;
    }

    @Override
    public R setValue(R value) {
        R oldValue = this.right;
        this.right = value;

        return oldValue;
    }

    //    public R getAndSetValue(R newRight) {
    //        return getAndSetRight(newRight);
    //    }
    //
    //    public R setAndGetValue(R newRight) {
    //        return setAndGetRight(newRight);
    //    }
    //
    //    /**
    //     * 
    //     * @param newRight
    //     * @param predicate
    //     * @return
    //     * @see #setRightIf(Object, BiPredicate)
    //     */
    //    public boolean setValueIf(final R newRight, BiPredicate, ? super R> predicate) {
    //        return setRightIf(newRight, predicate);
    //    }

    /**
     * 
     * @return a new instance of Pair<R, L>.
     */
    public Pair reversed() {
        return new Pair<>(this.right, this.left);
    }

    public Pair copy() {
        return new Pair<>(this.left, this.right);
    }

    public Object[] toArray() {
        return new Object[] { left, right };
    }

    public  A[] toArray(A[] a) {
        if (a.length < 2) {
            a = N.copyOf(a, 2);
        }

        a[0] = (A) left;
        a[1] = (A) right;

        return a;
    }

    public void forEach(Consumer comsumer) {
        final Consumer objComsumer = (Consumer) comsumer;

        objComsumer.accept(left);
        objComsumer.accept(right);
    }

    public void accept(final BiConsumer action) {
        action.accept(left, right);
    }

    public void accept(final Consumer> action) {
        action.accept(this);
    }

    public  U map(final BiFunction mapper) {
        return mapper.apply(left, right);
    }

    public  U map(final Function, U> mapper) {
        return mapper.apply(this);
    }

    public Optional> filter(final BiPredicate predicate) {
        return predicate.test(left, right) ? Optional.of(this) : Optional.> empty();
    }

    public Optional> filter(final Predicate> predicate) {
        return predicate.test(this) ? Optional.of(this) : Optional.> empty();
    }

    public Stream> stream() {
        return Stream.of(this);
    }

    public Tuple2 toTuple() {
        return Tuple.of(left, right);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + N.hashCode(left);
        result = prime * result + N.hashCode(right);
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof Pair) {
            final Pair other = (Pair) obj;

            return N.equals(left, other.left) && N.equals(right, other.right);
        }

        return false;
    }

    @Override
    public String toString() {
        return "[" + N.toString(left) + ", " + N.toString(right) + "]";
    }
}