forked from plusone/plusone-commons
添加流 API
parent
eba31a93f3
commit
dc86c59d91
|
@ -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<T> extends Consumer<Consumer<T>> {
|
||||||
|
// 这个方法和 forEach 是完全等价的
|
||||||
|
void accept(Consumer<T> consumer);
|
||||||
|
|
||||||
|
static <T> Seq<T> from(Collection<T> collection) {
|
||||||
|
return collection::forEach;
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> Seq<T> unit(T t) {
|
||||||
|
return c -> c.accept(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <E> Seq<E> map(Function<T, E> func) {
|
||||||
|
Seq<T> srcSeq = this;
|
||||||
|
return c -> srcSeq.accept((T t) -> c.accept(func.apply(t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <E> Seq<E> flatMap(Function<T, Seq<E>> function) {
|
||||||
|
Seq<T> srcSeq = this;
|
||||||
|
return c -> srcSeq.accept(t -> function.apply(t).accept(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
default Seq<T> filter(Predicate<T> predicate) {
|
||||||
|
Seq<T> srcSeq = this;
|
||||||
|
return (Consumer<T> c) -> srcSeq.accept((T t) -> {
|
||||||
|
if (predicate.test(t)) {
|
||||||
|
c.accept(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stop() {
|
||||||
|
throw StopException.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
default void consumeTillStop(Consumer<T> consumer) {
|
||||||
|
try {
|
||||||
|
accept(consumer);
|
||||||
|
} catch (StopException ignore) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default Seq<T> take(int n) {
|
||||||
|
return c -> {
|
||||||
|
int[] i = { n };
|
||||||
|
consumeTillStop(t -> {
|
||||||
|
if (i[0]-- > 0) {
|
||||||
|
c.accept(t);
|
||||||
|
} else {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default Seq<T> drop(int n) {
|
||||||
|
return c -> {
|
||||||
|
int[] a = { n - 1 };
|
||||||
|
accept(t -> {
|
||||||
|
if (a[0] < 0) {
|
||||||
|
c.accept(t);
|
||||||
|
} else {
|
||||||
|
a[0]--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default Seq<T> onEach(Consumer<T> consumer) {
|
||||||
|
Seq<T> srcSeq = this;
|
||||||
|
return c -> srcSeq.accept(consumer.andThen(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <E, R> Seq<R> zip(Iterable<E> iterable, BiFunction<T, E, R> function) {
|
||||||
|
return c -> {
|
||||||
|
Iterator<E> 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<T> toList() {
|
||||||
|
ImmutableList.Builder<T> builder = ImmutableList.builder();
|
||||||
|
accept(builder::add);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
default Set<T> toSet() {
|
||||||
|
ImmutableSet.Builder<T> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Integer> list = ImmutableList.of(108, 2333, 666, 555, 1, 2, 3, 23, 78, 65, 77, 22, 108);
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
Seq<String> targetSeq = new Seq<String>() {
|
||||||
|
@Override
|
||||||
|
public void accept(Consumer<String> 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<String> set = new TreeSet<>();
|
||||||
|
Seq<String> s = result::forEach;
|
||||||
|
s.accept(set::add);
|
||||||
|
log.info("{}", set);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterable<Integer> produceEvenNumbers(int upto) {
|
||||||
|
Seq<Integer> seq = c -> {
|
||||||
|
for (int i = 0; i <= upto; i += 2) {
|
||||||
|
c.accept(i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return seq.toList();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue