Stream流
Stream流的使用方式
-
生成流:通过数据源(数组或者集合)生成流,
list.stream()
-
中间流:一个流后面可以跟随任意个中间操作,其目的是打开流,在过程中做 过滤/映射,然后返回一个新的流交给下一个操作使用,
filter()
-
结束流:一个流只能有一个终结操作,当这个操作执行后,流就被使用 完 了。
forEach()
Stream 才是真正的把函数式编程带给了 Java
demo: 筛选数据的两种方式:
- 正常调用方法,一步步筛选
- 通过Steam流的方式,把集合转成流,调用filter方法,进行筛选
package com.itxs.demo09;
import java.util.ArrayList;
/**
* @Classname : demo01
* @Description : TODO 简单使用一下Stream流
* @Author : lin_refuel@qq.com
*/
public class demo01 {
public static void main(String[] args) {
// 定义一个集合
ArrayList<String> list = new ArrayList<>();
beginningList(list); // 初始化集合里面的数据
// 找出集合里面名字是三个字以上的成员并且进行输出
ArrayList<String> three = new ArrayList<>();
for (String name : list) {
if(name.length() >= 3)
three.add(name);
}
// 输出three
for (String name : three) {
System.out.println(name);
}
System.out.println("==================================");
// 找出集合three里面里面姓郭的成员
ArrayList<String> threeguo = new ArrayList<>();
for (String name : three) {
if(name.startsWith("郭"))
threeguo.add(name);
}
for (String name : threeguo) {
System.out.println(name);
}
System.out.println("===================================");
// 通过Stream流的方式
System.out.println("通过Stream流的方式");
list.stream().filter(s -> s.length() >= 3).filter(s ->s.startsWith("郭")).forEach(System.out::println);
}
/**
* 初始化集合里面数据
* @param list 目标集合
*/
private static void beginningList(ArrayList<String> list) {
list.add("郭德纲");
list.add("郭麒麟");
list.add("郭汾阳");
list.add("郭冬临");
list.add("郭美美");
list.add("郭靖");
list.add("黄蓉");
list.add("小龙女");
list.add("杨过");
list.add("迪丽热巴");
list.add("古力娜扎");
}
}
模拟Stream流的过程
demo:对象的连贯操作,进行字符串拼接
定义一个名字为MyStringBuilder类
package com.itxs.demo09;
/**
* @Classname : MyStringBuilder
* @Description : TODO
* @Author : lin_refuel@qq.com
*/
public class MyStringBuilder {
// 定义一个空的字符串串
private String str = "";
public String getStr() {
return str;
}
// 模拟起始流
public MyStringBuilder append(String s){
str += s;
return this;// 返回当前自己
}
// 结束流
public void printInfo(){
System.out.println(str);
str = "";// 重置字符串
}
}
测试类:demo02
package com.itxs.demo09;
/**
* @Classname : demo02
* @Description : TODO 对象的连贯操作 - 模拟流的过程
* @Author : lin_refuel@qq.com
*/
public class demo02 {
public static void main(String[] args) {
MyStringBuilder msb = new MyStringBuilder();
// 对象连贯操作
msb.append("JavaSE ").append("MySQL ").append("JDBC ").append("Linux").printInfo();
System.out.println( msb.getStr());
}
}
运行结果:
Stream流的生成方式
Stream只能是针对数组或者集合进行操作
demo: 集合和数组生成流的方式
package com.itxs.demo09;
import java.util.*;
import java.util.stream.Stream;
/**
* @Classname : demo03
* @Description : TODO 集合,数组 生成流的方式
* @Author : lin_refuel@qq.com
*/
public class demo03 {
public static void main(String[] args) {
// Collection 单列集合 分为 Arraylist 和 Set
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();// Arraylist的生成流的方式
//***********************************************************
// Set集合生成流的方式
Set<String> s = new HashSet<>(); // Set集合中的HashSet
Stream<String> stream1 = s.stream();// Set集合生成流
//***********************************************************
// Map 双列集合
HashMap<String, String> hm = new HashMap<>();
Stream<String> stream2 = hm.keySet().stream();// 获取键值的流
Stream<String> stream3 = hm.values().stream();// 获取键对应的值的流
Set<Map.Entry<String, String>> entries = hm.entrySet();
Stream<Map.Entry<String, String>> stream4 = entries.stream();// 获取键值对的流
//*************************************************************
// 数组生成流的方式
String[] strArr ={};
Stream<String> S01 = Stream.of(strArr);
// 第二种方式,Stream。of()里面放入的是可变长的参数
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);// 直接生成一个Integer类型的流
Stream<String> stringStream = Stream.of("1", "2", "3");// 生成一个String类型的流
}
Stream中间流
中间流常用的方法
package com.itxs.demo09;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.stream.Stream;
/**
* @Classname : demo04
* @Description : TODO 中间流 & 结束流
* @Author : lin_refuel@qq.com
*/
public class demo04 {
public static void main(String[] args) {
// 定义一个集合
ArrayList<String> list = new ArrayList<>();
beginningList(list); // 初始化集合里面的数据
// 找出集合里面姓氏为郭的
// filter数据筛选
//list.stream().filter((s)->s.startsWith("郭")).forEach(System.out::println);
//***************************************************************************
// 截取集合里面前面6个数据
//list.stream().limit(6).forEach(System.out::println);
//***************************************************************************
// 跳过前面2个数据
//list.stream().skip(2).forEach(System.out::println);
//***************************************************************************
// 跳过前面2个数据 截取后面6个数据
// list.stream().skip(2).limit(6).forEach(System.out::println);
//***************************************************************************
// 结合两个流
// 跳过前面2个组成一个流
//Stream<String> s01 = list.stream().skip(2);;
// 取前面的4个
//Stream<String> s02 = list.stream().limit(4);
// 进行结合
// Stream.concat(s01,s02).forEach(System.out::println);// 不去重复
//Stream.concat(s01,s02).distinct().forEach(System.out::println);// 去重复
//***************************************************************************
// Stream流数据比较
// list.stream().sorted().forEach(System.out::println);// 自然规则进行排序
list.stream().sorted(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int res = o1.length() - o2.length(); // 按照字符串长度进行比较
return res == 0 ? o1.compareTo(o2) : res;
}
}).forEach(System.out::println);// 自定义规则进行排序
}
/**
* 初始化集合里面数据
*
* @param list 目标集合
*/
private static void beginningList(ArrayList<String> list) {
list.add("郭德纲");
list.add("郭麒麟");
list.add("郭汾阳");
list.add("郭冬临");
list.add("郭美美");
list.add("郭靖");
list.add("黄蓉");
list.add("小龙女");
list.add("杨过");
list.add("迪丽热巴");
list.add("古力娜扎");
}
}
Stream结束流
结束流常用的一些方法
package com.itxs.demo09;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.OptionalDouble;
import java.util.OptionalInt;
/**
* @Classname : demo05
* @Description : TODO 结束流用到的一些常用的方法
* @Author : lin_refuel@qq.com
*/
public class demo05 {
public static void main(String[] args) {
// 定义一个集合
ArrayList<String> list = new ArrayList<>();
// 调用add进行添加元素
list.add("23456789");
list.add("3456789");
list.add("123456789");
list.add("6789");
list.add("56789");
list.add("456789");
// 通过流的方式进行自然排序
//list.stream().sorted().forEach(System.out::println);
//*****************************************************
// 通过流的方式,按照字符串长度进行排序
//list.stream().sorted(Comparator.comparingInt(String::length).thenComparing(o -> o)).forEach(System.out::println);
//*****************************************************
// 把字符串转换成为Integer类型后进行排序 - 从小到大进行排序
//list.stream().map(Integer::parseInt).sorted().forEach(System.out::println);
//*****************************************************
// 求出上面字符串转成Integer类型后的和
//int sum = list.stream().mapToInt(Integer::parseInt).sum();
//System.out.println("sum = " + sum);
//*****************************************************
// 求出上面字符串转成Integer类型后的平均值
// OptionalDouble res = list.stream().mapToInt(s -> Integer.parseInt(s)).average();
// // OptionalDouble是一个对象,输出格式如下
// System.out.println(res);// 输出结果:OptionalDouble[2.5148455666666668E7]
// // 调用方法 getAsDouble 可以获取对应类型值
// double asDouble = res.getAsDouble();
// System.out.println(asDouble);// 输出结果:2.5148455666666668E7
//*****************************************************
// 可以统计流中元素个数的方法 count
//long count = list.stream().count();
//System.out.println(count);// 6个元素
//通过元素中长度超过6的元素个数
//long count = list.stream().filter(s -> s.length() > 6).count();
//System.out.println(count); // 3个
//******************************************************
// 可以求出字符串转Integer类型后元素的最大值和最小值
// 获取到对象max
OptionalInt max = list.stream().mapToInt(s -> Integer.parseInt(s)).max();
// 获取整数类型的值 getAsInt
System.out.println(max.getAsInt());// 123456789
// 最小值
OptionalInt min = list.stream().mapToInt(Integer::parseInt).min();
System.out.println(min.getAsInt());// 6789
}
}
案例 - 翻页的逻辑
- 每页输出5个数据
- 通过N(下一页) 和 B(上一页)进行换页码
package com.itxs.demo09;
import java.util.ArrayList;
import java.util.Scanner;
/**
* @Classname : demo06
* @Description : TODO 翻页的逻辑
* @Author : lin_refuel@qq.com
*/
public class demo06 {
public static void main(String[] args) {
// 定义一个集合
ArrayList<String> list = new ArrayList<>();
beginningList(list); // 初始化集合里面的数据
//=============================================
final int number = 5;// 每页展示的数据个数为5
int pageNumber = (list.size() / number) + (list.size() % number == 0 ? 0 : 1);// 页码数
int pages = 0;// 控制页码数
//=============================================
while (true) {
// 输出第一页的5个数据 skip中间流用于每次翻页跳过五个数据 limit用于取到5个数据
list.stream().skip(pages * number).limit(number).forEach(System.out::println);
System.out.println("N -- 下一页 || B -- 上一页 ");
// 重复进行调用方法进行选择翻页还是上一页n
switch (new Scanner(System.in).next()) {
case "N":
case "n":
pages = Math.min(pages + 1, pageNumber - 1);// 设置翻页的下限,返回最小值
break;
case "B":
case "b":
pages = Math.max(pages - 1, 0);// 设置翻页的上限,返回一个最大值
break;
default:
System.out.println("操作无效");
}
}
}
/**
* 初始化集合里面数据
*
* @param list 目标集合
*/
private static void beginningList(ArrayList<String> list) {
list.add("郭德纲");
list.add("郭麒麟");
list.add("郭汾阳");
list.add("郭冬临");
list.add("郭美美");
list.add("郭靖");
list.add("黄蓉");
list.add("小龙女");
list.add("杨过");
list.add("迪丽热巴");
list.add("古力娜扎");
list.add("小厮");
list.add("小v");
list.add("小a");
}
}