Builder pattern with a Java 8 Stream

后端 未结 2 1824
遇见更好的自我
遇见更好的自我 2021-02-14 17:57

I am building an object with a simple loop:

WebTarget target = getClient().target(u);

for (Entry queryParam : queryParams.entrySet()) {
           


        
2条回答
  •  南笙
    南笙 (楼主)
    2021-02-14 18:16

    It's not very difficult to implement a correct foldLeft for Java 8 streams:

    @SuppressWarnings("unchecked")
    public static  U foldLeft(Stream stream, 
                                    U identity, BiFunction accumulator) {
        Object[] result = new Object[] { identity };
        stream.forEachOrdered(t -> result[0] = accumulator.apply((U) result[0], t));
        return (U) result[0];
    }
    

    Or in type-safe manner:

    public static  U foldLeft(Stream stream, 
                                    U identity, BiFunction accumulator) {
        class Box {
            U value;
            Box(U value) { this.value = value; }
        }
        Box result = new Box(identity);
        stream.forEachOrdered(t -> result.value = accumulator.apply(result.value, t));
        return result.value;
    }
    

    This works correctly for sequential and parallel streams. You can even have a speed gain using parallel streams if your stream has some CPU-consuming stateless intermediate operations like map: in this case the next element can be processed by map in the parallel with the current element processed by foldLeft. I don't agree that such operation is not suitable for Stream API, because it can be correctly expressed via already existing forEachOrdered.

    I have this operation in my StreamEx library, so you can use it like this:

    WebTarget target = EntryStream.of(queryParams).foldLeft(getClient().target(u), 
            (t, entry) -> t.queryParam(entry.getKey(), entry.getValue()))
    

提交回复
热议问题