diff --git a/src/main/java/xyz/zhouxy/plusone/commons/seq/Seq.java b/src/main/java/xyz/zhouxy/plusone/commons/seq/Seq.java new file mode 100644 index 0000000..82f753a --- /dev/null +++ b/src/main/java/xyz/zhouxy/plusone/commons/seq/Seq.java @@ -0,0 +1,133 @@ +package xyz.zhouxy.plusone.commons.seq; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.StringJoiner; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +@Beta +@FunctionalInterface +public interface Seq extends Consumer> { + // 这个方法和 forEach 是完全等价的 + void accept(Consumer consumer); + + static Seq from(Collection collection) { + return collection::forEach; + } + + static Seq unit(T t) { + return c -> c.accept(t); + } + + default Seq map(Function func) { + Seq srcSeq = this; + return c -> srcSeq.accept((T t) -> c.accept(func.apply(t))); + } + + default Seq flatMap(Function> function) { + Seq srcSeq = this; + return c -> srcSeq.accept(t -> function.apply(t).accept(c)); + } + + default Seq filter(Predicate predicate) { + Seq srcSeq = this; + return (Consumer c) -> srcSeq.accept((T t) -> { + if (predicate.test(t)) { + c.accept(t); + } + }); + } + + static void stop() { + throw StopException.INSTANCE; + } + + default void consumeTillStop(Consumer consumer) { + try { + accept(consumer); + } catch (StopException ignore) { + // ignore + } + } + + default Seq take(int n) { + return c -> { + int[] i = { n }; + consumeTillStop(t -> { + if (i[0]-- > 0) { + c.accept(t); + } else { + stop(); + } + }); + }; + } + + default Seq drop(int n) { + return c -> { + int[] a = { n - 1 }; + accept(t -> { + if (a[0] < 0) { + c.accept(t); + } else { + a[0]--; + } + }); + }; + } + + default Seq onEach(Consumer consumer) { + Seq srcSeq = this; + return c -> srcSeq.accept(consumer.andThen(c)); + } + + default Seq zip(Iterable iterable, BiFunction function) { + return c -> { + Iterator iterator = iterable.iterator(); + consumeTillStop(t -> { + if (iterator.hasNext()) { + c.accept(function.apply(t, iterator.next())); + } else { + stop(); + } + }); + }; + } + + default String join(String sep) { + StringJoiner joiner = new StringJoiner(sep); + accept(t -> joiner.add(t.toString())); + return joiner.toString(); + } + + default List toList() { + ImmutableList.Builder builder = ImmutableList.builder(); + accept(builder::add); + return builder.build(); + } + + default Set toSet() { + ImmutableSet.Builder set = ImmutableSet.builder(); + accept(set::add); + return set.build(); + } + + static class StopException extends RuntimeException { + private static final long serialVersionUID = -8975705275260458012L; + private static final StopException INSTANCE = new StopException(); + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + } +} \ No newline at end of file diff --git a/src/test/java/xyz/zhouxy/plusone/commons/seq/SeqTests.java b/src/test/java/xyz/zhouxy/plusone/commons/seq/SeqTests.java new file mode 100644 index 0000000..0d79881 --- /dev/null +++ b/src/test/java/xyz/zhouxy/plusone/commons/seq/SeqTests.java @@ -0,0 +1,56 @@ +package xyz.zhouxy.plusone.commons.seq; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.function.Consumer; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableList; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +class SeqTests { + + @Test + void testSeq() { + List list = ImmutableList.of(108, 2333, 666, 555, 1, 2, 3, 23, 78, 65, 77, 22, 108); + List result = new ArrayList<>(); + Seq targetSeq = new Seq() { + @Override + public void accept(Consumer c) { + list.forEach(t -> { + c.accept(String.valueOf(t + 250)); + }); + } + }; + targetSeq.accept(result::add); + // list.forEach(t -> { + // result.add(t + 250 + ""); + // }); + log.info("{}", result); + + for (Integer i : produceEvenNumbers(9)) { + System.out.print(i); + System.out.print(" "); + } + System.out.println(); + + Set set = new TreeSet<>(); + Seq s = result::forEach; + s.accept(set::add); + log.info("{}", set); + } + + Iterable produceEvenNumbers(int upto) { + Seq seq = c -> { + for (int i = 0; i <= upto; i += 2) { + c.accept(i); + } + }; + return seq.toList(); + } +}