Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.medallia.word2vec.util.Pair Maven / Gradle / Ivy
package com.medallia.word2vec.util;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Simple class for storing two arbitrary objects in one.
*
* @param the type of the first value
* @param the type of the second value
*/
public class Pair implements Map.Entry, Serializable {
/** @see Serializable */
private static final long serialVersionUID = 1L;
/** The first item in the pair. */
public final K first;
/** The second item in the pair. */
public final V second;
/** Creates a new instance of Pair */
protected Pair(K first, V second) {
this.first = first;
this.second = second;
}
/** Type-inferring constructor */
public static Pair cons(X x, Y y) { return new Pair(x,y); }
/** Type-inferring constructor for pairs of the same type, which can optionally be swapped */
public static Pair cons(X x, X y, boolean swapped) { return swapped ? new Pair(y, x) : new Pair(x, y); }
@Override
public int hashCode() {
// Compute by hand instead of using Encoding.combineHashes for improved performance
return (first == null ? 0 : first.hashCode() * 13) + (second == null ? 0 : second.hashCode() * 17);
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (o == null || !getClass().equals(o.getClass()))
return false;
Pair,?> op = (Pair,?>) o;
return Objects.equals(op.first, first) && Objects.equals(op.second, second);
}
/** @return {@link #first}; needed because String Templates have 'first' as a reserved word. */
public K getOne() { return first; }
/** @return {@link #first} */
public K getFirst() { return first; }
/** @return {@link #second} */
public V getSecond() { return second; }
@Override public String toString() {
return "Pair<"+first+","+second+">";
}
/** @return a list with the two elements from this pair, regardless of whether they are null or not */
public List asList() {
return Lists.newArrayList(first, second);
}
/**
* @return a list of key/value pairs (keys are at even indices, values at odd) taken from the
* given array, whose length must be even.
*/
@SafeVarargs
public static List> fromPairs(X... args) {
if (Common.isOdd(args.length))
throw new IllegalArgumentException("Array length must be even: " + args.length);
List> l = new ArrayList<>(args.length / 2);
for (int i = 0; i < args.length; i += 2)
l.add(Pair.cons(args[i], args[i + 1]));
return l;
}
/**
* Converts a Map to a List of pairs.
* Each entry in the map results in a Pair in the returned list.
*/
public static List> fromMap(Map m) {
List> l = new ArrayList<>();
for (Map.Entry me : m.entrySet()) {
l.add(Pair.cons(me.getKey(), me.getValue()));
}
return l;
}
private static >> C fromMapFlatten(C c, Map extends X, ? extends Collection extends Y>> m) {
for (Map.Entry extends X, ? extends Collection extends Y>> me : m.entrySet()) {
for (Y y : me.getValue())
c.add(Pair.cons(me.getKey(), y));
}
return c;
}
@Override public K getKey() { return first; }
@Override public V getValue() { return second; }
@Override public V setValue(V value) { throw new UnsupportedOperationException(); }
/** Method that allows Pair to be used directly by the Setup system (wtf) */
public String getName() { return String.valueOf(second); }
/** @return a reversed version of this pair */
public Pair swapped() { return Pair.cons(second, first); }
/** @return {@link Function} which performs a {@link #swapped()} */
public static Function, Pair> swappedFunction() {
return new Function, Pair>() {
@Override public Pair apply(Pair p) {
return p.swapped();
}
};
}
/**
* @return {@link Ordering} which compares the first value of the pairs.
* Pairs with equal first value will be considered equivalent independent of the second value
*/
public static > Ordering> firstComparator() {
return new Ordering>() {
@Override public int compare(Pair o1, Pair o2) {
return Compare.compare(o1.first, o2.first);
}
};
}
/**
* @return {@link Ordering} which compares the second value of the pairs.
* Pairs with equal second value will be considered equivalent independent of the first value
*/
public static > Ordering> secondComparator() {
return new Ordering>() {
@Override public int compare(Pair, Y> o1, Pair, Y> o2) {
return Compare.compare(o1.second, o2.second);
}
};
}
/** @return {@link Ordering} which compares both values of the {@link Pair}s, with the first taking precedence. */
public static , Y extends Comparable super Y>> Ordering> firstThenSecondComparator() {
return new Ordering>() {
@Override public int compare(Pair o1, Pair o2) {
int k = Compare.compare(o1.first, o2.first);
if (k == 0) k = Compare.compare(o1.second, o2.second);
return k;
}
};
}
/** @return {@link Ordering} which compares both values of the {@link Pair}s, with the second taking precedence. */
public static , Y extends Comparable super Y>> Ordering> secondThenFirstComparator() {
return new Ordering>() {
@Override public int compare(Pair o1, Pair o2) {
int k = Compare.compare(o1.second, o2.second);
if (k == 0)
k = Compare.compare(o1.first, o2.first);
return k;
}
};
}
/**
* Pair comparator that applies the given {@link Comparator} to the first value of the pairs
*/
public static Comparator> firstComparator(final Comparator super X> comp) {
return new Comparator>() {
@Override public int compare(Pair o1, Pair o2) {
return comp.compare(o1.first, o2.first);
}
};
}
/**
* Pair comparator that applies the given {@link Comparator} to the second value of the pairs
*/
public static Comparator> secondComparator(final Comparator super Y> comp) {
return new Comparator>() {
@Override public int compare(Pair o1, Pair o2) {
return comp.compare(o1.second, o2.second);
}
};
}
/**
* Pair comparator that compares both values of the pairs, with the first taking
* precedence; the order is reversed for the first value only.
*/
public static , Y extends Comparable super Y>> Comparator> bothFirstReversedComparator() {
return new Comparator>() {
@Override public int compare(Pair o1, Pair o2) {
int k = Compare.compare(o2.first, o1.first);
if (k == 0) k = Compare.compare(o1.second, o2.second);
return k;
}
};
}
private static Map fillMap(Map m, Iterable extends Pair extends X, ? extends Y>> pairs) {
for (Pair extends X, ? extends Y> p : pairs) {
m.put(p.first, p.second);
}
return m;
}
/** @return the combination of all the elements in each collection. For instance if the first collection is
* {@code [1, 2, 3]}, and the second one is {@code [a, b]}, then the result is {@code [(1, a), (1, b), (2, a), ...]}
*/
@SuppressWarnings("unchecked")
public static List> cartesianProduct(Collection c1, Collection c2) {
return FluentIterable.from(Sets.cartesianProduct(ImmutableSet.copyOf(c1), ImmutableSet.copyOf(c2)))
.transform(new Function, Pair>() {
@Override public Pair apply(List objs) {
X x = (X) objs.get(0);
Y y = (Y) objs.get(1);
return Pair.cons(x, y);
}
})
.toList();
}
/** @return the elements at equal indices in the two lists, which must be of the same
* length, as pairs.
*/
public static List> zip(Collection c1, Collection c2) {
return zip(c1, c2, new ArrayList>(c1.size()), false);
}
/** @return the elements at equal indices in the two lists, which must be of the same
* length, as pairs.
*/
public static List> zip(X[] a1, Y[] a2) {
return zip(ImmutableList.copyOf(a1), ImmutableList.copyOf(a2));
}
/**
* @return the elements at equal indices in the two lists, which must be of
* the same length, as pairs, without duplicates removed from the
* first list
*/
public static List> zipUnique(Collection c1, Collection c2) {
return zip(c1, c2, new ArrayList>(), true);
}
private static List> zip(Collection c1, Collection c2, List> output, boolean uniqueKeys) {
int size = c1.size();
if (size != c2.size())
throw new IllegalArgumentException("Collections must be of same size: " + size + ", " + c2.size());
Set set = uniqueKeys ? new HashSet() : null;
Iterator it1 = c1.iterator();
Iterator it2 = c2.iterator();
while (it1.hasNext() && it2.hasNext()) {
X x = it1.next();
Y y = it2.next();
if (set == null || set.add(x))
output.add(Pair.cons(x, y));
}
return output;
}
/**
* @return the elements at equal indices of the two list as pairs. The number of elements in the result list
* is the minimum of the given iterable
* of different size only elements at indices
* present on the first {@link Iterable} are used.
*/
public static Iterable> zipInner(final Iterable first, final Iterable second) {
return new Iterable>() {
@Override public Iterator> iterator() {
final Iterator x = first.iterator();
final Iterator y = second.iterator();
return new Iterator>() {
@Override public boolean hasNext() {
return x.hasNext() && y.hasNext();
}
@Override
public Pair next() {
return Pair.cons(x.next(), y.next());
}
@Override
public void remove() {
x.remove();
y.remove();
}
};
}
};
}
/** @return {@link Function} which retrieves the second of the pair */
public static Function, V> retrieveSecondFunction() {
return new Function, V>() {
@Override
public V apply(Pair, V> p) {
return p.second;
}
};
}
/** @return {@link Iterable} of second element in pair */
public static Iterable unzipSecond(Iterable> pairs) {
return Iterables.transform(pairs, Pair.retrieveSecondFunction());
}
/** @return {@link Function} which maps the value of each pair through the given {@link Function} */
public static Function, Pair> mapValues(final Function super V, V2> func) {
return new Function, Pair>() {
@Override public Pair apply(Pair p) {
return Pair.cons(p.first, func.apply(p.second));
}
};
}
/** @return the first value, or null if the pair is null */
public static K firstOrNull(Pair pair) {
return pair != null ? pair.first : null;
}
/** @return the second value, or null if the pair is null */
public static V secondOrNull(Pair, V> pair) {
return pair != null ? pair.second : null;
}
/** @return {@link Predicates} which filters only on the first value */
public static Predicate> getFirstPredicate(final Predicate super K> pred) {
return new Predicate>() {
@Override public boolean apply(Pair pair) {
return pred.apply(pair.first);
}
};
}
/** @return {@link Predicates} which filters only on the second value */
public static Predicate> getSecondPredicate(final Predicate super V> pred) {
return new Predicate>() {
@Override public boolean apply(Pair pair) {
return pred.apply(pair.second);
}
};
}
/** @return {@link Predicates} which accepts a pair only if both values are accepted */
public static Predicate> getAndPredicate(final Predicate super K> firstPred, final Predicate super V> secondPred) {
return new Predicate>() {
@Override public boolean apply(Pair pair) {
return firstPred.apply(pair.first) && secondPred.apply(pair.second);
}
};
}
/** @return {@link Predicates} which accepts a pair if either values is accepted */
public static Predicate> getOrPredicate(final Predicate super K> firstPred, final Predicate super V> secondPred) {
return new Predicate>() {
@Override public boolean apply(Pair pair) {
return firstPred.apply(pair.first) || secondPred.apply(pair.second);
}
};
}
/**
* @return {@link ImmutableList} containing all values paired with their applied value
* through the function
*/
public static ImmutableList> toPairList(Iterable values, Function func) {
ImmutableList.Builder> result = ImmutableList.builder();
for (X x : values)
result.add(Pair.cons(x, func.apply(x)));
return result.build();
}
}