Skip to content

5‐二元流

wolray edited this page Oct 16, 2023 · 6 revisions

二元流的构建

基于生成器表达式

同一元流一样,二元流也能用lambda表达式以类似于生成器的方式构建任意流

// {code block} -> ((0, 1), (1, 2), (2, 3), (3, 4), ...)
Seq2<Integer, Integer> seq = c -> {
    c.accept(0, 1);
    // 这也是一个无限流
    for (int i = 1; ; i++) {
        c.accept(i, i + 1);
    }
};

基于现成元素

单位流

// unit(1, 2) -> ((1, 2))
static <K, V> Seq2<K, V> unit(K k, V v)

空流

// empty() -> ()
static <K, V> Seq2<K, V> empty()

基于Map

// of({1='a', 2='b'}) -> ((1, 'a'), (2, 'b'))
static <K, V> Seq2<K, V> of(Map<K, V> map)

基于文本解析

kv字符串解析

// parseMap("a:1;b:2;c:3", ";", ":") -> (("a", "1"), ("b", "2"), ("c", "3"))
static Seq2<String, String> parseMap(String s, char entrySep, char kvSep)

解析后的二元流,可以通过toMap方法直接转为Map

二元流的链式调用

一元流转二元流

pair

由类型为T的一元流,通过两个映射函数,转为类型为(A,B)的二元流

// (1, 2, 3, 4) -> pair(i -> i + 10, Integer::toString) -> ((11, "1"), (12, "2"), (13, "3"), (14, "4"))
default <A, B> Seq2<A, B> pair(Function<T, A> f1, Function<T, B> f2)

pairBy

pair的特殊场景,将类型为T的元素转化为E后与原来的元素拼在一起构成二元流,新元素在前

// (1, 2, 3, 4) -> pairBy(i -> i + 10) -> ((11, 1), (12, 2), (13, 3), (14, 4))
default <E> Seq2<E, T> pairBy(Function<T, E> function)

pairWith

pair的特殊场景,将类型为T的元素转化为E后与原来的元素拼在一起构成二元流,新元素在后

// (1, 2, 3, 4) -> pairWith(i -> i + 10) -> ((1, 11), (2, 12), (3, 13), (4, 14))
default <E> Seq2<T, E> pairWith(Function<T, E> function)

pairByNotNull

pairBy并且过滤映射后的非空元素

default <E> Seq2<E, T> pairByNotNull(Function<T, E> function)

pairWithNotNull

pairWith并且过滤映射后的非空元素

default <E> Seq2<T, E> pairWithNotNull(Function<T, E> function)

mapPair

相邻元素两两组合,参数overlapping决定是否两两交替

// (1, 2, 3, 4, 5) -> mapPair(true) -> ((1, 2), (2, 3), (3, 4), (4, 5))
// (1, 2, 3, 4, 5) -> mapPair(false) -> ((1, 2), (3, 4))
default Seq2<T, T> mapPair(boolean overlapping)

二元流到二元流

mapKey

根据key和value替换原有key

// ((1, 2), (2, 3), (3, 4)) -> mapKey((k, v) -> k + 10) -> ((11, 2), (12, 3), (13, 4))
default <T> Seq2<T, V> mapKey(BiFunction<K, V, T> function)

根据key替换为新的key

// ((1, 2), (2, 3), (3, 4)) -> mapKey(k -> k + 10) -> ((11, 2), (12, 3), (13, 4))
default <T> Seq2<T, V> mapKey(Function<K, T> function)

mapValue

根据key和value替换原有value

// ((1, 2), (2, 3), (3, 4)) -> mapValue((k, v) -> v + 10) -> ((1, 12), (2, 13), (3, 14))
default <T> Seq2<K, T> mapValue(BiFunction<K, V, T> function)

根据value替换为新的value

// ((1, 2), (2, 3), (3, 4)) -> mapValue(v -> v + 10) -> ((1, 12), (2, 13), (3, 14))
default <T> Seq2<K, T> mapValue(Function<V, T> function)

filter

根据key和value进行过滤

// ((1, 2), (2, 3), (3, 4)) -> filter((k, v) -> k % 2 == 1) -> ((1, 12), (3, 14))
default Seq2<K, V> filter(BiPredicate<K, V> predicate)

filterByKey

根据key进行过滤

// ((1, 2), (2, 3), (3, 4)) -> filterByKey(k -> k % 2 == 1) -> ((1, 12), (3, 14))
default Seq2<K, V> filterByKey(Predicate<K> predicate)

filterByValue

根据value进行过滤

// ((1, 2), (2, 3), (3, 4)) -> filterByValue(v -> v % 2 == 0) -> ((1, 12), (3, 14))
default Seq2<K, V> filterByValue(Predicate<V> predicate)

onEach

处理但不消费,逻辑与一元流一样

default Seq2<K, V> onEach(BiConsumer<K, V> consumer)

swap

交换key和value

// ((1, 2), (2, 3), (3, 4)) -> swap() -> ((2, 1), (3, 2), (4, 3))
default Seq2<V, K> swap()

cache

利用一元Pair流将二元流缓存

default Seq2<K, V> cache()

二元流转一元流

map

根据key和value将二元流直接映射为一元流

// ((1, 2), (2, 3), (3, 4)) -> map((k, v) -> k + v) -> (3, 5, 7)
default <T> Seq<T> map(BiFunction<K, V, T> function)

justKeys

只保留keys成为一元流

// ((1, 2), (2, 3), (3, 4)) -> justKeys() -> (1, 2, 3)
default Seq<K> justKeys()

justValues

只保留values成为一元流

// ((1, 2), (2, 3), (3, 4)) -> justValues() -> (2, 3, 4)
default Seq<V> justValues()

paired

把二元流转化为一元的Pair

default Seq<Pair<K, V>> paired()

二元流的终端操作

消费

consume

这同时也是二元流的定义

public interface Seq2<K, V> {
    void consume(BiConsumer<K, V> consumer);
}

聚合

fold

类似一元流,由初始值和三元递推函数function确定

// ((1, 2), (2, 3), (3, 4)) -> fold(0, (a, k, v) -> a + k + v) -> 15 (1+2 + 2+3 + 3+4)
default <E> E fold(E init, Function3<E, K, V, E> function)

reduce

类似一元流,由初始值和三元累加器accumulator确定

// ((1, 2), (2, 3), (3, 4)) -> reduce(new HashMap<>(), Map::put) -> {1=2, 2=3, 3=4}
default <E> E reduce(E des, Consumer3<E, K, V> accumulator)

toMap

指定两个映射函数toKeytoValue转为Map,遇到键冲突由新值覆盖

default <A, B> SeqMap<A, B> toMap(BiFunction<K, V, A> toKey, BiFunction<K, V, B> toValue)

也可以额外指定容器Map

default <A, B> SeqMap<A, B> toMap(Map<A, B> des, BiFunction<K, V, A> toKey, BiFunction<K, V, B> toValue)

也可以只指定容器Map

default SeqMap<K, V> toMap(Map<K, V> des)

也可以直接toMap,使用默认的LinkedSeqMap

default SeqMap<K, V> toMap()

值得提到的是,toMap得到的SeqMap依然是Seq2,所以这个聚合操作本身也是一种链式调用

max/minByKey

根据比较器comparator取得key最大/最小的Pair

default Pair<K, V> maxByKey(Comparator<K> comparator)
default Pair<K, V> minByKey(Comparator<K> comparator)

max/minByValue

根据比较器comparator取得value最大/最小的Pair

default Pair<K, V> maxByValue(Comparator<V> comparator)
default Pair<K, V> minByValue(Comparator<V> comparator)