joshng.util.collect.Pair.java Source code

Java tutorial

Introduction

Here is the source code for joshng.util.collect.Pair.java

Source

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Middleware LLC.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package joshng.util.collect;

import com.google.common.base.Function;
import com.google.common.collect.PublicImmutableEntry;
import joshng.util.blocks.F;
import joshng.util.blocks.F2;

import javax.annotation.concurrent.Immutable;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;
import static joshng.util.Reflect.blindCast;

@Immutable
public class Pair<T, U> extends PublicImmutableEntry<T, U> {
    private static final F GET_FIRST = new F<Map.Entry, Object>() {
        public Object apply(Map.Entry pair) {
            return pair.getKey();
        }
    };
    private static final F GET_SECOND = new F<Map.Entry, Object>() {
        public Object apply(Map.Entry pair) {
            return pair.getValue();
        }
    };
    public static final F SWAPPER = new F<Map.Entry, Map.Entry>() {
        @Override
        public Map.Entry apply(Map.Entry input) {
            return Pair.of(input.getValue(), input.getKey());
        }
    };

    private Integer hashCode;

    public static <T, U> F2<T, U, Pair<T, U>> creator() {
        return Pair::new;
    }

    public Pair(T first, U second) {
        super(checkNotNull(first, "first"), checkNotNull(second, "second"));
    }

    public static <T, U> Pair<T, U> of(T t, U u) {
        return new Pair<>(t, u);
    }

    @SuppressWarnings({ "unchecked" })
    public static <T> F<Map.Entry<? extends T, ?>, T> getFirstFromPair() {
        return (F<Map.Entry<? extends T, ?>, T>) GET_FIRST;
    }

    @SuppressWarnings({ "unchecked" })
    public static <T> F<Map.Entry<?, ? extends T>, T> getSecondFromPair() {
        return (F<Map.Entry<?, ? extends T>, T>) GET_SECOND;
    }

    @SuppressWarnings({ "unchecked" })
    public static <K, V> F<Map.Entry<K, V>, Map.Entry<V, K>> swapper() {
        return SWAPPER;
    }

    public static <T, U> Pair<FunIterable<T>, FunIterable<U>> unzip(Iterable<? extends Map.Entry<T, U>> pairs) {
        //        return Pair.of(FunIterable.map(pairs, Pair.<T>getFirstFromPair()), FunIterable.map(pairs, Pair.<U>getSecondFromPair()));
        return Pair.of(FunIterable.map(pairs, Pair.<T>getFirstFromPair()),
                FunIterable.map(pairs, Pair.<U>getSecondFromPair()));
    }

    public static <T, U> Pair<U, U> map(Pair<? extends T, ? extends T> pair,
            Function<? super T, ? extends U> mapper) {
        return Pair.of(mapper.apply(pair.getKey()), mapper.apply(pair.getValue()));
    }

    public T getFirst() {
        return getKey();
    }

    public U getSecond() {
        return getValue();
    }

    public Pair<U, T> swap() {
        return Pair.of(getValue(), getKey());
    }

    public <V> Pair<V, U> mapKey(Function<? super T, ? extends V> mapper) {
        return Pair.of(mapper.apply(getKey()), getValue());
    }

    public <V> Pair<T, V> mapValue(Function<? super U, ? extends V> mapper) {
        return Pair.of(getKey(), mapper.apply(getValue()));
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Pair) {
            Pair other = (Pair) obj;
            // if computed, use hashcodes to obtain a cheap answer
            if (hashCode != null && other.hashCode != null && !hashCode.equals(other.hashCode))
                return false;
        } else if (!(obj instanceof Map.Entry)) {
            return false;
        }

        Map.Entry<?, ?> that = (Map.Entry<?, ?>) obj;
        return getKey().equals(that.getKey()) && getValue().equals(that.getValue());
    }

    @Override
    public String toString() {
        return "[" + getKey() + "," + getValue() + "]";
    }

    @Override
    public int hashCode() {
        //cached because the graph can be deep
        if (hashCode == null)
            hashCode = super.hashCode();
        return hashCode;
    }
}