public class StreamTest {
List<Student> students = Arrays.asList(
new Student("张三",12, Student.Status.VOCATION),
new Student("李四",18, Student.Status.BUSY),
new Student("王五",19, Student.Status.FREE),
new Student("赵六",39, Student.Status.BUSY)
);
/**
* 1. 创建Stream
*/
@Test
public void test(){
//1. 通过Collection 集合提供的 stream() 或 parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
Stream<String> stream1 = list.parallelStream();
//2.通过Arrays中的静态方法 stream() 获取数组流
Student[] students = new Student[10];
Stream<Student> stream2 = Arrays.stream(students);
//3. 通过Stream的静态方法 of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
//4. 创建无限流
//4.1 迭代
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
stream4.limit(4).forEach(System.out::println);
//4.2 生成
Stream.generate(()-> (int) (Math.random() * 10))
.limit(5)
.forEach(System.out::println);
}
/**
* 2. stream中间操作
*
* 筛选与切片
* filter - 接收Lambda,从流中排除某些元素
* limit - 截断流,使其元素不超过给定数量
* skip(n) - 跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
* distinct - 筛选,通过流所生成元素的 hashCode() 和equals() 去除重复元素。
*
*
* 内部迭代:迭代操作是由Stream API 自己完成的。
*/
@Test
public void test1(){
Stream<Student> stream = students.stream()
.filter((e) -> {
return e.getAge() > 18;
});
// 终止操作 直到有终止操作,中间操作才会执行(惰性求值)。
stream.forEach(System.out::println);
}
/**
* 映射
* map - 接收lambda, 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
* flatMap - 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流都连接成一个流。
*/
@Test
public void test2(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
list.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
// 将多stream合并成一个Stream 类似于 addAll(Collection c)
list.stream()
.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(Compartor com) - 定制排序
*/
@Test
public void test3(){
List<String> list = Arrays.asList("ccc", "bbb", "aaa", "ddd", "eee");
//sorted()
list.stream()
.sorted()
.forEach(System.out::println);
//sorted(Compartor com)
students.stream()
.sorted((s1,s2) ->{
if (s1.getAge() > s2.getAge()){
return -1;
}else if (s1.getAge() < s2.getAge()){
return 1;
}else {
return s1.getName().compareTo(s2.getName());
}
}).forEach(System.out::println);
}
/**
* 3. 终止操作
*
* 查找与匹配
* allMatch - 检查是否匹配所有元素
* anyMatch - 检查是否至少匹配一个元素
* noneMatch - 检查是否没有匹配所有元素
* findFirst - 返回第一个元素
* findAny - 返回当前流中的任意元素
* count - 返回流中元素的总个数
* max - 返回流中的最大值
* min - 返回流中的最小值
*/
@Test
public void test4(){
// allMatch
boolean b1 = students.stream()
.allMatch((x) -> x.getStatus().equals(Student.Status.BUSY));
System.out.println(b1); //false
//anyMatch
boolean b2 = students.stream()
.anyMatch((x) -> x.getStatus().equals(Student.Status.BUSY));
System.out.println(b2); //true
//noneMatch
boolean b3 = students.stream()
.noneMatch((x) -> x.getStatus().equals(Student.Status.BUSY));
System.out.println(b3); //false
//findFirst
Student student = students.stream()
.findFirst().get();
System.out.println(student);
//findAny
Student student1 = students.stream()
.findAny().get();
System.out.println(student1);
//count
long count = students.stream().count();
System.out.println(count);
//max
Student student2 = students.stream()
.max(Comparator.comparingInt(Student::getAge))
.get();
System.out.println(student2);
//min
Integer minAge = students.stream()
.map(Student::getAge)
.min(Integer::compare).get();
System.out.println(minAge);
}
/**
* 归约
*
* reduce(T identity, BinaryOperator)
*
* reduce(BinaryOperator)
* 可以将流中元素反复结合起来,得到一个值。
*/
@Test
public void test5(){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Integer s = list.stream()
.reduce(100, Integer::sum);
System.out.println(s); //145
Integer s1 = list.stream()
.reduce(Integer::sum).get();
System.out.println(s1); //45
Optional<Integer> reduce = students.stream()
.map(Student::getAge)
.reduce(Integer::sum);
System.out.println(reduce.get());
}
/**
* 收集
* collect - 将流转换为其它形式。
* 接收一个Collector接口的实现,用于给Stream中元素做汇总方法。
*/
@Test
public void test6(){
//收集成Collection集合类
List<String> list = students.stream()
.map(Student::getName)
.collect(Collectors.toList());
Set<String> set = students.stream()
.map(Student::getName)
.collect(Collectors.toSet());
HashSet<String> hashSet = students.stream()
.map(Student::getName)
.collect(Collectors.toCollection(HashSet::new));
Map<String, Student> map = students.stream()
.collect(Collectors.toMap(Student::getName, (s) -> s));
}
/**
* 求值
*/
@Test
public void test7(){
// 总数
Long collect = students.stream()
.collect(Collectors.counting());
System.out.println(collect);
// 总和
Integer sum = students.stream()
.collect(Collectors.summingInt(Student::getAge));
System.out.println(sum);
// 平均值
Double avg = students.stream()
.collect(Collectors.averagingInt(Student::getAge));
System.out.println(avg);
// 最大值
Optional<Student> max = students.stream()
.collect(Collectors.maxBy((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge())));
System.out.println(max.get());
// 最小值
Optional<Integer> min = students.stream()
.map(Student::getAge)
.collect(Collectors.minBy(Integer::compareTo));
System.out.println(min.get());
//总的 求值收集器
IntSummaryStatistics statistics = students.stream()
.collect(Collectors.summarizingInt(Student::getAge));
System.out.println(statistics.getCount());
System.out.println(statistics.getSum());
System.out.println(statistics.getAverage());
System.out.println(statistics.getMax());
System.out.println(statistics.getMin());
}
/**
* 分组
*/
@Test
public void test8(){
// 按照Status分组
Map<Student.Status, List<Student>> map = students.stream()
.collect(Collectors.groupingBy(Student::getStatus));
System.out.println(map);
// 多级分组
Map<Student.Status, Map<String, List<Student>>> map1 = students.stream()
.collect(Collectors.groupingBy(Student::getStatus, Collectors.groupingBy((s) -> {
if (s.getAge() < 18) {
return "少年";
} else if (s.getAge() >= 18 && s.getAge() < 20) {
return "成年";
} else {
return "老年";
}
})));
System.out.println(map1);
}
/**
* 分区
*/
@Test
public void test9(){
Map<Boolean, List<Student>> map = students.stream()
.collect(Collectors.partitioningBy((s) -> s.getStatus() == Student.Status.BUSY));
System.out.println(map);
}
/**
* join 连接字符串
*/
@Test
public void test10(){
String joinStr = students.stream()
.map(Student::getName)
.collect(Collectors.joining(","));
System.out.println(joinStr); //张三,李四,王五,赵六
}
}
Lambda 方法引用与构造器引用
//方法引用
public class TestMethodRef {
/**
* 若lambda实现体内调用方法的 参数 与返回值 与 函数式接口一样 那么就可以使用 `方法引用`
*
* 1. 对象::实例方法名
*
* 2. 类::静态方法名
*/
//对象::实例方法名
@Test
public void test(){
// 空参数 返回值T
Student student = new Student();
Supplier<String> su = student::getName;
// Runnable接口 空参数 空返回值
new Thread(student::haha).start();
}
// 类::静态方法名
@Test
public void test2(){
//原来的写法
Comparator<Integer> com = (x,y)-> Integer.compare(x,y);
//改变后的写法
Comparator<Integer> com1 = Integer::compare;
}
/**
* 若函数式接口的
* 第一个参数 是lambda体 实例方法 的调用者
* 第二个参数 是lambda体 实例方法 的参数
* 那么可以使用 类::实例方法名
*/
@Test
public void test3(){
// 原来的写法
BiPredicate<String,String> bp = (x,y) -> x.equals(y);
// 改变后的写法
BiPredicate<String,String> bp1 = String::equals;
}
}
/**
* 构造器引用
*
* 格式: ClassName::new
*/
public class TestConstructRef {
@Test
public void test(){
//原来写法
Supplier<Student> stu = ()-> new Student();
//构造器引用写法 使用的是空参构造 实际上与Supplier的 get()方法 的参数与返回值一致
Supplier<Student> stu1 = Student::new;
}
}