package com.codepoetics.octarine.joins; import java.util.Comparator; import java.util.function.Function; import java.util.stream.Stream; public final class Joins<L> { private final Stream<L> lefts; private Joins(Stream<L> lefts) { this.lefts = lefts; } public static <L> Joins<L> join(Stream<L> lefts) { return new Joins<>(lefts); } public <K extends Comparable<K>> JoinBuilder<K, L> on(Function<? super L, ? extends K> foreignKey) { return comparingWith(Comparator.<K>naturalOrder()).on(foreignKey); } public static interface ComparatorCapture<K, L> { JoinBuilder<K, L> on(Function<? super L, ? extends K> foreignKey); } public <K> ComparatorCapture<K, L> comparingWith(Comparator<? super K> comparator) { return f -> new JoinBuilder<>(comparator, lefts, JoinKey.on(f, comparator)); } public static final class JoinBuilder<K, L> { private final Comparator<? super K> comparator; private final Stream<L> lefts; private final JoinKey<L, K> foreignKey; public JoinBuilder(Comparator<? super K> comparator, Stream<L> lefts, JoinKey<L, K> foreignKey) { this.comparator = comparator; this.lefts = lefts; this.foreignKey = foreignKey; } public <R> Joiner<L, R, K> to(Function<? super R, ? extends K> primaryKey) { return new Joiner<>(foreignKey.index(lefts), JoinKey.on(primaryKey, comparator)); } } }