Stream的学习
流的本质
是数据渠道,用于操作数据源(集合,数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”
注意
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream.
③Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream操作的三个步骤
步骤
创建Stream --一个数据源,获取一个流
中间操作–对数据源的数据进行操作
终止操作–产生结果
创建Stream
// 1.可以通过Collection 系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
// 2.通过Arrays 中的静态方法stream() 获取数组流
Employee[] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);
// 3.通过Stream 类中的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "ddd");
// 4.创建无线流
//迭代
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 20);
中间操作
中间操作:多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理! 而在终止操作时一次性全部处理,称为“惰性求值”。
中间操作的种类
筛选与切片
filter:接收Lambda ,从流中排除某些元素。
limit:截断流, 使其元素不超过给定的数量。
skip(n): 跳过元素,返回一个扔掉了前N个元素的流。若流中的元素不足N个,则返回一个空流。与limit(N)互补。
distinct:筛选,通过流所生成元素的hashcode()和equals()去重复元素
// 中间操作不会执行任何操作
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",38,4555.66),
new Employee("王五",50,6666.66),
new Employee("赵六",16,7777.77),
new Employee("田七",8,8888.88)
);
@Test
public void test1(){
// 中间操作不会执行任何操作
Stream<Employee> employeeStream = employees.stream()
.filter((e) -> {
System.out.println("Stream API 的中间操作 ");
return e.getAge() > 35;
});
// 触发终止操作 所有操作全部执行
employeeStream.forEach(System.out::println);
}
@Test
public void test2(){
employees.stream()
.filter((e) -> e.getSalary() > 5000)
.limit(2)
.forEach(System.out::println);
}
映射
map:接收Lambda ,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap:接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连成一个流。
@Test
public void test4(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
list.stream()
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
System.out.println("----------------------");
// 提取名字
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
System.out.println("----------------------");
//map 的使用 相当于集合中 add
Stream<Stream<Character>> stream1 = list.stream()
.map(StreamTest2::filterCharacter);//{{a,a,a},{b,b,b}}
stream1.forEach((sm) ->
sm.forEach(System.out::println));
System.out.println("----------------------");
//flatMap 的使用 相当于集合中的addALL
Stream<Character> stream2 = list.stream()
.flatMap(StreamTest2::filterCharacter);//{a,a,a,b,b,b}
stream2.forEach(System.out::println);
}
// 将字符串中字母拿出来放到集合中,返回该集合的流
public static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
排序
sorted() :自然排序(comparable)
sorted(comparator com ) :定制排序
// 自然排序
List<String> list = Arrays.asList("aaa","ccc", "ddd", "ppp", "bbb", "eee");
list.stream()
.sorted()
.forEach(System.out::println);
// 定制排序
employees.stream()
.sorted((e1, e2) -> {
if(e1.getAge().equals(e2.getAge())){
return e1.getName().compareTo(e2.getName());
}else{
return e1.getAge().compareTo(e2.getAge());
}
}).forEach(System.out::println);
终止操作
查找与匹配
* allMatch:检查是否匹配所有元素
* anyMatch:检查是否至少匹配一个元素
* noneMatch:检查是否没有匹配所有元素
* findFirst:返回第一个元素
* findAny:返回当前流中的任意元素
* count:返回流中元素的总个数
* max:返回流中最大值
* min:返回流中最小值
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99, Employee.Status.FREE),
new Employee("李四",38,4555.66, Employee.Status.BUSINESS),
new Employee("王五",50,6666.66, Employee.Status.FREE),
new Employee("赵六",16,7777.77, Employee.Status.BUSINESS),
new Employee("田七",8,8888.88, Employee.Status.VOCATION)
);
@Test
public void test(){
boolean b = employees.stream()
.allMatch((e) -> e.getStatus().equals(Employee.Status.BUSINESS));
System.out.println(b);//false
boolean b1 = employees.stream()
.anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSINESS));
System.out.println(b1);//true
boolean b2 = employees.stream()
.noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSINESS));
System.out.println(b2);//false
// Optional 容器类 减少控制针异常 相当于数据库中的IFNULL
Optional<Employee> op = employees.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
.findFirst();
// 获取工资最低的员工信息
System.out.println(op.get());
/**
* parallelStream():并行流,多个线程同时去找,谁先找到,返回谁
* stream():串行流,一个接一个去找
*/
Optional<Employee> op2 = employees.parallelStream()
.filter((e) -> e.getStatus().equals(Employee.Status.FREE))
.findAny();
System.out.println(op2.get());
//总数 员工工资大于5000的员工人数有?
long count = employees.stream()
.filter((e) -> e.getSalary() > 5000)
.count();
System.out.println(count);
//返回流中最大值 员工中最高工资是那位员工?
Optional<Employee> op3 = employees.stream()
.max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op3.get());
//返回流中最小值 员工中最低工资是?
Optional<Double> op4 = employees.stream()
.map(Employee::getSalary)
.min(Double::compare);
System.out.println(op4.get());
}