文章目录

  • 1. 一个流的使用例子
  • 2. 流简介
  • 3. 流的特点
  • 4. 流基本操作
    • 4.1 中间操作
    • 4.2 终端操作
  • 5. 筛选和切片
    • 5.1 用谓词筛选
    • 5.2 筛选各异的元素
    • 5.3 截短流
    • 5.4 跳过元素
  • 6. 映射
    • 6.1 对流中每一个元素应用函数
    • 6.2 流的扁平化
  • 7. 查找和匹配
    • 7.1 检查谓词是否至少匹配一个元素
    • 7.2 检查谓词是否匹配所有元素
    • 7.3 查找任意元素
    • 7.4 查找第一个元素
  • 8. 归约
    • 8.1 元素求和
    • 8.2 最大值和最小值
  • 9. 数值流
    • 9.1 原始类型流特化
    • 9.2 数值范围
  • 10. 构建流
    • 10.1 由值创建流
    • 10.2 由数组创建流
    • 10.3 由文件生成流
    • 10.4 由函数生成流:创建无限流

1. 一个流的使用例子

场景:现在有一个菜品集合,需要找出菜品中的卡路里小于400的菜品并且按照卡路里多少进行排序

class Dish{String name;int price;int calories;public Dish(String name, int price, int calories) {super();this.name = name;this.price = price;this.calories = calories;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public int getCalories() {return calories;}public void setCalories(int calories) {this.calories = calories;}@Overridepublic String toString() {return "Dish [name=" + name + ", price=" + price + ", calories=" + calories + "]";}}

普通方式的实现:

public class StreamDemo {public static void main(String[] args) {List<Dish> menu=Arrays.asList(new Dish("pork",800),new Dish("beef",700),new Dish("chicken",400),new Dish("french fries",530),new Dish("rice",350),new Dish("fruit",120),new Dish("pizza",550));List<Dish> lowCaloriesDish=new ArrayList<>();for(Dish d:menu){if(d.getCalories()<400)lowCaloriesDish.add(d);}Collections.sort(lowCaloriesDish,new Comparator<Dish>() {@Overridepublic int compare(Dish o1, Dish o2) {return Integer.compare(o1.getCalories(), o2.getCalories());}});for(Dish d:lowCaloriesDish)System.out.println(d.getName()+"  "+d.getCalories());}
}

使用流实现:

import java.util.List;
import static java.util.stream.Collectors.toList;
public class StreamDemo {public static void main(String[] args) {List<Dish> menu=Arrays.asList(new Dish("pork",800),new Dish("beef",700),new Dish("chicken",400),new Dish("french fries",530),new Dish("rice",350),new Dish("fruit",120),new Dish("pizza",550));List<String> lowCaloriesDishName=menu.stream().filter(d->d.getCalories()<400).sorted((d1,d2)->d1.getCalories()-d2.getCalories()).map(d->d.getName()).collect(toList());for(String name:lowCaloriesDishName)System.out.println(name);}
}


2. 流简介

流是从支持数据处理操作的源生成的元素序列

