JAVA8之工具类Stream
一. 概述
在jdk1.8中引入的新的对集合中数据的处理的--Stream流.该工具类常常被我们用来对集合中数据的筛选,处理等等,使用流可以大大的减少我们的代码量,也是我们的代码逻辑性更强,更容易明白每一步是在做什么.
二. 特性
1. 流不会存储元素,遍历完一次就等于消费完了.
2. 流都是懒加载的,只有你用到结果的时候才会去执行.
3. 流只会操作数据,不会改变数据.
4. 它采用的是内部迭代,即它会根据环境等因素确定如果去操作数据,我们只需要告诉我我们的目的.
三. 操作过程
1. 创建操作(四种)
1.1 通过集合创建
先写一个用户类,重写了equals和hashCode方法.
package com.yczuoxin.demo.stream;
import java.util.Objects;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("zhangsan",18),
new User("lisi",19),
new User("wangwu",20),
new User("zhaoliu",21));
Stream<User> stream = list.stream();
Stream<User> userStream = list.parallelStream();
}
}
1.2 通过数组创建
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
Integer[] ints = new Integer[5];
Stream<Integer> integerStream = Arrays.stream(ints);
String[] strings = new String[5];
Stream<String> stringStream = Arrays.stream(strings);
}
}
1.3 通过值创建
package com.yczuoxin.demo.stream;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
Stream<String> stringStream = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu");
}
}
1.4 通过函数创建(该方法创建的是无限流,需要用limit来限制大小)
package com.yczuoxin.demo.stream;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
// 迭代
Stream<Integer> stream3 = Stream.iterate(2, (x) -> x * 2).limit(4);
stream3.forEach(System.out::println);
System.out.println("-------------");
// 生成
Stream<Double> stream4 = Stream.generate(Math::random).limit(4);
stream4.forEach(System.out::println);
}
}
1.5 通过文件创建
先创建一个文件
package com.yczuoxin.demo.stream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
try(Stream lines = Files.lines(Paths.get("E:\\code\\test\\demo\\src\\main\\java\\com\\yczuoxin\\demo\\stream\\test.properties"),Charset.defaultCharset())){
lines.forEach(System.out::println);
}catch(IOException e){
}
}
}
2. 中间操作
中间操作就是对流进行操作.
2.1 筛选
2.1.1 filter(Predicate p)方法
在流中筛选一些符合要求的元素.
2.1.2 distinct()方法
在流中利用hashCode的equals方法去除某些相同的元素.
2.1.3 limit(long maxSize)方法
在流中数据达到最大值时截断流.
2.1.4 skip(long n)方法
丢弃掉流中的前n个元素,如果流中数据没有达到n,则返回一个空流.
看下代码示例:
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.List;
public class StreamTest {
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("zhangsan",18),
new User("lisi",19),
new User("wangwu",20),
new User("wangwu",20),
new User("zhaoliu",21));
// 去重
list.stream().distinct()
// 筛选出年龄大于19的用户
.filter(user -> user.getAge() >= 19)
// 截取两个用户
.limit(2)
// 输出用户
.forEach(System.out::println);
}
}
2.2 映射
2.2.1 map(Function function)方法
接受一个函数入参,该函数会用在每个元素上,并将其结果映射成一个新的元素.
2.2.2 flatMap(Function function)方法
接受一个函数入参,该函数会用在每个元素上,并将流中每个元素换到另一个流中.然后将所有的流连在一起.
下面看示例代码
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
// 将所有的集合流映射到一个流里面
listStream.flatMap(list -> list.stream()).
// 对流里面的值都加10并输出
map(integer -> integer + 10).forEach(System.out::println);
}
}
将3个数组内的值全部都融合在一个数组输出.这就是flatMap的作用.
2.3 排序
2.3.1 sort()方法
按照自然规则排序
2.3.2 sort(Comparator comparator)方法
按照给定的规则排序
看下示例代码
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class StreamTest {
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("zhangsan",18),
new User("lisi",21),
new User("wangwu",19),
new User("zhaoliu",20));
list.stream().map(x -> x.getAge()).sorted().forEach(System.out::println);
list.stream().sorted(Comparator.comparing(x->x.getName())).forEach(System.out::println);
}
}
先使用自然排序对用户的年龄进行映射,然后对其排序输出.然后使用自己定义的排序规则对用户根据名字开的开头字母进行排序.
3. 终止操作
该操作和会使流进行操作然后获得结果.
3.1 匹配
3.1.1 count()方法
返回该流存在的元素个数,返回值类型为long类型.
3.1.2 findFirst()方法.
返回该流中第一个元素.如果没有不会报空指针,返回值为Optional类型,空时返回empty.
3.1.3 findAny()方法
返回流中任意一个元素.如果没有不会报空指针,返回值为Optional类型,空时返回empty.
3.1.4 allMatch(Predicate predicate)方法
返回流中所有的元素是否满足Predicate条件,返回值为布尔类型(boolean)
3.1.5 anyMatch(Predicate predicate)方法
返回流中的元素是否有满足Predicate条件,返回值为布尔类型(boolean)
3.1.6 noneMatch(Predicate predicate)方法
返回流中的元素是否都不满足Predicate条件,返回值为布尔类型(boolean)
3.1.7 max(Comparator comparator)方法
返回流中通过Comparator比较后的最大值,返回值为Optional类型.
3.1.8 min(Comparator comparator)方法
返回流中通过Comparator比较后的最小值,返回值为Optional类型.
3.1.9 forEach(Consumer consumer)方法
对流中所有的元素进行迭代操作(内部迭代).操作顺序是并行执行.一般情况下还是按顺序执行.
3.1.10 forEachOrdered(Consumer consumer)方法
对流中所有的元素进行迭代操作(内部迭代).操作顺序是按照流的顺序执行.效率没有前者高.
示例代码:
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class StreamTest {
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("zhangsan",18),
new User("lisi",21),
new User("wangwu",19),
new User("zhaoliu",20));
// 过滤出没有元素的流试探会不会报空指针异常
System.out.println(list.stream().map(x -> x.getAge()).sorted().filter(x -> x > 21).findAny());
// 判断是否全部用户年龄都大于19
System.out.println(list.stream().allMatch(user -> user.getAge() > 19));
// 判断是否至少有一位用户年龄都大于19
System.out.println(list.stream().anyMatch(user -> user.getAge() > 19));
// 判断是否全部用户年龄都不大于19
System.out.println(list.stream().noneMatch(user -> user.getAge() > 19));
// 求出用户年龄的最大值.
System.out.println(list.stream().max(Comparator.comparing(x->x.getAge())));
// 利用Comparator将用户年龄比较大小反写,利用最大值求出最小值
System.out.println(list.stream().max((x,y) -> y.getAge() - x.getAge()));
}
}
3.2 归约
3.2.1 reduce(T identity, BinaryOperator accumulator)
归约是将集合中的所有元素经过指定运算(加减乘除等),折叠成一个元素输出.返回一个T类型的值.第一个值为初始值.
3.2.2 reduce(BinaryOperator accumulator)
归约是将集合中的所有元素经过指定运算(加减乘除等),折叠成一个元素输出.返回一个Optional类型的值.
示例代码:
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.List;
public class StreamTest {
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("zhangsan",18),
new User("lisi",21),
new User("wangwu",19),
new User("zhaoliu",20));
System.out.println(list.stream().map(x -> x.getAge()).reduce(Integer::sum));
System.out.println(list.stream().map(x -> x.getAge()).reduce(0,Integer::sum));
}
}
上面是对于所有用户年龄的求和.
3.3 集合collect
将流转化成集合的形式.以下是示例代码:
package com.yczuoxin.demo.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamTest {
public static void main(String[] args) {
List<User> list = Arrays.asList(new User("zhangsan",18),
new User("lisi",21),
new User("wangwu",19),
new User("wangwu",19),
new User("zhaoliu",20));
list.stream().collect(Collectors.toSet()).forEach(System.out::println);
}
}
利用set集合来对list进行去重操作并将list转化成了set.如何具体使用可以去了解Collectors工具类.其对于流还有分组的功能,就如数据库操作的groupBy一样.