一、Stream介绍
1、什么是Stream
stream流是用来高效处理容器数据一种操作
2、Stream特点
- Stream不会改变源对象,每操作一次都会返回一个持有结果的新Stream
- Stream 操作是延迟执行的这意味着他们会等到需要结果的时候才执行即一旦执行终止操作,就执行中间操作链,并产生结果
- Stream一旦执行了终止操作,就不能再调用其它中间操作或终止操作了
3.Stream流的关键步骤
1.流的创建
一个数据源例如:数组、集合来创建一个流
1.1集合创建
//创建顺序流(顺序执行)
Stream<String> stream = list.stream();
//创建并行流(多线程并行执行,速度快)
Stream<String> parallelStream = list.parallelStream();
1.2数组创建
Stream<String> stream = Arrays.stream(arr);
1.3stream的of()静态方法
Stream<Integer> stream = Stream.of(1,2,3,4,5);
2.中间操作
准备数据员工类
package Stream;
import java.util.Objects;
public class Employee {
// id
private int id;
// 名称
private String name;
// 年龄
private int age;
// 工资
private double salary;
public Employee() {
}
public Employee(int id, String name, int age, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
/**
* 获取
* @return id
*/
public int getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(int id) {
this.id = id;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return salary
*/
public double getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Employee{id = " + id + ", name = " + name + ", age = " + age + ", salary = " + salary + "}";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;//如果两个对象的地址值相同,则表示一个对象
if (o == null || getClass() != o.getClass()) return false;//如果比较的对象为null或者两个对象的类不相同,则表示不是相同对象
Employee employee = (Employee) o;//将对象转换为同一类型
//比较里面的属性值是否相等
return id == employee.id && age == employee.age && Double.compare(employee.salary, salary) == 0 && name.equals(employee.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age, salary);
}
}
初始化数据
public class EmployeeData {
public static List<Employee> getEmployees(){
List<Employee> list = new ArrayList<>();
list.add(new Employee(1001, "马化腾", 34, 6000.38));
list.add(new Employee(1002, "马云", 2, 19876.12));
list.add(new Employee(1003, "刘强东", 33, 3000.82));
list.add(new Employee(1004, "雷军", 26, 7657.37));
list.add(new Employee(1005, "李彦宏", 65, 5555.32));
list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));
list.add(new Employee(1007, "任正非", 26, 4333.32));
list.add(new Employee(1008, "扎克伯格", 35, 2500.32));
return list;
}
}
2.1filter(筛选)
//1.筛选filter
//1.查询员工表薪资大于6000的员工信息
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().filter(m -> m.getSalary() >6000).toList().forEach(out::println);
2.2 limit(截断)
//limit截取前三个员工
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().limit(3).forEach(out::println);
2.3 skip(跳过)
//skip跳过前五个
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().skip(5).forEach(out::println);
2.7 distinct(去重)
List<Employee> employeeList = EmployeeData.getEmployees();
employeeList.add(new Employee(1009, "马云", 40, 12500.32));
employeeList.add(new Employee(1009, "马云", 40, 12500.32));
employeeList.add(new Employee(1009, "马云", 40, 12500.32));
employeeList.add(new Employee(1009, "马云", 40, 12500.32));
employeeList.stream().distinct().forEach(System.out::println);
2.8 map(映射)
//map映射
//获取员工姓名长度大于2的员工的姓名
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().map(Employee::getName).filter(n->n.length()>2).forEach(out::println);
2.9 sorted(排序)
//--------------------------Stream流操作
//sorted() 自然排序-升序
Integer[] arr = new Integer[]{31, 3, 64, 3, 46, 7, 3, 34, 65, 68};
String[] arr1 = new String[]{"GG", "DD", "MM", "SS", "JJ"};
Arrays.stream(arr).sorted().forEach(System.out::println);
Arrays.stream(arr1).sorted().forEach(System.out::println);
//sorted() 自然排序-降序
Arrays.stream(arr).sorted(Comparator.reverseOrder()).forEach(System.out::println);
Arrays.stream(arr1).sorted(Comparator.reverseOrder()).forEach(System.out::println);
//比较排序 类实现Comparable接口
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().sorted().forEach(out::println);
//借助比较器排序
employees.stream().sorted(Comparator.comparing(Employee::getAge)).forEach(out::println);
3.终止操作
collect(收集)
3.1 归集(toList/toSet/toMap)
//获取所有员工姓名
List<String> nameList1 = employeeList.stream().map(Employee::getName).collect(Collectors.toList());
// jdk16以后,collect(Collectors.toList())可以简写为.toList()
List<String> nameList2 = employeeList.stream().map(Employee::getName).toList();
//获取所有员工不重复的年龄
Set<Integer> ageList=employeeList.stream().map(Employee::getAge).collect(Collectors.toSet());
//
// key-名称 value-工资
Map<String, Double> nameSalaryMap = employeeList.stream()
.collect(Collectors.toMap(Employee::getName, Employee::getSalary));
3.2 统计(counting)元素个数
Long count = employeeList.stream().collect(Collectors.counting());
// 相当于
Long count2 = employeeList.stream().count();
3.3 分组(groupingBy)
//分组 key-年龄 value-对象
List<Employee> employees = EmployeeData.getEmployees();
Map<Integer, List<Employee>> collect = employees.stream().collect(Collectors.groupingBy(Employee::getAge));
out.println(collect);
3.4 接合(joining)
List<String> list = Arrays.asList("A", "B", "C");
String string = list.stream().collect(Collectors.joining("-"));
// 结果:A-B-C
二.并行流parallelStream
- fork根据cpu核数进行数据分块,join对各个fork进行合并
- 对于并行流,其在底层实现中,是沿用了Java7提供的forkljoin分解合并框架进行实现
1.串行与并行对比
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
list.add(i);
}
//--------------------------------------------------------------
List<Integer> collect = list.stream().map(i -> {
System.out.println("串行数据:" + i + ",线程名称:" + Thread.currentThread().getName());
return i * 2;
}).collect(Collectors.toList());
//---------------------------------------------------------------
List<Integer> collect1 = list.parallelStream().map(i -> {
System.out.println("并行数据:" + i + ",线程名称:" + Thread.currentThread().getName());
return i * 2;
}).collect(Collectors.toList());
//结果
串行数据:0,线程名称:main
串行数据:1,线程名称:main
串行数据:2,线程名称:main
串行数据:3,线程名称:main
串行数据:4,线程名称:main
并行数据:2,线程名称:main
并行数据:0,线程名称:ForkJoinPool.commonPool-worker-3
并行数据:3,线程名称:ForkJoinPool.commonPool-worker-3
并行数据:4,线程名称:ForkJoinPool.commonPool-worker-2
并行数据:1,线程名称:ForkJoinPool.commonPool-worker-1
2.执行效率
在单核CPU的情况下,Stream的串行选代的效率是要高于Stream的并行选代的效率的。
而在多核CPU的情况下,Stream的并行选代速度要比Stream的串行选代效率要高。但是,如果元素数量比较少的话,直接用常规迭代反而性能更好。
7万+

被折叠的 条评论
为什么被折叠?



