程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

带有状态的 Java Streams - 一个微不足道的练习 [重复]

发布于2021-07-21 09:19     阅读(1071)     评论(0)     点赞(21)     收藏(5)


在我接触 Java 8 流的过程中,下面的练习阻止了我。

鉴于IntStream.range(0, 6). 产生下面的字符串流:

"0, 1"
"1, 2"
"2, 3"
"3, 4"
"4, 5"

我想到了使用 Collectors.collectAndThen 将它传递给好的旧列表或数组并循环构建字符串列表,如下所示:

List<String> strgs = new ArrayList<>();
String prev = String.valueOf(nums[0]);
for (int i = 1; i < nums.length; i++) {
    strgs.add(prev+", "+String.valueOf(nums[i]));
    prev = String.valueOf(nums[i]);  
}

但它没有使用流的力量。我觉得 Venkat Subramaniam 说“我之后想洗个澡”。我想知道如何应用函数式技术,这样我就可以在编码后跳过淋浴!

另外,我想避免使用 StreamEx 或 JavaRx 之类的库,我想坚持使用普通的 Java 8 API。

编辑:@Tunaki,感谢您在我的问题中指出不清楚的措辞。它是由 Stream 的两个连续元素组成的对。更具体地说,像 Stream 这样的[1, 3, 5, 7, 9, ...]将是

"1, 3"
"3, 5"
"5, 7"
...

编辑 2

在对所有答案表示敬意之后,尽管我的问题与 Tunaki 指出的另一个问题重复。我想为 Bohemian 提供的答案扩展社区讨论。尽管有些人不喜欢他的回答,但它提出了一个严重的问题,即具有副作用的 reduce 操作。我对社区的要求是提供一个合理的反有效技术来解决这个问题。因此,我想重用波西米亚式答案如下:

给定输入: nums =new int[]{1,3,5,7,9}

请考虑以下片段:

List<CharSequence> stringList = new ArrayList<>();
IntBinaryOperator reductionWithSideEffect = (int left, int right) -> {
        stringList.add(new StringBuilder().append(left).append(", ").append(right));
        return right;
};
Arrays.stream(nums)
        .reduce(reductionWithSideEffect);
System.out.println(String.join(", ", stringList));

解决方案


在我看来,解决这个问题的最干净的方法是编写一个自定义拆分器并在其上创建一个 Stream。如果您不需要绝对最大的性能并且不关心并行处理(并行流可以工作,但效率低下),这并不是很难。像这样的事情会起作用:

public static <T, R> Stream<R> pairMap(BaseStream<T, ?> source,
        BiFunction<? super T, ? super T, ? extends R> mapper) {
    Spliterator<T> spltr = source.spliterator();
    long sourceSize = spltr.estimateSize();
    Spliterator<R> result = new Spliterators.AbstractSpliterator<R>(
            sourceSize > 0 && sourceSize < Long.MAX_VALUE ? sourceSize - 1 : sourceSize,
            spltr.characteristics() & (Spliterator.ORDERED | Spliterator.SIZED)) {
        T prev;
        boolean started;

        @Override
        public boolean tryAdvance(Consumer<? super R> action) {
            if (!started) {
                if (!spltr.tryAdvance(t -> prev = t))
                    return false;
                started = true;
            }
            return spltr.tryAdvance(t -> action.accept(mapper.apply(prev, prev = t)));
        }
    };
    return StreamSupport.stream(result, source.isParallel()).onClose(source::close);
}

mapper是基于输入流的一对相邻元素创建新流元素的函数。

用法示例:

pairMap(IntStream.range(0, 6), (a, b) -> a + ", " + b).forEach(System.out::println);

输出:

0, 1
1, 2
2, 3
3, 4
4, 5


所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/247967/e28bedeefff2f621fbd0/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

21 0
收藏该文
已收藏

评论内容:(最多支持255个字符)