Tuple fehlen leider immer noch in Java (wenn man von Krücken wie Map.Entry
oder javafx.util.Pair
einmal absieht), haben aber gerade im Collection-Umfeld viele potentielle Anwendungsmöglichkeiten, etwa:
[ul]
[li] interface Map<A,B> extends Iterable<Pair<A,B>>{...}
[/li][li] static List<Pair<A,B>> zip(List<A> listA, List<B> listB){...}
[/li][li] static Pair<List<A>,List<A>> partition(List<A> listA, Predicate<A> pred){...}
[/li][/ul]
Mir fallen folgende Fragen dazu ein:
[ul]
[li] Interface und Implementierung, oder nur Implementierung?[/li][li] Natürliche Namen (“Pair”, “Triple”) oder durchnummeriert (“T2”,“T3”)?[/li][li] Welche Stelligkeiten? Brauchen wir z.B. Quintuple? Brauchen wir auch Wrapper für Einzelwerte, oder sogar einen “nullstelligen” Typ (analog Scalas Unit
als vernünftige Alternative zu Void
)?[/li][li] Soll es eine gemeinsame Oberklasse geben? Oder eine (potentiell beliebig erweiterbare) Implementierung über HListen? (ich denke, beides eher nicht)[/li][li] Sollen die Klassen (wie in der javatuple-Bibliothek) Iterable<Object>
implementieren? (meiner Meinung nach eine schlechte Idee)[/li][/ul]
Als Diskussionsgrundlage poste ich mal die API meiner existierenden Pair-Klasse:
public abstract class Pair<A, B> {
private Pair(){}
public static <A, B> Pair<A, B> of(A a, B b) {...}
public static <A, B> Pair<A, B> lazyOf(Supplier<A> supplierA, Supplier<B> supplierB) {...}
public abstract A get1();
public abstract B get2();
public <A1> Pair<A1, B> with1(A$ a) {...}
public <B1> Pair<A, B1> with2(B$ b) {...}
public <A1> Pair<A1, B> map1(Function<A, A1> fn) {...}
public <B1> Pair<A, B1> map2(Function<B, B1> fn) {...}
public <A1,B1> Pair<A1,B1> bimap(Function<A, A1> fnA, Function<B, B1> fnB) {...}
public <C> C collapse(BiFunction<A,B,C> fn) {...}
public Pair<B, A> swap() {...}
@Override
public String toString() {
return String.format("(%s,%s)", get1(), get2());
}
public int hashCode() {...}
public boolean equals(Object o) {...}
public <A1, A2, B1, B2> Pair<A2, B2> merge(Pair<A1, B1> that, BiFunction<A, A1, A2> fnA, BiFunction<B, B1, B2> fnB) {...}
}