  1. 元素序列:就像集合一样,流也提供了一个接口,可以访问特定元素类型的一组有序值
  2. 源:流会使用一个提供数据的源,如集合、数组或输入/输出资源
  3. 数据处理操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如filter、map、reduce、find、match、sort等
  4. 流水线:很多流操作本身会返回一个流,这样多个操作就可以链接起来,形成一个大的流水线
  5. 内部迭代:与使用迭代器显式迭代的集合不同,流的迭代操作是在背后进行的




3. 流的特点

1. 流只能遍历一次

public class StreamDemo {public static void main(String[] args) {List<String> title=Arrays.asList("Java","Python","Go");Stream<String> s=title.stream();s.forEach(System.out::println);s.forEach(System.out::println);}
}

2. 流使用内部迭代

public class StreamDemo {public static void main(String[] args) {List<Dish> menu=Arrays.asList(new Dish("pork",800),new Dish("beef",700),new Dish("chicken",400),new Dish("french fries",530),new Dish("rice",350),new Dish("fruit",120),new Dish("pizza",550));/** 集合使用外部迭代*/List<String> names=new ArrayList<>();Iterator<Dish> iterator=menu.iterator();while(iterator.hasNext()) {Dish d=iterator.next();names.add(d.getName());}System.out.println(names);/** 流使用内部迭代*/List<String> names2=menu.stream().map(Dish::getName).collect(toList());System.out.println(names2);}
}

4. 流基本操作

4.1 中间操作

List<String> names=menu.stream().filter(d->d.getCalories()>400).map(d->d.getName()).limit(3).collect(toList());System.out.println(names);

代码中的filter、map、limit是中间操作


4.2 终端操作

public static void main(String[] args) {List<Dish> menu=Arrays.asList(new Dish("pork",800),new Dish("beef",700),new Dish("chicken",400),new Dish("french fries",530),new Dish("rice",350),new Dish("fruit",120),new Dish("pizza",550));menu.stream().forEach(System.out::println);}

将流中的数据输出到终端上



5. 筛选和切片

5.1 用谓词筛选

filter:返回一个包括所有符合谓词的元素的流

public static void main(String[] args) {List<Dish> menu=Arrays.asList(new Dish("pork",800,false),new Dish("beef",700,false),new Dish("chicken",400,false),new Dish("french fries",530,false),new Dish("rice",350,false),new Dish("fruit",120,true),new Dish("tomato",200,true));List<Dish> vegetableMenu=menu.stream().filter(d->d.isVegetable)//是否是蔬菜.collect(toList());System.out.println(vegetableMenu);}

5.2 筛选各异的元素

distinct():它会返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流

List<Integer> numbers=Arrays.asList(1,2,2,3,4,4,5,7);List<Integer> evenNumbers=numbers.stream().filter(x->x%2==0)//寻找偶数.collect(toList());System.out.println(evenNumbers);//[2, 2, 4, 4]

上面代码在一个集合中寻找偶数,结果中有两个相同的2,两个相同的4

List<Integer> numbers=Arrays.asList(1,2,2,3,4,4,5,7);List<Integer> evenNumbers=numbers.stream().filter(x->x%2==0)//寻找偶数.distinct()//distinct保证元素唯一.collect(toList());System.out.println(evenNumbers);//[2, 4]

5.3 截短流

limit(n):该方法会返回一个不超过给定长度的流

List<Integer> numbers=Arrays.asList(1,2,3,4,5,6,7,8,9);List<Integer> evenNumbers=numbers.stream().filter(x->x%2==0)//寻找偶数.collect(toList());System.out.println(evenNumbers);//[2, 4, 6, 8]
List<Integer> numbers=Arrays.asList(1,2,3,4,5,6,7,8,9);List<Integer> evenNumbers=numbers.stream().filter(x->x%2==0)//寻找偶数.limit(2).collect(toList());System.out.println(evenNumbers);//[2, 4]

5.4 跳过元素

skip方法返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流

List<Integer> numbers=Arrays.asList(1,2,3,4,5,6,7,8,9);List<Integer> evenNumbers=numbers.stream().filter(x->x%2==0)//寻找偶数.skip(1)//跳过流中的前n个元素.collect(toList());System.out.println(evenNumbers);//[4, 6, 8]

6. 映射

6.1 对流中每一个元素应用函数

     /** 先找出集合中的偶数  再将这些偶数进行平方操作*/List<Integer> numbers=Arrays.asList(1,2,3,4,5,6,7,8,9);List<Integer> evenNumbers=numbers.stream().filter(x->x%2==0)//寻找偶数.map(x->x*x).collect(toList());System.out.println(evenNumbers);//[2,4,6,8]->[4, 16, 36, 64]

6.2 流的扁平化

     List<String> words=Arrays.asList("Monday","Tuesday");List<String> characters=words.stream().map(word->word.split(""))//将每个单词转化为一个字符串数组.flatMap(Arrays::stream)//将每个字符数组扁平化.collect(toList());System.out.println(characters);//[M, o, n, d, a, y, T, u, e, s, d, a, y]


7. 查找和匹配

7.1 检查谓词是否至少匹配一个元素

anyMatch方法可以回答“流中是否有一个元素能匹配给定的谓词

List<Integer> numbers=Arrays.asList(1,2,4);if(numbers.stream().anyMatch(x->x%2==1)) {System.out.println("numbers集合中至少有1个奇数");}else {System.out.println("numbers集合中没有奇数");    }

7.2 检查谓词是否匹配所有元素

allMatch检查流中的元素是否都能匹配给定的谓词

List<Integer> numbers=Arrays.asList(1,2,3);if(numbers.stream().allMatch(x->x%2==1)) {System.out.println("numbers集合中都是奇数");}else {System.out.println("numbers集合中不全是奇数");  }

7.3 查找任意元素

findAny方法将返回当前流中的任意元素

List<Integer> numbers=Arrays.asList(1,2,3,4,5);Optional<Integer> allEven=numbers.stream().filter(x->x%2==0).findAny();System.out.println(allEven);

7.4 查找第一个元素

List<Integer> numbers=Arrays.asList(1,2,3,4,5);Optional<Integer> firstEven=numbers.stream().filter(x->x%2==0).findFirst();System.out.println(firstEven);//Optional[2]

8. 归约

8.1 元素求和

     /** reduce的第一个参数:初始值 相当于给求和一个初值* reduce的第二个参数:一个BinaryOperator<T>来将两个元素结合起来产生一个新值*/List<Integer> numbers=Arrays.asList(4,3,5,9);int sum=numbers.stream().reduce(0, (a,b)->a+b);System.out.println("sum="+sum);//21

8.2 最大值和最小值

     /** reduce重载的变体* 它不接受初始值,但是会返回一个Optional对象*/List<Integer> numbers=Arrays.asList(4,3,5,9);Optional<Integer> maxNum=numbers.stream().reduce((x,y)->x>y?x:y);Optional<Integer> minNum=numbers.stream().reduce((x,y)->x<y?x:y);System.out.println("maxNum="+maxNum);//maxNum=Optional[9]System.out.println("minNum="+minNum);//minNum=Optional[3]

9. 数值流

9.1 原始类型流特化

class Goods{String name;int price;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public Goods(String name, int price) {super();this.name = name;this.price = price;}@Overridepublic String toString() {return "Goods [name=" + name + ", price=" + price + "]";}}

1. 映射到数值流

mapToInt返回一个IntStream(而不是一个Stream)

public static void main(String[] args) {List<Goods> goods=Arrays.asList(new Goods("Apple", 10),new Goods("Banana", 5),new Goods("Bread", 3),new Goods("Milk", 15),new Goods("Wine", 20));//将Good对象流映射到价格流(整数流) 并求出价格总和int priceSum=goods.stream().mapToInt(g->g.getPrice()).sum();System.out.println(priceSum);//53}

2.转换回对象流

boxed方法:要把原始流转换成一般流(这里每个int都会装箱成一个Integer)

List<Goods> goods=Arrays.asList(new Goods("Apple", 10),new Goods("Banana", 5),new Goods("Bread", 3),new Goods("Milk", 15),new Goods("Wine", 20));IntStream intStream=goods.stream().mapToInt(g->g.getPrice());Stream<Integer> stream=intStream.boxed();

9.2 数值范围

Java 8引入了两个可以用于IntStream和LongStream的静态方法,帮助生成这种范围:range(左闭右开)和rangeClosed(左闭右闭)

//生成[1,50]内的所有偶数IntStream evenNums=IntStream.rangeClosed(1, 50).filter(x->x%2==0);evenNums.forEach(x->{System.out.print(" "+x);});


10. 构建流

10.1 由值创建流

使用静态方法Stream.of,通过显式值创建一个流

     Stream<String> stream=Stream.of("Java","Python","Go");stream.forEach(System.out::println);

10.2 由数组创建流

使用静态方法Arrays.stream从数组创建一个流

     int[] numbers= {1,2,3,4,5,6};IntStream stream=Arrays.stream(numbers);stream.forEach(System.out::println);

10.3 由文件生成流

Stream<String> lines=null;try {lines=Files.lines(Paths.get("data.txt"),Charset.defaultCharset());  lines.forEach(System.out::println);} catch (IOException e) {e.printStackTrace();}finally {lines.close();}

10.4 由函数生成流:创建无限流

1. 迭代

/** iterate方法接受一个初始值(在这里是0),还有一个依次应用在每个产生的新值上的Lambda(UnaryOperator<t>类型)* 这里,我们使用Lambda n-> n+2,返回的是前一个元素加上2*/Stream.iterate(0,n->n+2).limit(10).forEach(System.out::println);
     /** 生成斐波那契数列*/Stream.iterate(new int[] {0,1},t->new int[] {t[1],t[0]+t[1]}).limit(10).forEach(t->{System.out.println(t[0]+" "+t[1]);});

2. 生成

     /** 生成10个随机数*/Stream.generate(Math::random).limit(10).forEach(System.out::println);

Java流式编程详解相关推荐

  1. Java-Stream流式编程详解

    目录 一.概述 1.1.特性: 不存储数据.不改变数据源.不可重复使用 1.2.生成流的方式 1.3.反转流到集合 二.中间节点与终值节点 2.1.中间节点 2.2.终值节点 三.Stream的方法 ...

  2. Java stream流式计算详解

    Java stream流式计算详解 1. Stream概述 1.1 Stream简介 1.2 Stream分类 2. Stream操作 2.1 Stream创建 2.2 Stream无状态操作 2.3 ...

  3. Java JUC并发编程详解

    Java JUC并发编程详解 1. JUC概述 1.1 JUC简介 1.2 进程与线程 1.2 并发与并行 1.3 用户线程和守护线程 2. Lock接口 2.1 Synchronized 2.2 什 ...

  4. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  5. java流式编程(六)Collector接口

    目录 一.接口定义 二.接口泛型 一.接口定义 public interface Collector<T, A, R> {Supplier<A> supplier();BiCo ...

  6. Java高并发编程详解系列-类加载

    之前在写关于JVM的时候提到过类加载机制,类加载机制也是在Java面试中被经常问道的一个问题,在这篇博客中就来了解一下关于类加载的知识. 类加载   在JVM执行Java程序的时候实际上执行的编译好的 ...

  7. flink大数据处理流式计算详解

    flink大数据处理 文章目录 flink大数据处理 二.WebUI可视化界面(测试用) 三.Flink部署 3.1 JobManager 3.2 TaskManager 3.3 并行度的调整配置 3 ...

  8. java socket/Serversocket编程详解(中/英文)

    socket /套接字 Sockets let you send raw streams of bytes back and forth between two computers, giving y ...

  9. Java高并发编程详解系列-线程上下文设计模式及ThreadLocal详解

    导语   在之前的分享中提到过一个概念就是线程之间的通信,都知道在线程之间的通信是一件很消耗资源的事情.但是又不得不去做的一件事情.为了保证多线程线程安全就必须进行线程之间的通信,保证每个线程获取到的 ...

最新文章

  1. 关于Android 构建
  2. linux cmake 多线程 错误 undefined reference to 'pthread_create'
  3. respect labor
  4. p字间距 html段落内文字设置字间距间隔
  5. 常用的C#正则表达式!
  6. Java基础学习记录
  7. python codefirst_Python code.co_consts方法代码示例
  8. 飞线5根连接图_手机主板焊盘掉点飞线维修方法
  9. FPGA入门——1位全加器设计
  10. php扩展 ioncube组件的安装方法_安装IonCube Loader扩展方法
  11. mysql data seek_mysql_data_seek函数详解
  12. 视频大数据与物联网(IoT)融合发展的探索
  13. RTX用户帮助中心群:177262328
  14. RFID NFC NfcA NfcB NfcF NfcV Ndef NdefFormatable相关详解
  15. BIgDecimal的用法,及与各类数据类型的转换
  16. html2Canvas 边框虚线
  17. 区块链实战(一)实现简单的区块与区块链交易
  18. k8s pod 无法运行,错误registry.access.redhat.com/rhel7/pod-infrastructure:latest
  19. FairyGUI学习
  20. 测试游戏战地1配置软件,《战地1》显卡横向测试:良心真优化

热门文章

  1. 科学家首次拍到座头鲸交配场景:持续仅30秒
  2. 福禄克DSX-600测线仪使用手册
  3. 21款奔驰款奔驰GLC260L升级香氛负离子 告别异味
  4. C语言:输入10个人的英文(拼音也行)名字,名字按字母顺序从小到大排列.
  5. 免费赠书 | 房价的一元回归分析
  6. 全国行政区划代码(json对象)---只包含城市代号和城市名称的json对象代码(包括县级市)
  7. 多任务进化优化算法(三)利用显式自编码器的进化多任务、基于生物群落共生的进化多任务优化简介
  8. 蓝牙客户端QBluetoothSocket的使用——Qt For Android
  9. RT_Thread_临界资源保护
  10. java-php-python-ssm基于汽车美容管理计算机毕业设计