官网地址:https://www.oracle.com/java/technologies/javase/8-whats-new.html
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
1.1什么是 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)实现。
1.2 生成流
在Java 8中,集合接口有两个方法来生成流:
stream() −为集合创建串行流。
parallelStream() − 为集合创建并行流。
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
items.stream().filter(i -> !i.isEmpty()).collect(Collectors.toList());
1.3 forEach
Stream 提供了新的方法 forEach来迭代流中的每个数据。
遍历一个list:
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
items.forEach(item -> System.out.print(item));
//或者
items.forEach(System.out::println);
遍历一个map:
Map<String, String> map = new HashMap<>();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
map.put("d", "4");
map.put("e", "5");
map.forEach((k, v) -> System.out.println("key:" + k + " value:" + v));
1.4 map
map 方法用于映射每个元素到对应的结果(允许你把 object 转化成其他对象)
将一个List
class Person {
private Integer id;
private String name;
private Integer age;
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Person() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
public void map() {
List<Person> list = Arrays.asList(new Person(1, "zhangsan", 18), new Person(2, "lisi", 19), new Person(3, "wangwu", 20));
List namList = list.stream().map(x -> x.getName().toUpperCase()).collect(Collectors.toList());
System.out.println(namList);
}
输出:
[ZHANGSAN, LISI, WANGWU]
objects List转化为 其他 objects List
List<Person> list = Arrays.asList(new Person(1, "zhangsan", 18), new Person(2, "lisi", 19), new Person(3, "wangwu", 20));
List<Person> otherList = list.stream().map(x -> {
Person p = new Person();
p.setId(x.getId());
p.setName(x.getName());
p.setAge(x.getAge());
if ("lisi".equals(x.getName())) {
p.setName("zhaoliu");
}
return p;
}).collect(Collectors.toList());
System.out.println(otherList);
输出:
[Person{id=1, name='zhangsan', age=18}, Person{id=2, name='zhaoliu', age=19}, Person{id=3, name='wangwu', age=20}]
1.5 filter
filter 方法用于通过设置条件过滤出元素。以下代码片段使用filter 方法过滤出空字符串:
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
List filterList = items.stream().filter(i -> "4".equals(i)).collect(Collectors.toList());
System.out.println("filterList:"+filterList);
输出:
filterList:[4]
1.6 limit
limit 方法用于获取指定数量的流。
输出list中的三个元素:
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
List limitList = items.stream().limit(3).collect(Collectors.toList());
System.out.println(limitList);
输出:
[1, 2, 3]
1.7 sorted
sorted 方法用于对流进行排序。
对list进行排序:
List<String> items = Arrays.asList("1", "3", "5", "2", "4");
//正序
List sortedList = items.stream().sorted().collect(Collectors.toList());
//倒序
List sortedList2 = items.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
System.out.println(sortedList);
System.out.println(sortedList2);
输出:
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
对集合对象进行排序:
List<Person> persionList = Arrays.asList(new Person(2, "zhangsan", 18), new Person(1, "lisi", 19), new Person(3, "wangwu", 20));
//正序
List pList = persionList.stream().sorted(Comparator.comparing(x -> x.id)).collect(Collectors.toList());
//或者
List pList2 = persionList.stream().sorted(Comparator.comparing(Person::getId)).collect(Collectors.toList());
//倒序
List pList3 = persionList.stream().sorted(Comparator.comparing(Person::getId).reversed()).collect(Collectors.toList());
System.out.println(pList);
System.out.println(pList2);
System.out.println(pList3);
输出:
[Person{id=1, name='lisi', age=19}, Person{id=2, name='zhangsan', age=18}, Person{id=3, name='wangwu', age=20}]
[Person{id=1, name='lisi', age=19}, Person{id=2, name='zhangsan', age=18}, Person{id=3, name='wangwu', age=20}]
[Person{id=3, name='wangwu', age=20}, Person{id=2, name='zhangsan', age=18}, Person{id=1, name='lisi', age=19}]
1.8 并行(parallel)程序
parallelStream 是流并行处理程序的代替方法。以下实例我们使用parallelStream 来输出空字符串的数量:
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
Long count=items.parallelStream().filter(x->x.isEmpty()).count();
System.out.println(count);
1.9 Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors可用于返回列表或字符串:
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
List list=items.stream().filter(x->!x.isEmpty()).collect(Collectors.toList());
String s=items.stream().filter(x->!x.isEmpty()).collect(Collectors.joining(";"));
System.out.println(list);
System.out.println(s);
输出:
[1, 2, 3, 4, 5]
1;2;3;4;5
1.10 统计
另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
List<String> items = Arrays.asList("1", "2", "3", "4", "5");
IntSummaryStatistics iss =items.stream().mapToInt(x->Integer.parseInt(x)).summaryStatistics();
System.out.println(iss.getMax());
System.out.println(iss.getMin());
System.out.println(iss.getAverage());
System.out.println(iss.getSum());
输出:
5
1
3.0
15