学习笔记-Java8新特性-第四节-StreamAPI
StreamAPI
-
利用StreamAPI可以像流水线一样操作处理数据源(数组、集合……)
-
Stream自己不会存储元素
-
Stream不会改变数据源,而是会返回一个持有处理结构的新Stream
-
Steam操作时延迟执行的,他们会等到需要结果的时候才执行
- 称为惰性求值
Stream操作的三个步骤
-
创建Stream
- 一个数据源(如:集合、数组),获取一个流
-
中间操作
- 一个中间操作链,对数据源的数据进行处理
-
终止操作
- 一个终止操作,执行中间操作链,并产生结果
创建Stream
-
通过Collection系列集合提供的stream()或paralleStream()
- List
list = new ArrayList<>();
Streamstream = list.stream();
- List
-
通过Arrays中的静态方法stream()获取数组流
- Employee[] employees = new Employee[10];
Streamstream1 = Arrays.stream(employees);
- Employee[] employees = new Employee[10];
-
通过Stream类中的静态方法of()
- Stream
stream2 = Stream.of("aa", "bb", "cc");
- Stream
-
创建无限流
中间操作
筛选与切片
-
filter——接收断言型Lambda,从流中排除某些元素
- public void test1() {
//过滤,保留年龄大于35的员工
employees.stream()
.filter((e) -> {
System.out.println("StreamAPI的中间操作");
return e.getAge() > 35;
})
.forEach(System.out::println);
}
- public void test1() {
-
limit——截断流,使其元素不超过给定数量
- public void test2() {
//截取,保留2个
employees.stream()
.limit(2)
.forEach(System.out::println);
}
- public void test2() {
-
skip——跳过,扔掉前n个元素
- public void test3() {
//跳过,扔掉前2个
employees.stream()
.skip(2)
.forEach(System.out::println);
}
- public void test3() {
-
distinct——去重,通过hashCode()和equals()判断是否相等
- @Test
public void test4() {
//去重
employees.stream()
.distinct()
.forEach(System.out::println);
}
- @Test
映射
-
map——接受一个Lambda,将元素转换成其他形式或提取信息
-
接收一个函数作为参数,该函数会被应用到每个元素上,并映射成一个新的元素
-
public void test5() {
Listlist = Arrays.asList("aa", "bb", "ccc", "ddd", "eee"); list.stream()
.map((s) -> s.toUpperCase())
.forEach(System.out::println);System.out.println("_________________");
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);}
-
-
flatMap
-
接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流
-
public void test6() {
Listlist = new ArrayList<>();
list.add("aaa");
list.add("bbb");list.stream()
//返回值为Stream<Stream>
.map(TestStreamAPI2::filterCharacter)
.forEach((characterStream) -> {
characterStream.forEach(System.out::println);
});System.out.println("------------------------");
list.stream()
//返回值为Stream
.flatMap(TestStreamAPI2::filterCharacter)
.forEach(System.out::println);
}public static Stream
filterCharacter(String str) {
Listlist = new ArrayList<>(); for(Character ch : str.toCharArray()) {
list.add(ch);
}return list.stream();
}
-
排序
-
sorted()——自然排序(Comparable)
-
sorted(Comparator cmp)——定制排序
-
public void test7() {
Listlist = Arrays.asList("bbb", "aaa", "ddd", "eee", "ccc"); list.stream()
.sorted()
.forEach(System.out::println);System.out.println("---------------------");
employees.stream()
.sorted((e1, e2) -> {
if(e1.getAge() == e2.getAge()) {
return e1.getName().compareTo(e2.getName());
} else {
return Integer.compare(e1.getAge(), e2.getAge());
}
})
.forEach(System.out::println);}
终止操作
查找与匹配
-
allMatch——检查是否匹配所有元素
-
anyMatch——检查是狗至少匹配一个元素
-
noneMatch——检查是否没有匹配所有元素
-
findFirst——返回第一个元素
-
findAny——返回当前流中的任意元素
-
List
employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Status.FREE),
new Employee("李四", 38, 5555.55, Employee.Status.BUSY),
new Employee("王五", 50, 6666.66, Employee.Status.VOCATION),
new Employee("赵六", 16, 3333.33, Employee.Status.FREE),
new Employee("田七", 8, 7777.77, Employee.Status.BUSY)
);@Test
public void test1() {
boolean b1 = employees.stream()
.allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);boolean b2 = employees.stream()
.anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b2);boolean b3 = employees.stream()
.noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b3);Optional
first = employees.stream()
.sorted(Comparator.comparingDouble(Employee::getSalary))
.findFirst();
System.out.println(first);Optional
any = employees.parallelStream()
.filter((e) -> e.getStatus().equals(Employee.Status.BUSY))
.findAny();
System.out.println(any);}
-
-
count——返回流中元素的总个数
-
max——返回流中的最大值
-
min——返回流中的最小值
-
public void test2() {
long count = employees.stream()
.count();
System.out.println(count);Optional
max = employees.stream()
.max(Comparator.comparingDouble(Employee::getSalary));
System.out.println(max);Optional
min = employees.stream()
.map(Employee::getSalary)
.min(Double::compare);
System.out.println(min);
}
-
规约
-
reduce(T identity, BinaryOperator) / reduce(BinaryOperator)
-
将流中的元素反复结合起来,得到一个值
-
identity代表一个初始值
-
public void test3() {
Listlist = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Integer sum = list.stream()
.reduce(0, Integer::sum);
System.out.println(sum);System.out.println("-------------------");
Optional
op = employees.stream()
.map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(op.get());
}
-
收集
-
collect——将流转换为其他形式
-
接收一个Collector接口的实现
- 使用对应的静态类Collectors提供的静态方法,可以方便地创建Collector实例
-
用于给Stream中元素做汇总的方法
-
public void test4() {
Listlist = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list.forEach(System.out::println);System.out.println("------------------");
Set
set = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
set.forEach(System.out::println);System.out.println("------------------");
HashSet<Employee.Status> hashSet = employees.stream()
.map(Employee::getStatus)
.collect(Collectors.toCollection(HashSet::new));
hashSet.forEach(System.out::println);}
-
public void test5() {
Double avg = employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(avg);System.out.println("_________________________");
Double sum = employees.stream()
.collect(Collectors.summingDouble(Employee::getSalary));}
-
@Test
public void test6() {
// 分组
Map<Employee.Status, List> collect = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(collect);// 多级分组
Map<Employee.Status, Map<String, List>> collect1 = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if (e.getAge() <= 35) {
return "青年";
} else if (e.getAge() <= 50) {
return "中年";
} else {
return "老年";
}
})));
System.out.println(collect1);}
-
public void test7() {
// 分区
Map<Boolean, List> collect = employees.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() > 5000));
System.out.println(collect);
} -
public void test8() {
// 统计
DoubleSummaryStatistics statistics = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));System.out.println(statistics.getSum());
System.out.println(statistics.getAverage());
System.out.println(statistics.getMax());
} -
public void test9() {
// 字符串处理
String collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(",", "=", "="));
System.out.println(collect);
// =张三,李四,王五,赵六,田七=
}
-
并行流与顺序流
-
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流
-
底层使用到了Fork/Join框架
-
使用了工作窃取模式
-
将小任务分成了数个线程队列
-
当某个线程队列处理完成后,会从其他没有完成的线程队列末尾偷取任务
-
-

-
可以使用parallel方法将流切换到并行模式
-
提高工作效率

浙公网安备 33010602011771号