Utworzono klasy tuple
i umieść je w kolekcji Java. Ale nie chcę używać tuple
jako parametrów funkcji bezpośrednio podczas iterowania kolekcji. Więc zaimplementowałem rozpakowywanie krotek jako następujący kod.Jak zaimplementować rozpakowanie krotek dla parametrów funkcji w Javie?
zasadzie to działa, ale problemem jest to, że odlew typ jest potrzebne:
map((Func2<Long, Long, Long>) (a, b) -> a + b)
Czy istnieje jakiś sposób, aby usunąć casting typu tutaj?
edit:
Może nie było jasne, nie tylko tuple2
, ale także tuple3
, tuple4
... powinny być wspierane. @ Flown na odpowiedź działa znacznie dla Tuple2
, ale nie działa na tuple2
, tuple3
, tuple4
w międzyczasie
package test;
import com.google.common.collect.Iterables;
import java.util.Arrays;
import java.util.function.Function;
import static test.TupleIterable.Tuple.tuple;
public interface TupleIterable<T> {
Iterable<T> apply();
static <E> TupleIterable<E> from(Iterable<E> iterable) {
return() -> iterable;
}
default <E> TupleIterable<E> map(Function<? super T, ? extends E> op) {
return() -> Iterables.transform(TupleIterable.this.apply(), op::apply);
}
interface Func2<T1, T2, R> extends Function<Tuple.Tuple2<T1, T2>, R> {
R apply(T1 t1, T2 t2);
@Override
default R apply(Tuple.Tuple2<T1, T2> t) {
return apply(t.t1, t.t2);
}
}
interface Func3<T1, T2, T3, R> extends Function<Tuple.Tuple3<T1, T2, T3>, R> {
R apply(T1 t1, T2 t2, T3 t3);
@Override
default R apply(Tuple.Tuple3<T1, T2, T3> t) {
return apply(t.t1, t.t2, t.t3);
}
}
interface Tuple {
static <T1, T2> Tuple2<T1, T2> tuple(T1 t1, T2 t2) {
return new Tuple2<>(t1, t2);
}
static <T1, T2, T3> Tuple3<T1, T2, T3> tuple(T1 t1, T2 t2, T3 t3) {
return new Tuple3<>(t1, t2, t3);
}
class Tuple2<T1, T2> implements Tuple {
public T1 t1;
public T2 t2;
public Tuple2(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
}
}
class Tuple3<T1, T2, T3> implements Tuple {
public T1 t1;
public T2 t2;
public T3 t3;
public Tuple3(T1 t1, T2 t2, T3 t3) {
this.t1 = t1;
this.t2 = t2;
this.t3 = t3;
}
}
}
public static void main(String[] args) {
TupleIterable.from(Arrays.asList(1L, 2L))
.map(x -> tuple(x, x)) // map long to tuple2
.map((Func2<Long, Long, Tuple.Tuple3<Long, Long, Long>>) (a, b) -> tuple(a, b, a + b)) // map tuple2 to tuple3
.map((Func3<Long, Long, Long, Long>) (a, b, c) -> a + b + c) // map tuple3 to Long
.apply()
.forEach(System.out::println);
}
}
Dziękuję za wspaniałą odpowiedź! Mam inne pytanie, czy to wspiera inne krotki, takie jak 'Tuple3',' Tuple4', etc ... Wydaje się, że muszę stworzyć wiele metod, takich jak 'mapToTuple3',' mapToTuple4' ... – moshangcheng
'Tuple3Iterable ',' Tuple4Iterable' nie są ze sobą kompatybilne. To znaczy, argumenty nie mogą być rozpakowane w 'Tuple3Iterable :: mapToTuple4' – moshangcheng
@moshangcheng Jeśli chcesz być taki ogólny, nie możesz uniknąć rzucania. – Flown