假设我有一些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)

在这里适用吗?使用某种方式是建设者?

最佳答案

经过思考,我发现在按顺序减少流时可以完全删除持有人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)

07-24 09:19