Java 将列表缩减为后备链
Java reduce list to fallback chain
假设我在 Java 中有一些实体的列表,例如
List<Entity> entities = Arrays.asList(entity1, entity2, entity3...);
我想将其缩减为链对象的一个实例,例如:
class EntityChain {
private final Entity entity;
private final Optional<EntityChain> fallback;
private EntityChain(Builder builder) {
this.entity = builder.entity;
this.fallback = builder.fallback;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private Entity entity;
private Optional<EntityChain> fallback = Optional.empty();
public Builder withEntity(Entity entity) {
this.entity = entity;
return this;
}
public Builder withFallback(EntityChain fallback) {
this.fallback = Optional.of(fallback);
return this;
}
public EntityChain build() {
return new EntityChain(this);
}
}
}
EntityChain
是不可变的并且有一个构建器。
这样结果将是一个 EntityChain
实例,例如:
chain
-> entity = entity1
-> fallback
-> entity = entity2
-> fallback
-> entity = entity3
-> fallback
...
有没有可能用一些魔法来做到这一点Java 8 流利减少?
是
Stream.reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner)
这里适用吗?以某种方式使用它的生成器?
您可以在需要时通过延迟构建 EntityChain
来实现。我用Supplier<EntityChain>
搞定了
BiFunction<Supplier<EntityChain>, Entity, Supplier<EntityChain>> reducing =
(initializer, entity) ->
// get the EntityChain instance when get() called.
() -> Optional.ofNullable(initializer.get())
// create a builder with fallback if EntityChain present
.map(fallback -> EntityChain.builder().withFallback(fallback))
// create a builder without fallback
.orElseGet(EntityChain::builder)
//build the EntityChain
.withEntity(entity).build();
// combiner never be used in sequentially stream
BinaryOperator<Supplier<EntityChain>> rejectedInParallelStream = (t1, t2) -> {
throw new IllegalStateException("Can't be used in parallel stream!");
};
EntityChain chain = reverse(entities).
stream().reduce(() -> null, reducing, rejectedInParallelStream)
//when the initializer chain built/reduced,
//calling the get() to fetch EntityChain header
.get();
//copy & reverse the copied List
static <T> List<T> reverse(List<T> list) {
List<T> it = list.stream().collect(Collectors.toList());
Collections.reverse(it);
return it;
}
输出
-> entity = entity1
-> fallback
-> entity = entity2
-> fallback (empty)
为了将列表缩减为构建器,您需要一个累加器 (Builder::withEntity
) 和一个组合器 (Builder::combine
):
public class ChainBuilder {
public static class Entity {
int data;
public Entity(int i) {
data = i;
}
@Override
public String toString() {
return "Entity [data=" + data + "]";
}
}
public static class EntityChain {
private Entity entity;
private Optional<EntityChain> fallback = null;
@Override
public String toString() {
return "EntityChain [entity=" + entity + ", fallback=" + fallback + "]";
}
public static class Builder {
private EntityChain chain = null;
public Builder() { }
private static EntityChain newChainLink(Entity e){
EntityChain n = new EntityChain();
n.entity = e;
n.fallback = Optional.empty();
return n;
}
/** accumulator, attaches to the end of the chain */
public Builder withEntity(Entity e) {
if(chain == null) {
chain = newChainLink(e);
} else {
EntityChain last = getLast();
last.fallback = Optional.of(newChainLink(e));
}
return this;
}
/** combiner, glues two chains together */
public Builder combine(Builder u) {
if(u.chain != null) {
getLast().fallback = Optional.of(u.chain);
}
return this;
}
/** returns the end of the chain */
private EntityChain getLast() {
EntityChain link = chain;
while(link.fallback.isPresent()){
link = link.fallback.get();
}
return link;
}
public EntityChain build() {
return chain;
}
}
}
public static void main(String[] args) {
List<Entity> entities = Arrays.asList(new Entity(1), new Entity(2), new Entity(3));
final Builder reduced = entities.stream().reduce(new EntityChain.Builder(),
(t,u)->t.withEntity(u),
(t,u)->t.combine(u));
System.out.println(reduced.build());
}
}
这会打印:
EntityChain [entity=Entity [data=1], fallback=Optional[EntityChain [entity=Entity [data=2], fallback=Optional[EntityChain [entity=Entity [data=3], fallback=Optional.empty]]]]]
经过思考,我发现我可以在顺序流中减少时完全删除持有人Supplier<EntityChain>
。该算法是构建实体链的逆向:首先构建 entity(n) ,然后是 entity(n-1), ... entity(0).
BiFunction<EntityChain, Entity, EntityChain> reducing =
(next, entity) -> Optional.ofNullable(next)
// create a builder with fallback if EntityChain present
.map(fallback -> EntityChain.builder().withFallback(fallback))
// create a builder without fallback
.orElseGet(EntityChain::builder)
//build the EntityChain
.withEntity(entity).build();
// combiner never be used in sequentially stream
BinaryOperator<EntityChain> rejectedInParallelStream = (t1, t2) -> {
//when you use parallel the chain order maybe changed, and the result is wrong.
throw new IllegalStateException("Can't be used in parallel stream!");
};
EntityChain chain = reverse(entities).
stream().reduce(null, reducing, rejectedInParallelStream);
//copy & reverse the copied List
static <T> List<T> reverse(List<T> list) {
List<T> it = list.stream().collect(Collectors.toList());
Collections.reverse(it);
return it;
}
输出
-> entity = entity1
-> fallback
-> entity = entity2
-> fallback (empty)
假设我在 Java 中有一些实体的列表,例如
List<Entity> entities = Arrays.asList(entity1, entity2, entity3...);
我想将其缩减为链对象的一个实例,例如:
class EntityChain {
private final Entity entity;
private final Optional<EntityChain> fallback;
private EntityChain(Builder builder) {
this.entity = builder.entity;
this.fallback = builder.fallback;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private Entity entity;
private Optional<EntityChain> fallback = Optional.empty();
public Builder withEntity(Entity entity) {
this.entity = entity;
return this;
}
public Builder withFallback(EntityChain fallback) {
this.fallback = Optional.of(fallback);
return this;
}
public EntityChain build() {
return new EntityChain(this);
}
}
}
EntityChain
是不可变的并且有一个构建器。
这样结果将是一个 EntityChain
实例,例如:
chain
-> entity = entity1
-> fallback
-> entity = entity2
-> fallback
-> entity = entity3
-> fallback
...
有没有可能用一些魔法来做到这一点Java 8 流利减少?
是
Stream.reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner)
这里适用吗?以某种方式使用它的生成器?
您可以在需要时通过延迟构建 EntityChain
来实现。我用Supplier<EntityChain>
搞定了
BiFunction<Supplier<EntityChain>, Entity, Supplier<EntityChain>> reducing =
(initializer, entity) ->
// get the EntityChain instance when get() called.
() -> Optional.ofNullable(initializer.get())
// create a builder with fallback if EntityChain present
.map(fallback -> EntityChain.builder().withFallback(fallback))
// create a builder without fallback
.orElseGet(EntityChain::builder)
//build the EntityChain
.withEntity(entity).build();
// combiner never be used in sequentially stream
BinaryOperator<Supplier<EntityChain>> rejectedInParallelStream = (t1, t2) -> {
throw new IllegalStateException("Can't be used in parallel stream!");
};
EntityChain chain = reverse(entities).
stream().reduce(() -> null, reducing, rejectedInParallelStream)
//when the initializer chain built/reduced,
//calling the get() to fetch EntityChain header
.get();
//copy & reverse the copied List
static <T> List<T> reverse(List<T> list) {
List<T> it = list.stream().collect(Collectors.toList());
Collections.reverse(it);
return it;
}
输出
-> entity = entity1
-> fallback
-> entity = entity2
-> fallback (empty)
为了将列表缩减为构建器,您需要一个累加器 (Builder::withEntity
) 和一个组合器 (Builder::combine
):
public class ChainBuilder {
public static class Entity {
int data;
public Entity(int i) {
data = i;
}
@Override
public String toString() {
return "Entity [data=" + data + "]";
}
}
public static class EntityChain {
private Entity entity;
private Optional<EntityChain> fallback = null;
@Override
public String toString() {
return "EntityChain [entity=" + entity + ", fallback=" + fallback + "]";
}
public static class Builder {
private EntityChain chain = null;
public Builder() { }
private static EntityChain newChainLink(Entity e){
EntityChain n = new EntityChain();
n.entity = e;
n.fallback = Optional.empty();
return n;
}
/** accumulator, attaches to the end of the chain */
public Builder withEntity(Entity e) {
if(chain == null) {
chain = newChainLink(e);
} else {
EntityChain last = getLast();
last.fallback = Optional.of(newChainLink(e));
}
return this;
}
/** combiner, glues two chains together */
public Builder combine(Builder u) {
if(u.chain != null) {
getLast().fallback = Optional.of(u.chain);
}
return this;
}
/** returns the end of the chain */
private EntityChain getLast() {
EntityChain link = chain;
while(link.fallback.isPresent()){
link = link.fallback.get();
}
return link;
}
public EntityChain build() {
return chain;
}
}
}
public static void main(String[] args) {
List<Entity> entities = Arrays.asList(new Entity(1), new Entity(2), new Entity(3));
final Builder reduced = entities.stream().reduce(new EntityChain.Builder(),
(t,u)->t.withEntity(u),
(t,u)->t.combine(u));
System.out.println(reduced.build());
}
}
这会打印:
EntityChain [entity=Entity [data=1], fallback=Optional[EntityChain [entity=Entity [data=2], fallback=Optional[EntityChain [entity=Entity [data=3], fallback=Optional.empty]]]]]
经过思考,我发现我可以在顺序流中减少时完全删除持有人Supplier<EntityChain>
。该算法是构建实体链的逆向:首先构建 entity(n) ,然后是 entity(n-1), ... entity(0).
BiFunction<EntityChain, Entity, EntityChain> reducing =
(next, entity) -> Optional.ofNullable(next)
// create a builder with fallback if EntityChain present
.map(fallback -> EntityChain.builder().withFallback(fallback))
// create a builder without fallback
.orElseGet(EntityChain::builder)
//build the EntityChain
.withEntity(entity).build();
// combiner never be used in sequentially stream
BinaryOperator<EntityChain> rejectedInParallelStream = (t1, t2) -> {
//when you use parallel the chain order maybe changed, and the result is wrong.
throw new IllegalStateException("Can't be used in parallel stream!");
};
EntityChain chain = reverse(entities).
stream().reduce(null, reducing, rejectedInParallelStream);
//copy & reverse the copied List
static <T> List<T> reverse(List<T> list) {
List<T> it = list.stream().collect(Collectors.toList());
Collections.reverse(it);
return it;
}
输出
-> entity = entity1
-> fallback
-> entity = entity2
-> fallback (empty)