Java基础系列文章
Java基础(一):语言概述 | Java基础(二):原码、反码、补码及进制之间的运算 | Java基础(三):数据类型与进制 | Java基础(四):逻辑运算符和位运算符 |
---|---|---|---|
Java基础(五):流程控制语句 | Java基础(六):数组 | Java基础(七):面向对象编程 | Java基础(八):封装、继承、多态性 |
Java基础(九):Object 类的使用 | Java基础(十):关键字static、代码块、关键字final | Java基础(十一):抽象类、接口、内部类 | Java基础(十二):枚举类 |
Java基础(十三):注解(Annotation) | Java基础(十四):包装类 | Java基础(十五):异常处理 | Java基础(十六):String的常用API |
Java基础(十七):日期时间API | Java基础(十八):java比较器、系统相关类、数学相关类 | Java基础(十九):集合框架 | Java基础(二十):泛型 |
Java基础(二十一):集合源码 | Java基础(二十二):File类与IO流 | Java基础(二十三):反射机制 | Java基础(二十四):网络编程 |
Java基础(二十五):Lambda表达式、方法引用、构造器引用 | Java基础(二十六):Stream流及Optional类 | 关于字符集(彻底搞清楚一个中文占几个字节?) |
操作数据源
(集合、数组等)所生成的元素序列不会存储
元素不会改变源
对象。相反,他们会返回一个持有结果的新Stream延迟
执行的 中间操作
或终止操作
了操作链
,可对数据源的数据进行n次处理@Test
public void test01(){
List<String> list = Arrays.asList("a", "b", "c", "d");
//创建顺序流(顺序执行)
Stream<String> stream = list.stream();
//创建并行流(多线程并行执行,速度快)
Stream<String> parallelStream = list.parallelStream();
}
@Test
public void test02(){
String[] arr = {"hello","world"};
Stream<String> stream = Arrays.stream(arr);
}
@Test
public void test03(){
int[] arr = {1,2,3,4,5};
IntStream stream = Arrays.stream(arr);
}
@Test
public void test04(){
Stream<Integer> stream = Stream.of(1,2,3,4,5);
stream.forEach(System.out::println);
}
@Test
public void test05() {
// 迭代累加,获取前五个
Stream<Integer> stream = Stream.iterate(1, x -> x + 2);
stream.limit(5).forEach(System.out::println);
System.out.println("**********************************");
// 一直生成随机数,获取前五个
Stream<Double> stream1 = Stream.generate(Math::random);
stream1.limit(5).forEach(System.out::println);
}
输出结果:
1
3
5
7
9
**********************************
0.1356905695577818
0.33576714141304886
0.7325647295361851
0.29218866245097375
0.24849848127040652
多个
中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行
任何的处理准备测试数据
// @Data 注在类上,提供类的get、set、equals、hashCode、toString等方法
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
// id
private int id;
// 名称
private String name;
// 年龄
private int age;
// 工资
private double 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;
}
}
// 获取员工集合数据
List<Employee> employeeList = EmployeeData.getEmployees();
Stream<Employee> stream = employeeList.stream();
stream.filter(emp -> emp.getSalary() > 7000).forEach(System.out::println);
employeeList.stream().limit(10).forEach(System.out::println);
employeeList.stream().skip(5).forEach(System.out::println);
List<Employee> employeeList = employeeList.stream()
.skip((long) (current - 1) * size).limit(size)
.collect(Collectors.toList());
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);
//方式1:Lambda表达式
employeeList.stream().map(emp -> emp.getName())
.filter(name -> name.length() > 3).forEach(System.out::println);
//方式2:方法引用第三种 类 :: 实例方法名
employeeList.stream().map(Employee::getName)
.filter(name -> name.length() > 3).forEach(System.out::println);
List<List<Integer>> nestedList = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6),
Arrays.asList(7, 8, 9)
);
nestedList.stream()
.flatMap(item -> item.stream())
.forEach(System.out::println);
// 获取名字长度的总和
List<String> list1 = Arrays.asList("Apple", "Banana", "Orange", "Grapes");
IntStream intstream = list1.stream().mapToInt(String::length);
int sum = intstream.sum();
//sorted() 自然排序-升序
Integer[] arr = new Integer[]{345,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);
//因为Employee没有实现Comparable接口,所以报错!
employeeList.stream().sorted().forEach(System.out::println);
// 根据工资自然排序(从小到大)
employeeList.stream().sorted(Comparator.comparing(Employee::getSalary))
.forEach(System.out::println);
// 根据工资倒序(从大到小)
employeeList.stream().sorted(Comparator.comparing(Employee::getSalary).reversed())
.forEach(System.out::println);
employeeList.stream()
.map(Employee::getName)
.peek(System.out::println)
.filter(name -> name.length() > 3)
.forEach(System.out::println);
boolean allMatch = employeeList.stream().allMatch(emp -> emp.getAge() > 18);
boolean anyMatch = employeeList.stream().anyMatch(emp -> emp.getAge() > 18);
boolean noneMatch = employeeList.stream().noneMatch(emp -> emp.getAge() > 18);
Optional<Employee> first = employeeList.stream().findFirst();
Employee employee = first.get();
Optional<Employee> any = employeeList.stream().findAny();
Employee employee = any.get();
ps:集合中数据为空,会抛异常No value present,后面会将Optional类的空值处理
Optional<Employee> max = employeeList.stream().max(Comparator.comparingDouble(Employee::getSalary));
Employee employee = max.get();
Optional<Employee> min = employeeList.stream().min(Comparator.comparingDouble(Employee::getSalary));
Employee employee = min.get();
long count = employeeList.stream().filter(emp -> emp.getSalary() > 7000).count();
// 计算1-10的自然数的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> reduce6 = list.stream().reduce(Integer::sum);
Integer sum = reduce6.get();
// 计算公司所有员工工资的总和
Optional<Double> reduce7 = employeeList.stream().map(Employee::getSalary).reduce(Double::sum);
Double aDouble = reduce7.get();
推荐使用
// 计算1-10的自然数的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer reduce1 = list.stream().reduce(0, (x1, x2) -> x1 + x2);
Integer reduce2 = list.stream().reduce(0, (x1, x2) -> Integer.sum(x1, x2));
Integer reduce3 = list.stream().reduce(0, Integer::sum);
// 计算1-10的自然数的乘积
Integer reduce4 = list.stream().reduce(1, (x1, x2) -> x1 * x2);
// 计算公司所有员工工资的总和
Double reduce5 = employeeList.stream().map(Employee::getSalary).reduce(0.0, Double::sum);
Collector
接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、Map)Collectors
实用类提供了很多静态方法,可以方便地创建常见收集器实例,如下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重复,会抛异常java.lang.IllegalStateException: Duplicate key xxx
// key-名称 value-员工对象
Map<String, Employee> employeeNameMap = employeeList.stream()
.collect(Collectors.toMap(Employee::getName, Function.identity()));
// key-名称 value-工资
Map<String, Double> nameSalaryMap = employeeList.stream()
.collect(Collectors.toMap(Employee::getName, Employee::getSalary));
key重复
后如何操作value的内容// key-名称 value-员工对象
Map<String, Employee> employeeNameMap = employeeList.stream()
.collect(Collectors.toMap(Employee::getName, Function.identity(),(oldValue,newValue) -> oldValue));
// key-名称 value-工资
Map<String, Double> nameSalaryMap = employeeList.stream()
.collect(Collectors.toMap(Employee::getName, Employee::getSalary,(oldValue,newValue) -> oldValue + newValue));
Long count = employeeList.stream().collect(Collectors.counting());
// 相当于
Long count2 = employeeList.stream().count();
Double aDouble = employeeList.stream().collect(Collectors.averagingInt(Employee::getAge));
Double bDouble = employeeList.stream().collect(Collectors.averagingDouble(Employee::getSalary));
Integer count = employeeList.stream().collect(Collectors.summingInt(Employee::getAge));
Double total = employeeList.stream().collect(Collectors.summingDouble(Employee::getSalary));
// 最大值
Optional<Employee> employee = employeeList.stream()
.collect(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)));
// 最小值
Optional<Employee> employee = employeeList.stream()
.collect(Collectors.minBy(Comparator.comparingDouble(Employee::getSalary)));
IntSummaryStatistics summaryStatistics = employeeList.stream().collect(Collectors.summarizingInt(Employee::getAge));
System.out.println(summaryStatistics);// IntSummaryStatistics{count=8, sum=263, min=2, average=32.875000, max=65}
Map<Boolean, List<Employee>> listMap = employeeList.stream()
.collect(Collectors.partitioningBy(emp -> emp.getSalary() > 6000));
Map<Integer, List<Employee>> collect = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getAge));
List<String> strings = Arrays.asList("apple", "banana", "apple", "cherry", "banana", "date", "apple");
Map<String, Long> stringCountMap = strings.stream()
.collect(Collectors.groupingBy(t -> t, Collectors.counting()));
Map<Integer, Long> collect = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getAge, Collectors.counting()));
Map<Integer, Double> collect = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getAge, Collectors.summingDouble(Employee::getSalary)));
Map<Integer, List<Double>> integerListMap = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getAge,
Collectors.mapping(Employee::getSalary, Collectors.toList())));
Map<Integer, Map<Double, List<Employee>>> collect = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getAge, Collectors.groupingBy(Employee::getSalary)));
List<String> list = Arrays.asList("A", "B", "C");
String string = list.stream().collect(Collectors.joining("-"));
// 结果:A-B-C
实现过程如下所示:
执行顺序
@Test
public void test1() {
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
list.add(i);
}
System.out.println("*****************************************");
List<Integer> collect = list.stream().map(item -> {
System.out.println("串行数据:" + item + ",线程名称:" + Thread.currentThread().getName());
return item * 2;
}).collect(Collectors.toList());
System.out.println("*****************************************");
List<Integer> collect1 = list.parallelStream().map(item -> {
System.out.println("并行数据:" + item + ",线程名称:" + Thread.currentThread().getName());
return item * 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
forEachOrdered保证执行顺序
@Test
public void test2() {
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 5; i++) {
list.add(i);
}
System.out.println("*****************************************");
list.stream().map(item -> {
return item + "|";
}).forEach(o -> {
System.out.println("forEach循环数据:" + o + ",线程名称:" + Thread.currentThread().getName());
});
System.out.println("*****************************************");
list.parallelStream().map(item -> {
return item + "|";
}).forEachOrdered(o -> {
System.out.println("forEachOrdered循环数据:" + o + ",线程名称:" + Thread.currentThread().getName());
});
}
输出结果:并行流forEachOrdered可以保证执行顺序
*****************************************
forEach循环数据:0|,线程名称:main
forEach循环数据:1|,线程名称:main
forEach循环数据:2|,线程名称:main
forEach循环数据:3|,线程名称:main
forEach循环数据:4|,线程名称:main
*****************************************
forEachOrdered循环数据:0|,线程名称:ForkJoinPool.commonPool-worker-3
forEachOrdered循环数据:1|,线程名称:ForkJoinPool.commonPool-worker-1
forEachOrdered循环数据:2|,线程名称:ForkJoinPool.commonPool-worker-1
forEachOrdered循环数据:3|,线程名称:ForkJoinPool.commonPool-worker-1
forEachOrdered循环数据:4|,线程名称:ForkJoinPool.commonPool-worker-1
执行效率
@Test
public void test3() {
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 1000000; i++) {
list.add(i);
}
long l1 = System.currentTimeMillis();
List<Integer> collect = list.stream().map(item -> {
return item * 2;
}).collect(Collectors.toList());
System.out.println("串行流耗时:" + (System.currentTimeMillis() - l1) + "ms");
long l2 = System.currentTimeMillis();
List<Integer> collect1 = list.parallelStream().map(item -> {
return item * 2;
}).collect(Collectors.toList());
System.out.println("并行流流耗时:" + (System.currentTimeMillis() - l2) + "ms");
}
输出结果:并行流明显高于串行
串行流耗时:17ms
并行流流耗时:81ms
Optional类内部结构(value为实际存储的值)
public final class Optional<T> {
// 空Optional对象,value为null
private static final Optional<?> EMPTY = new Optional<>();
// 实际存储的内容
private final T value;
// 私有的构造
private Optional() {
this.value = null;
}
...
}
@Test
public void optionalTest(){
Integer value1 = null;
Integer value2 = 10;
// 允许传递为null参数
Optional<Integer> a = Optional.ofNullable(value1);
// 如果传递的参数是null,抛出异常NullPointerException
Optional<Integer> b = Optional.of(value2);
// 空对象,value为null
Optional<Object> c = Optional.empty();
}
@Test
public void optionalTest() {
Integer value1 = null;
Optional<Integer> a = Optional.ofNullable(value1);
System.out.println("value值是否为null:" + a.isPresent());
System.out.println("获取value值,空报错空指针:" + a.get());
System.out.println("获取value值,空返回默认值0:" + a.orElse(0));
System.out.println("获取value值,空返回Supplier返回值:" + a.orElseGet(() -> 100));
System.out.println("获取value值,空抛出异常:" + a.orElseThrow(() -> new RuntimeException("value为空")));
}
@Test
public void optionalTest() {
Integer value1 = 10;
Optional<Integer> a = Optional.ofNullable(value1);
// 空不处理,非空则根据Consumer消费接口处理
a.ifPresent(o -> System.out.println("ifPresent value值:" + o)); // 10
// 空不处理,filter过滤
a.filter(o -> o > 1).ifPresent(o -> System.out.println("filter value值:" + o)); // 10
// 空不处理,map映射
a.map(o -> o + 10).ifPresent(o -> System.out.println("map value值:" + o)); // 20
// 空不处理,flatMap映射
a.flatMap(o -> Optional.of(o + 20)).ifPresent(o -> System.out.println("flatMap value值:" + o)); // 30
}