Java8 Stream
什么是Stream?
Stream是java8的新特性,它允许你以声明式处理数据集合,可以把它作是遍历数据集的高级迭代器。此外与stream与lambda表达式结合后编码效率大大提高。
要澄清的是 java8 中的 stream 与 InputStream 和 OutputStream 是完全
不同的概念.
案例:
class Apple {
private int num;
private String name;
private String color;
public Apple(int num, String name, String color) {
this.num = num;
this.name = name;
this.color = color;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Apple{" +
"num=" + num +
", name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
public static void main(String[] args) {
List<Apple> appleList = new ArrayList<>();
appleList.add(new Apple(1, "草莓0", "黑色"));
appleList.add(new Apple(444, "草莓1", "红色"));
appleList.add(new Apple(3, "草莓4", "白色"));
appleList.add(new Apple(45, "草莓50", "红色"));
//我们的需求是在appleList集合中找出红色苹果手机
//使用Stream流快速实现操作
List<Apple> apples = appleList
//先转换成流
.stream()
//过滤器
.filter(c->c.getColor().equals("红色"))
//转成集合
.collect(Collectors.toList());
System.out.println(apples);
}
结果:
[Apple{num=444, name='草莓1', color='红色'}, Apple{num=45, name='草莓50', color='红色'}]
什么是流呢?
简单地定义,就是“从支持数据处理操作的源,生成的元素序列”。
元素列表:和集合一样,流也提供了一个接口,访问特定元素类型的一组有序值。
数据源:获取数据的源,比如集合。
数据处理操作:流更偏向于数据处理和计算,比如filter、map、find、sort等。
简单来说,我们通过一个集合的stream方法获取一个流,然后对流进行一系列流操作,最后再构建成我们需要的数据集合。
简单来说,就是:
数据源—>中间操作—>终端操作—>结果
获取流
使用 Collection 接口下的 stream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
使用 Arrays 中的 stream() 方法,将数组转成流
Integer[] nums = new Integer[10];
Stream<Integer> stream = Arrays.stream(nums);
使用 Stream 中的静态方法:of()
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
使用 BufferedReader.lines() 方法,将每行内容转成流
BufferedReader reader=new BufferedReader(new FileReader("stream.txt"));
Stream<String> lineStream = reader.lines();
流操作
流操作可以分为两类:中间操作和终端操作。回看之前的代码:
List<Apple> apples = applestore
.stream() 获得流
.filter(a -> a.getColor().equals("red")) 中间操作
.collect(Collectors.toList()); 终端操作
简化一下就是:
数据源 => 中间操作 => 终端操作 => 结果
诸如 filter 或者 sort 等中间操作会返回另一个流,进而进行下一步流操作,而终 端操作则是将流关闭,构建新的数据集合对象(也可以不构建)。
中间操作
filter:过滤流中的某些元素,
sorted(): 自然排序,流中元素需实现 Comparable 接口
distinct: 去除重复元素
limit(n): 获取 n 个元素
skip(n): 跳过 n 元素,配合 limit(n)可实现分页
map(): 将其映射成一个新的元素
终端操作
forEach: 遍历流中的元素
toArray:将流中的元素倒入一个数组
Min:返回流中元素最小值
Max:返回流中元素最大值
count:返回流中元素的总个数
Reduce:所有元素求和
anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足条件则返 回 true,否则返回 false
allMatch:接收一个 Predicate 函数,当流中每个元素都符合条件时才返 回 true,否则返回 false
findFirst:返回流中第一个元素
collect:将流中的元素倒入一个集合,Collection 或 Map
/*
Stream java8之后提供数据集合进行遍历操作的高级迭代器
集合/数组——》元素序列(Stream)——》中间操作(过滤、去重,排序。。。)——》终端操作
流的使用:1、获取流: 数组集合可以转换成流
2、中间操作
3、终端操作
*/
public static void main(String[] args) {
/*
Integer sum = Stream.of(1,2,3,4,5,5).reduce((o1, o2)->{return o1+o2;}).get();
System.out.println(sum);
*/
//遍历
Stream.of(5,2,7,4,5,5)
.filter(e->{return e>2;}) //把数据大于2的元素留下来
.sorted(((o1, o2) -> o2.compareTo(o1))) //逆序排序
.distinct() //去重
.forEach(System.out::println);
System.out.println("---------------max最大值分割线------------------");
System.out.println("max=" + Stream.of(10, 3, 4, 5, 1, 8, 9)
.max(((o1, o2) -> {
return o1.compareTo(o2); //比较大小
}))
.get()
);
System.out.println("---------------reduce求和分割线------------------");
Integer sum = Stream.of(10, 3, 4, 5, 1, 8, 9)
.reduce((o1, o2) -> {
return o1 + o2; //q求和
})
.get();
System.out.println("和为:" + sum);
System.out.println("---------------anyMatch分割线------------------");
Boolean b = Stream.of(10, 3, 4, 5, 1, 8, 9)
.anyMatch((e) -> { // anyMath
return e > 4; //只要有一个大于4就返回true,否则返回false
});
System.out.println(b);
System.out.println("---------------allMatch分割线------------------");
Boolean b1 = Stream.of(10, 3, 4, 5, 1, 8, 9)
.allMatch((e) -> { // allMatch
return e > 3; //只要有一个不是小于等于3就返回false,否则返回true
});
System.out.println(b1);
}
运行结果:
中间操作map 以及终端操作collect:
/*
stream java8 之后对集合(集合,数组)进行遍历操作的高级迭代器(重点在于对数据操作)
集合/数组 --> 元素序列(stream) --> 中间操作(过滤,排序,去重...) --> 终端操作(最终的结果)
流的使用:
1.获取流 集合,数组 都可以转为流
2.中间操作
3.终端操作
*/
public static void main(String[] args) {
List<Apple> applestore = new ArrayList();
applestore.add(new Apple(1, "red", 500, "河南"));
applestore.add(new Apple(2, "red", 400, "陕西"));
applestore.add(new Apple(3, "green", 300, "上海"));
applestore.add(new Apple(5, "green", 200, "湖北"));
applestore.add(new Apple(4, "green", 100, "湖南"));
/*
map(方法) 将某一个值 映射到stream中去
*/
applestore.stream()
.map(Apple::getId) //只把id映射到map中去
.forEach(System.out::println);
List list = applestore.stream()
.sorted(((o1, o2) -> {
return o1.getId() - o2.getId();
}))
.collect(Collectors.toList());
System.out.println(list);
//前提得重写equal方法,hashcode方法
Set set = applestore.stream()
.sorted(((o1, o2) -> {
return o1.getId() - o2.getId();
}))
.collect(Collectors.toSet());
System.out.println(set);
Map<Integer, String> map = applestore.stream()
.sorted(((o1, o2) -> {
return o1.getId() - o2.getId();
}))
.collect(Collectors.toMap(Apple::getId, Apple::getAddress));
System.out.println(map);
}