java8 Stream
概述
steam是java8的新特性,主要是对集合的处理。
一般一个完整的steam语法分为三个步骤
- 创建
- 处理
- 终止条件
//比如
List<Employee> collect = employees.stream().filter((x) -> x.age > 35).collect(Collectors.toList());
接下来用代码实现steam的三个步骤,最后面会把所有用到的代码整体粘贴出来
一、创建
stream流有五种创建方法
public static void createStream() {
// 1:collection系列
List<String> srrLIst = new ArrayList<>();
Stream<String> stream = srrLIst.stream();
// 2.Arrays
Integer[] ints = new Integer[10];
Stream<Integer> stream1 = Arrays.stream(ints);
// 3.Stream.of
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
// 4.无限流 Stream.iterate();
Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
// 5.Stream.generate();
Stream<Double> generate = Stream.generate(Math::random);
}
二、处理
流的处理有多种功能
- 筛选与切片
filter:过滤得到符合条件的数据
limit:拿到结果的前几条
skip:跳过结果的前几条
distinct:去重,注意,依靠hashcode,equals 方法去重
必须得提一句,stream的处理过程都是在终止操作时才执行的,而不是把每一个都元素都直接处理完成再执行终止语句。
public static void test() {
// filter
employees.stream().filter((x) -> x.age > 35).forEach(System.out::println);
System.out.println("----------------------------------");
// limit
employees.stream().filter((x) -> x.salary > 5000)
.limit(2)
.forEach(System.out::println);
System.out.println("----------------------------------");
// skip
employees.stream().filter((x) -> x.salary > 5000)
.skip(2)
.forEach(System.out::println);
System.out.println("----------------------------------");
// distinct
employees.stream().filter((x) -> x.salary > 5000)
.distinct()
.forEach(System.out::println);
}
- 映射
map: 接受一个函数作为参数,该函数会应用到没一个元素上,并将其映射成一个新的元素
flatMap: 将流中的每个值都转化为另一个流,并且将所有流连接成一个流。
public static void testMap() {
// map
String[] strArr = {"aaa", "bbb", "ccc", "ddd"};
Arrays.stream(strArr).map(String::toUpperCase).forEach(System.out::println);
System.out.println("--------------------------");
employees.stream().map(Employee::getName).forEach(System.out::println);
System.out.println("#########################");
// flatMap
// 如果只使用map,将上面strArr拆分成 {"a","a","a","b",.....}
Stream<Stream<Character>> rStream = Arrays.stream(strArr).map(StreamTest::filterCharacter);
rStream.forEach((st) -> st.forEach(System.out::println));
System.out.println("--------------------------");
//使用 flatMap
Arrays.stream(strArr).flatMap(StreamTest::filterCharacter).forEach(System.out::println);
}
public static Stream<Character> filterCharacter(String str) {
List<Character> list = new ArrayList<>();
for (char c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
- 排序
sorted() : 自然排序 (comparable)
sorted(Comparator com)
public static void sort() {
// sorted()
String[] strArr = {"ccc", "ddd", "aaa", "bbb"};
Arrays.stream(strArr).sorted().forEach(System.out::println);
System.out.println("-----------------------------------");
// sorted(Comparator com)
employees.stream().sorted((x, y) -> {
if (x.getAge().equals(y.getAge())) {
return x.getName().compareTo(y.getName());
} else {
return x.getAge().compareTo(y.getAge());
}
}).forEach(System.out::println);
}
三、终止条件
- 查找与匹配
allMatch : 检查是否匹配所有元素
anyMatch: 检查是否匹配一个元素
noneMatch: 检查是否没有匹配任何一个个元素
findFirst: 返回第一个元素
findAny: 返回任意一个元素
count: 计算总数
max: 返回最大值
min: 返回最小值
public static void find() {
// allMatch
boolean b = employees.stream().allMatch(x -> x.getStatus().equals(Employee.Status.BUSY));
System.out.println(b);
System.out.println("--------------------------------");
// findFirst
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first.get());
System.out.println("--------------------------------");
// count
long count = employees.stream().count();
System.out.println(count);
System.out.println("--------------------------------");
// max min
Optional<Employee> max = employees.stream().max((x, y) -> Double.compare(x.getAge(), y.getAge()));
System.out.println(max);
Optional<Integer> max1 = employees.stream().map(Employee::getAge).max(Double::compare);
System.out.println(max1.get());
}
- 规约与收集
规约:可以将流中的元素反复结合起来,得到一个值
public static void test1() {
// 规约
Integer[] intArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Integer reduce = Arrays.stream(intArr).reduce(0, (x, y) -> x + y);
System.out.println(reduce);
System.out.println("--------------------------------------");
Optional<Double> reduce1 = employees.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println(reduce1.get());
System.out.println("##############################");
// 收集
List<Employee> collect = employees.stream().collect(Collectors.toList());
Set<Employee> collect1 = employees.stream().collect(Collectors.toSet());
HashSet<String> collect2 = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
// 总数 : Collectors.counting()
// 平均值: Collectors.averagingDouble();
// 总和: Collectors.summingDouble();
// 其他获取总数,平均值的方法
DoubleSummaryStatistics collect7 = employees.stream().collect(Collectors.summarizingDouble(Employee::getAge));
double average = collect7.getAverage();
long count = collect7.getCount();
double max = collect7.getMax();
double min = collect7.getMin();
double sum = collect7.getSum();
// 最值
Optional<Employee> collect3 = employees.stream().collect(Collectors.maxBy((x, y) -> Double.compare(x.getSalary(), y.getSalary())));
// 分组
Map<Employee.Status, List<Employee>> collect4 = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
// 多级分组
Map<Employee.Status, Map<Integer, List<Employee>>> collect5 = employees.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(Employee::getAge)));
// 分区,满足条件的一个区,不满足条件的一个区
Map<Boolean, List<Employee>> collect6 = employees.stream().collect(Collectors.partitioningBy(e -> e.getAge() > 35));
// join
String collect8 = employees.stream().map(Employee::getName).collect(Collectors.joining()); // 将每个employee中的name相连
String collect9 = employees.stream().map(Employee::getName).collect(Collectors.joining(",")); // 将每个employee中的name相连,用‘,’隔开
String collect10 = employees.stream().map(Employee::getName).collect(Collectors.joining(",", "++", "++"));// 将每个employee中的name相连,用‘,’隔开,前后加上++
}
四、并行流
并行流
.parallel() :利用fork/join框架并行执行,并行执行,提高效率。
public static void test2(){
Instant start = Instant.now();
LongStream.rangeClosed(0, 99999999999L)
.parallel()
.reduce(0, Long::sum);
Instant end = Instant.now();
System.out.println(Duration.between(start,end).toMillis());
System.out.println("--------------------------");
employees.stream()
.parallel()
.filter((x) -> x.age > 35).forEach(System.out::println);
}
本次测试一共使用两个类,都粘贴在下面
- StreamTest
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
* Stream 的三个步骤
* <p>
* 1:创建
* <p>
* 2:处理
* <p>
* 3:终止操作
*/
public class StreamTest {
static List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Status.FREE),
new Employee("李四", 58, 5555.55, Employee.Status.VOCATION),
new Employee("王五", 26, 3333.33, Employee.Status.FREE),
new Employee("赵六", 36, 6666.66, Employee.Status.FREE),
new Employee("田七", 12, 8888.88, Employee.Status.BUSY),
new Employee("田七", 12, 8888.88, Employee.Status.FREE),
new Employee("田七", 12, 8888.88, Employee.Status.FREE)
);
public static void main(String[] args) {
// 创建测试
// createStream();
// 筛选与切片测试
// test();
// 映射
// testMap();
// 排序
// sort();
// 查找与匹配
// find();
// 规约与收集
// test1();
// 并行测试
test2();
}
public static void createStream() {
// 1:collection系列
List<String> srrLIst = new ArrayList<>();
Stream<String> stream = srrLIst.stream();
// 2.Arrays
Integer[] ints = new Integer[10];
Stream<Integer> stream1 = Arrays.stream(ints);
// 3.Stream.of
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
// 4.无限流 Stream.iterate();
Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
// 5.Stream.generate();
Stream<Double> generate = Stream.generate(Math::random);
}
/**
* 1:筛选与切片
* filter:过滤得到符合条件的数据
* limit:拿到结果的前几条
* skip:跳过结果的前几条
* distinct:去重,注意,依靠hashcode,equals 方法去重
*/
public static void test() {
// filter
employees.stream().filter((x) -> x.age > 35).forEach(System.out::println);
System.out.println("----------------------------------");
// limit
employees.stream().filter((x) -> x.salary > 5000)
.limit(2)
.forEach(System.out::println);
System.out.println("----------------------------------");
// skip
employees.stream().filter((x) -> x.salary > 5000)
.skip(2)
.forEach(System.out::println);
System.out.println("----------------------------------");
// distinct
employees.stream().filter((x) -> x.salary > 5000)
.distinct()
.forEach(System.out::println);
}
/**
* 映射
* map: 接受一个函数作为参数,该函数会应用到没一个元素上,并将其映射成一个新的元素
* flatMap: 将流中的每个值都转化为另一个流,并且将所有流连接成一个流。
*/
public static void testMap() {
// map
String[] strArr = {"aaa", "bbb", "ccc", "ddd"};
Arrays.stream(strArr).map(String::toUpperCase).forEach(System.out::println);
System.out.println("--------------------------");
employees.stream().map(Employee::getName).forEach(System.out::println);
System.out.println("#########################");
// flatMap
// 如果只使用map,将上面strArr拆分成 {"a","a","a","b",.....}
Stream<Stream<Character>> rStream = Arrays.stream(strArr).map(StreamTest::filterCharacter);
rStream.forEach((st) -> st.forEach(System.out::println));
System.out.println("--------------------------");
//使用 flatMap
Arrays.stream(strArr).flatMap(StreamTest::filterCharacter).forEach(System.out::println);
}
public static Stream<Character> filterCharacter(String str) {
List<Character> list = new ArrayList<>();
for (char c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
/**
* 排序
* <p>
* sorted() : 自然排序 (comparable)
* sorted(Comparator com)
*/
public static void sort() {
// sorted()
String[] strArr = {"ccc", "ddd", "aaa", "bbb"};
Arrays.stream(strArr).sorted().forEach(System.out::println);
System.out.println("-----------------------------------");
// sorted(Comparator com)
employees.stream().sorted((x, y) -> {
if (x.getAge().equals(y.getAge())) {
return x.getName().compareTo(y.getName());
} else {
return x.getAge().compareTo(y.getAge());
}
}).forEach(System.out::println);
}
/**
* 查找与匹配
* <p>
* allMatch : 检查是否匹配所有元素
* anyMatch: 检查是否匹配一个元素
* noneMatch: 检查是否没有匹配任何一个个元素
* findFirst: 返回第一个元素
* findAny: 返回任意一个元素
* count: 计算总数
* max: 返回最大值
* min: 返回最小值
*/
public static void find() {
// allMatch
boolean b = employees.stream().allMatch(x -> x.getStatus().equals(Employee.Status.BUSY));
System.out.println(b);
System.out.println("--------------------------------");
// findFirst
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first.get());
System.out.println("--------------------------------");
// count
long count = employees.stream().count();
System.out.println(count);
System.out.println("--------------------------------");
// max min
Optional<Employee> max = employees.stream().max((x, y) -> Double.compare(x.getAge(), y.getAge()));
System.out.println(max);
Optional<Integer> max1 = employees.stream().map(Employee::getAge).max(Double::compare);
System.out.println(max1.get());
}
/**
* 规约
* 可以将流中的元素反复结合起来,得到一个值
*/
public static void test1() {
// 规约
Integer[] intArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Integer reduce = Arrays.stream(intArr).reduce(0, (x, y) -> x + y);
System.out.println(reduce);
System.out.println("--------------------------------------");
Optional<Double> reduce1 = employees.stream().map(Employee::getSalary).reduce(Double::sum);
System.out.println(reduce1.get());
System.out.println("##############################");
// 收集
List<Employee> collect = employees.stream().collect(Collectors.toList());
Set<Employee> collect1 = employees.stream().collect(Collectors.toSet());
HashSet<String> collect2 = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
// 总数 : Collectors.counting()
// 平均值: Collectors.averagingDouble();
// 总和: Collectors.summingDouble();
// 其他获取总数,平均值的方法
DoubleSummaryStatistics collect7 = employees.stream().collect(Collectors.summarizingDouble(Employee::getAge));
double average = collect7.getAverage();
long count = collect7.getCount();
double max = collect7.getMax();
double min = collect7.getMin();
double sum = collect7.getSum();
// 最值
Optional<Employee> collect3 = employees.stream().collect(Collectors.maxBy((x, y) -> Double.compare(x.getSalary(), y.getSalary())));
// 分组
Map<Employee.Status, List<Employee>> collect4 = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
// 多级分组
Map<Employee.Status, Map<Integer, List<Employee>>> collect5 = employees.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(Employee::getAge)));
// 分区,满足条件的一个区,不满足条件的一个区
Map<Boolean, List<Employee>> collect6 = employees.stream().collect(Collectors.partitioningBy(e -> e.getAge() > 35));
// join
String collect8 = employees.stream().map(Employee::getName).collect(Collectors.joining()); // 将每个employee中的name相连
String collect9 = employees.stream().map(Employee::getName).collect(Collectors.joining(",")); // 将每个employee中的name相连,用‘,’隔开
String collect10 = employees.stream().map(Employee::getName).collect(Collectors.joining(",", "++", "++"));// 将每个employee中的name相连,用‘,’隔开,前后加上++
}
/**
* 并行流
*
* .parallel() :利用fork/join框架并行执行
*/
public static void test2(){
Instant start = Instant.now();
LongStream.rangeClosed(0, 99999999999L)
.parallel()
.reduce(0, Long::sum);
Instant end = Instant.now();
System.out.println(Duration.between(start,end).toMillis());
System.out.println("--------------------------");
employees.stream()
.parallel()
.filter((x) -> x.age > 35).forEach(System.out::println);
}
}
- Employee
public class Employee {
String name;
Integer age;
Double salary;
Status status;
public Employee(String name, Integer age, Double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public Employee(String name, Integer age, Double salary, Status status) {
this.name = name;
this.age = age;
this.salary = salary;
this.status = status;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (name != null ? !name.equals(employee.name) : employee.name != null) return false;
if (age != null ? !age.equals(employee.age) : employee.age != null) return false;
if (salary != null ? !salary.equals(employee.salary) : employee.salary != null) return false;
return status == employee.status;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (age != null ? age.hashCode() : 0);
result = 31 * result + (salary != null ? salary.hashCode() : 0);
result = 31 * result + (status != null ? status.hashCode() : 0);
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
", status=" + status +
'}';
}
public enum Status{
FREE,
BUSY,
VOCATION;
}
}