首页 > 编程语言 >提前中止Java Stream forEach的优雅解决方案

提前中止Java Stream forEach的优雅解决方案

时间:2023-03-04 11:33:05浏览次数:43  
标签:predicate Java Stream spliterator element boolean forEach public

1.概述

Java Stream foreach 是一种声明式的,整洁的遍历循环。但是当我们满足某个条件想要中止这个循环的时候,通常却十分繁琐,比如使用异常,但通常这不是一种很好的实现方案

2.Java 9 Stream.takeWhile()

Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck")
	.takeWhile(n - > n.length()%2 !=0)
  .forEach(System.out::println)

运行结果

cat
dog

3.定制Spliterator

如果版本还是Java8的情况

首先,从我们的流中拿一个Spliterator,提供一个谓词Predicate 去控制break.

  public static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<T> predicate) {
        CustomSpliterator<T> customSpliterator = new CustomSpliterator<>(stream.spliterator(),predicate);
        return StreamSupport.stream(customSpliterator,false);
    }
public class CustomSpliterator<T> extends Spliterators.AbstractSpliterator<T> {

    private Spliterator<T> spliterator;
    private Predicate<T> predicate;
    private boolean isMatched = true;

    public CustomSpliterator(Spliterator<T> spliterator, Predicate<T> predicate) {
        super(spliterator.estimateSize(), 0);
        this.spliterator = spliterator;
        this.predicate = predicate;
    }


    @Override
    public synchronized boolean tryAdvance(Consumer<? super T> consumer) {
        boolean hadNext = spliterator.tryAdvance(element -> {
            if(predicate.test(element) && isMatched){
                consumer.accept(element);
            }else{
                isMatched = false;
            }
        });
        return hadNext && isMatched;
    }
}

写一个测试,只要Stream里面还有元素并且满足我们的谓词的条件就会中止

  @Test
    public void whenCustomTakeWhileIsCalled_ThenCorrectItemsAreReturned(){
        Stream<String> initialStream = Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck");
        List<String> result = CustomTakeWhile.takeWhile(initialStream, x -> x.length() % 2 != 0).collect(Collectors.toList());
        assertEquals(asList("cat", "dog"),result);
    }

4.定制ForEach

不对Stream.spliterator进行包装的方法

public class CustomForEach {

    public static class Breaker{
        private boolean shouldBreak = false;
        public void stop(){
            shouldBreak = true;
        }
        boolean get(){
            return shouldBreak;
        }
    }
    public static <T> void forEach(Stream<T> stream, BiConsumer<T,Breaker> consumer){
        Spliterator<T> spliterator = stream.spliterator();
        boolean hadNext = true;
        Breaker breaker = new Breaker();
        while(hadNext && !breaker.get()){
            hadNext = spliterator.tryAdvance(element -> {
                consumer.accept(element, breaker);
            });
        }
    }
}
   @Test
    public void whenCustomTakeWhileIsCalled_ThenCorrectItemsAreReturned2(){
        Stream<String> initialStream = Stream.of("cat", "dog", "elephant", "fox", "rabbit", "duck");
        List<String> result = new ArrayList<>();

        CustomForEach.forEach(initialStream,(element,breaker)->{
            if(element.length() % 2 == 0){
                breaker.stop();
            } else{
                result.add(element);
            }
        });

        assertEquals(asList("cat", "dog"),result);
    }

标签:predicate,Java,Stream,spliterator,element,boolean,forEach,public
From: https://www.cnblogs.com/metatreasure/p/17177960.html

相关文章

  • Java应用【XIII】使用Apache Spark MLlib构建机器学习模型【上】
    如果您觉得本博客的内容对您有所帮助或启发,请关注我的博客,以便第一时间获取最新技术文章和教程。同时,也欢迎您在评论区留言,分享想法和建议。谢谢支持!​​一、引言1.1Spark......
  • JavaScript中Date对象
    当我们收到甲方的需求,要做一个类似于商城之类的项目的时候,JS的Date对象就至关重要了.因为在商城中,各种优惠和折扣,就需要在一个时间的紧迫下,才能达到一个火爆的效果,......
  • JAVA将Object类对象转为对应实体类对象
    方式一        利用com.fasterxml.jackson.databind.ObjectMapper 包下的convertValue方法将Object对象转为对应实体对象。Useruser=newObjectMapper().......
  • 用Java和C# SDK获取nacos配置
    在分布式配置nacos搭建踩坑指南(下)这篇文章里,我在nacos后台创建了一个配置,下面我们来看如何用Java和c#来获取这个配置.一.Java  1.启动nacos,和前面文章介绍的一样。......
  • java的基本语法—运算符
    运算符算术运算符:+,-,*,/,%,++,--赋值运算符:=关系运算符:>,<,>=,==,!=,instanceof逻辑运算符:&&与,||或,!非位运算符:&,|,~,>>,<<,>>>(了解!!!)条件运算符:?:扩展赋值运算符:+=,-=,*=,/=......
  • java-spring
    1、介绍2、架构图......
  • OpenAI Java SDK——chatgpt-java-v1.0.3更新支持GPT-3.5-Turbo,支持语音转文字,语音翻
    简介chatgpt-java是一个OpenAI的Java版SDK,支持开箱即用。目前以支持官网全部Api。支持最新版本GPT-3.5-Turbo模型以及whisper-1模型。增加chat聊天对话以及语音文件转文字......
  • JavaScript——快速判断数组对象的值是否全部满足条件
    前言EasyBe主题开发中遇到一个问题,查看了下MDN文档找到了比较合适的方法,这里只做了简单的示例,详细的一些描述和原理建议访问MDN进行查看;every:everysome:some内容ev......
  • java学习日记20230303-基本数据类型转换
    自动类型转换java程序在进行运算和赋值时,精度小的类型自动转化为精度大的类型,这个就是自动类型转化数据类型按照精度大小排序char-int-long-float-doublebyte-short-in......
  • mybatis动态标签——foreach批量添加和删除
    <!--【foreach标签】collection:设置要循环的数组或集合item:用一个字符串表示数组或集合中的每一个数据separator:设置每次循环的数据之间的分隔符......