文章目录
- 前言
- Stream是什么
- Stream流语法
- Stream流的常用方法
- 代码示例
前言
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Stream是什么
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。可以是集合,数组,I/O channel,产生器generator 等。
- 聚合操作 类似SQL语句一样的操作,比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同,Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格(fluent style)。这样做可以对操作进行优化,比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代,这叫做外部迭代。Stream提供了内部迭代的方式,通过访问者模式(Visitor)实现。
Stream流语法
| stream of elements +> |filter±> |sorted±> |map±> |collect|
Stream流的常用方法
- 终结方法:返回值类型不再是Stream接口本身类型的方法,例如:forEach方法和count方法
- 非终结方法/延迟方法:返回值类型仍然是Stream接口自身类型的方法,除了终结方法都是延迟方法。例如:filter,limit,skip,map,conat
方法名称 | 方法作用 | 方法种类 | 是否支持链式调用 |
---|---|---|---|
count | 统计个数 | 终结方法 | 否 |
forEach | 迭代处理 | 终结方法 | 否 |
filter | 过滤 | 函数拼接 | 是 |
limit | 取用前几个 | 函数拼接 | 是 |
skip | 跳过前几个 | 函数拼接 | 是 |
map | 映射 | 函数拼接 | 是 |
concat | 组合 | 函数拼接 | 是 |
distinct | 去重 | 函数拼接 | 否 |
sorted | 排序 | 函数拼接 | 是 |
peek | 流中调用 | 函数拼接 | 是 |
collect | 集合 | 函数拼接 | 是 |
代码示例
public class Test {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("一往情深");list.add("石昊");list.add("秦昊");list.add("石中天");// 过滤出名字结尾有“昊”的名字list.stream().filter(p -> p.endsWith("昊")).forEach(p -> {System.out.println("符合条件的姓名:" + p);});System.out.println("--------------------------------");// 过滤出名字第一个字有“石”的名字,并且名字长度是3个数list.stream().filter(p -> p.startsWith("石")).filter(p -> p.length() == 3).forEach(p -> {System.out.println("符合条件的姓名:" + p);});}
}
输出:
符合条件的姓名:石昊
符合条件的姓名:秦昊
--------------------------------
符合条件的姓名:石中天
public class Test {public static void main(String[] args) {String str = "一往情深 ,石昊,秦昊,石中天, , 一往情深,AA,aa";// 1. 按“,”分割成数组// 2. 去除左右两边空格// 3. 转小写// 4. 过滤出不为空的// 5. 去重Arrays.stream(str.split(",")).map(String::trim).map(String::toLowerCase).filter(StringUtil::isNotEmpty).distinct().collect(Collectors.toList()).forEach(s -> {switch (s) {case "一往情深":System.out.println("作者:" + s);break;case "石昊":System.out.println("这个就厉害了:" + s);break;default:System.out.println(s);break;}});}
}
输出:
作者:一往情深
这个就厉害了:石昊
秦昊
石中天
aa
public class Test {public static void main(String[] args) {// stream()操作对象示例List<User> userList = new ArrayList<>();userList.add(new User(1, "1号选手"));userList.add(new User(2, "2号选手"));userList.add(new User(3, "3号选手"));// 过滤出id大于1的UserSystem.out.println(userList.stream().filter(p -> p.getId() > 1).collect(Collectors.toList()));// 1. 按id倒序,从大到小// 2. 过滤出name中不包含2的User对象System.out.println(userList.stream().sorted(Comparator.comparing(User::getId).reversed()).filter(p -> !p.getName().contains("2")).collect(Collectors.toList()));}
}@Getter
@ToString
class User {private Integer id;private String name;public User(Integer id, String name) {this.id = id;this.name = name;}
}
输出:
[User(id=2, name=2号选手), User(id=3, name=3号选手)]
[User(id=3, name=3号选手), User(id=1, name=1号选手)]
public class test {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);// 统计IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();System.out.println("列表中最大的数 : " + stats.getMax());System.out.println("列表中最小的数 : " + stats.getMin());System.out.println("所有数之和 : " + stats.getSum());System.out.println("平均数 : " + stats.getAverage());}
}
输出:
列表中最大的数 : 7
列表中最小的数 : 2
所有数之和 : 25
平均数 : 3.5714285714285716