org.d2ab.util.Pair Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sequence Show documentation
Show all versions of sequence Show documentation
A lightweight alternative to Java 8 sequential Stream
/*
* Copyright 2015 Daniel Skogquist Åborg
*
* 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 org.d2ab.util;
import org.d2ab.function.Functions;
import org.d2ab.function.QuaternaryFunction;
import javax.annotation.Nullable;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.function.*;
import static java.util.Comparator.*;
public interface Pair extends Entry, Comparable> {
static Pair of(@Nullable T left, @Nullable U right) {
return new Base() {
@Override
public T getLeft() {
return left;
}
@Override
public U getRight() {
return right;
}
};
}
static Pair from(Entry extends K, ? extends V> entry) {
return new Base() {
@Override
public K getLeft() {
return entry.getKey();
}
@Override
public V getRight() {
return entry.getValue();
}
};
}
static Pair unary(@Nullable T item) {
return new Base() {
@Override
public T getLeft() {
return item;
}
@Override
public T getRight() {
return item;
}
};
}
static boolean test(Entry entry, BiPredicate super K, ? super V> predicate) {
return Entries.asPredicate(predicate).test(entry);
}
static UnaryOperator> asUnaryOperator(BiFunction super K, ? super V, ? extends Pair>
op) {
return entry -> op.apply(entry.getLeft(), entry.getRight());
}
static UnaryOperator> asUnaryOperator(BiFunction super K, ? super V, ? extends
Pair> f,
BiFunction super KK, ? super VV, ? extends
Pair> g) {
Function super Pair, ? extends Pair> f1 = asFunction(f);
Function super Pair, ? extends Pair> g1 = asFunction(g);
return Functions.toUnaryOperator(f1, g1);
}
static BinaryOperator> asBinaryOperator(QuaternaryFunction> f) {
return (e1, e2) -> f.apply(e1.getLeft(), e1.getRight(), e2.getLeft(), e2.getRight());
}
static Function super Pair, ? extends R> asFunction(BiFunction super K, ? super V, ? extends
R>
mapper) {
return entry -> mapper.apply(entry.getLeft(), entry.getRight());
}
static Predicate super Pair> asPredicate(BiPredicate super K, ? super V> predicate) {
return entry -> predicate.test(entry.getLeft(), entry.getRight());
}
static Consumer super Pair> asConsumer(BiConsumer super K, ? super V> action) {
return entry -> action.accept(entry.getLeft(), entry.getRight());
}
L getLeft();
R getRight();
@Override
default L getKey() {
return getLeft();
}
@Override
default R getValue() {
return getRight();
}
@Override
default R setValue(R value) {
throw new UnsupportedOperationException();
}
default Pair swap() {
return new Base() {
@Override
public R getLeft() {
return Pair.this.getRight();
}
@Override
public L getRight() {
return Pair.this.getLeft();
}
};
}
default Pair withLeft(LL left) {
return new Base() {
@Override
public LL getLeft() {
return left;
}
@Override
public R getRight() {
return Pair.this.getRight();
}
};
}
default Pair withRight(RR right) {
return new Base() {
@Override
public L getLeft() {
return Pair.this.getLeft();
}
@Override
public RR getRight() {
return right;
}
};
}
default Pair shiftRight(LL replacement) {
return new Base() {
@Override
public LL getLeft() {
return replacement;
}
@Override
public L getRight() {
return Pair.this.getLeft();
}
};
}
default Pair shiftLeft(RR replacement) {
return new Base() {
@Override
public R getLeft() {
return Pair.this.getRight();
}
@Override
public RR getRight() {
return replacement;
}
};
}
default Pair map(Function super L, ? extends LL> leftMapper,
Function super R, ? extends RR> rightMapper) {
return new Base() {
@Override
public LL getLeft() {
return leftMapper.apply(Pair.this.getLeft());
}
@Override
public RR getRight() {
return rightMapper.apply(Pair.this.getRight());
}
};
}
default Pair map(BiFunction super L, ? super R, ? extends Pair> mapper) {
return mapper.apply(getLeft(), getRight());
}
default T apply(BiFunction super L, ? super R, ? extends T> function) {
return function.apply(getLeft(), getRight());
}
default boolean test(Predicate super L> leftPredicate, Predicate super R> rightPredicate) {
return leftPredicate.test(getLeft()) && rightPredicate.test(getRight());
}
default boolean test(BiPredicate super L, ? super R> predicate) {
return predicate.test(getLeft(), getRight());
}
default Map put(Map map) {
map.put(getLeft(), getRight());
return map;
}
default Iterator iterator() {
@SuppressWarnings("unchecked")
PairIterator, ?, T> pairIterator = new PairIterator(this);
return pairIterator;
}
abstract class Base implements Pair {
@SuppressWarnings("unchecked")
private static final Comparator NULLS_FIRST = nullsFirst((Comparator) naturalOrder());
private static final Function GET_LEFT = (Function) Pair::getLeft;
private static final Function GET_RIGHT = (Function) Pair::getRight;
@SuppressWarnings("unchecked")
private static final Comparator COMPARATOR =
comparing(GET_LEFT, NULLS_FIRST).thenComparing(GET_RIGHT, NULLS_FIRST);
public static String format(Object o) {
if (o instanceof String) {
return '"' + (String) o + '"';
}
return String.valueOf(o);
}
@Override
public int hashCode() {
int result = (getLeft() != null) ? getLeft().hashCode() : 0;
result = (31 * result) + ((getRight() != null) ? getRight().hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Pair))
return false;
Pair, ?> that = (Pair, ?>) o;
return ((getLeft() != null) ? getLeft().equals(that.getLeft()) : (that.getLeft() == null)) &&
((getRight() != null) ? getRight().equals(that.getRight()) : (that.getRight() == null));
}
@Override
public String toString() {
return "(" + format(getLeft()) + ", " + format(getRight()) + ')';
}
@Override
public int compareTo(Pair that) {
return COMPARATOR.compare(this, that);
}
}
class PairIterator implements Iterator {
private final Pair pair;
int index;
public PairIterator(Pair pair) {
this.pair = pair;
}
@Override
public boolean hasNext() {
return index < 2;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
switch (++index) {
case 1:
return pair.getLeft();
case 2:
return pair.getRight();
default:
// Can't happen due to above check
throw new IllegalStateException();
}
}
}
}