一、了解Stream
Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作
二、什么是Stream
流(Stream)到底是什么呢?
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”。
注意:
(1)、Stream自己不会存储元素。
(2)、Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。
(3)、Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
三、Stream的操作三个步骤
三、Stream的操作三个步骤
(1)、创建Stream
一个数据源(如:集合、数组),获取一个流
(2)、中间操作
一个中间操作链,对数据源的数据进行处理
(3)、终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果。
注意:java中:>>>和>>区别
>>>表示不带符号向右移动二进制数,移动后前面统统补0;两个箭头表示带符号移动
没有<<<这种运算符,因为左移都是补零,没有正负数的区别。
如 -12 的二进制为:1111 1111 1111 1111 1111 1111 1111 0100;
-12 >> 3 即带符号右移3位,结果是:1111 1111 1111 1111 1111 1111 1111 1110,十进制为: -2;
-12 >>> 3 就是右移三位,前面补零,为:0001 1111 1111 1111 1111 1111 1111 1110,十进制为:536870910。
四、创建Stream
// 可以通过Collection系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<String>();
Stream<String> stream1 = list.stream();
//通过Arrays中的静态方法stream()获取数组流
Employee[] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);
// 通过Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
stream3.forEach(System.out::println);
//创建无限流
// 迭代
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
stream4.limit(10).forEach(System.out::println);
// 生产
Stream.generate( () -> Math.random()).limit(5).forEach(System.out::println);
五、中间操作
5.1、筛选与切片
// 5.1.1、filter——接收 Lambda , 从流中排除某些元素。
//
emps.stream().filter((e)->e.getAge() > 18)
.forEach(System.out::println);
// 5.1.2、limit——截断流,使其元素不超过给定数量。
emps.stream().filter((e)-> e.getAge()>18)
.limit(2).forEach(System.out::println);
// 5.1.3、 skip(n) ——跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
emps.stream().filter((e)->e.getAge()>18)
.skip(2).forEach(System.out::println);
// 5.1.4、distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
emps.stream().distinct().forEach(System.out::println);
5.2、映射
5.2.1、map-接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
5.2.2、flatMap-接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
list.stream().map((str)->str.toUpperCase())
.forEach(System.out::println);
System.out.println("------");
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "张三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
emps.stream()
.map(Employee::getName)
.forEach(System.out::println);
//流中流
Stream<Stream<Character>> stream = list.stream()
.map(TestStream::filterCharacter);
stream.forEach(sm->{
sm.forEach(System.out::println);
});
Stream<Character> flatMap = list.stream()
.flatMap(TestStream::filterCharacter);
flatMap.forEach(System.out::println);
}
/**
* 测试map跟flatMap的区别
* 有点跟集合中的add跟addAll方法类似
* add是将无论是元素还是集合,整体加到其中一个集合中去[1,2,3.[2,3]]
* addAll是将无论是元素还是集合,都是将元素加到另一个集合中去。[1,2,3,2,3]
* @param str
* @return
*/
public static Stream<Character> filterCharacter(String str) {
List<Character> list = new ArrayList<>();
for( Character character:str.toCharArray()){
list.add(character);
}
return list.stream();
}
5.3、排序
5.3.1、sorted()---自然排序(Comparable)
5.3.2、sorted(Comparator com)----定制排序(Comparator)
List<String> list = Arrays.asList("aa", "cc", "dd","ee");
list.stream().sorted().forEach(System.out::println);
System.out.println("=====");
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "张三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
emps.stream().sorted((x,y)-> {
if (x.getAge() == y.getAge()) {
return x.getName().compareTo(y.getName());
} else {
return Integer.compare(x.getAge(), y.getAge());
}
}).forEach(System.out::println);
六、终止操作
6.1、查找与匹配
allMatch——检查是否匹配所有元素
anyMatch——检查是否至少匹配一个元素
noneMatch——检查是否没有匹配的元素
findFirst——返回第一个元素
findAny——返回当前流中的任意元素
count——返回流中元素的总个数
max——返回流中最大值
min——返回流中最小值
List<Employee2> emps = Arrays.asList(
new Employee2(102, "李四", 59, 6666.66, Employee2.Status.BUSY.BUSY),
new Employee2(101, "张三", 18, 9999.99, Employee2.Status.FREE),
new Employee2(103, "王五", 28, 3333.33, Employee2.Status.VOCATION),
new Employee2(104, "赵六", 8, 7777.77, Employee2.Status.BUSY),
new Employee2(104, "赵六", 8, 7777.77, Employee2.Status.FREE),
new Employee2(104, "赵六", 8, 7777.77, Employee2.Status.FREE),
new Employee2(105, "田七", 38, 5555.55, Employee2.Status.BUSY)
);
System.out.println("allMatch");
// allMatch
boolean allMath = emps.stream().allMatch((e)->e.getStatus().equals(Employee2.Status.BUSY));
System.out.println(allMath);
System.out.println("anyMatch");
// anyMatch
boolean anyMath = emps.stream().anyMatch((e)->e.getAge()>18);
System.out.println(anyMath);
System.out.println("noneMatch");
// noneMatch
boolean noneMath = emps.stream().noneMatch((e)->e.getStatus().equals(Employee2.Status.BUSY));
System.out.println(noneMath);
System.out.println("findFirst");
// findFirst
Optional<Employee2> findFirst = emps.stream().sorted((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())).findFirst();
System.out.println(findFirst);
// findAny
System.out.println("findAny");
Optional<Employee2> findAny = emps.stream().filter((e)->e.getStatus().equals(Employee2.Status.BUSY))
.findAny();
System.out.println(findAny);
// count
System.out.println("count");
long count = emps.stream().count();
System.out.println(count);
// max
System.out.println("max");
// Optional<Double> max = emps.stream().max(Employee2::getSalary).map(Double::compare);
// System.out.println(max);
// min
System.out.println("min");
Optional<Employee2> min = emps.stream().min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(min);
6.2、归约
6.2.1、reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);
Integer sum = list.stream().reduce(0,(x,y)->x+y);
System.out.println(sum);
6.3、收集
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)。但是Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:
6.3.1、Collectors.toList()
List<Employee2> emps = Arrays.asList(
new Employee2(102, "李四", 59, 6666.66, Employee2.Status.BUSY.BUSY),
new Employee2(101, "张三", 18, 9999.99, Employee2.Status.FREE),
new Employee2(103, "王五", 28, 3333.33, Employee2.Status.VOCATION),
new Employee2(104, "赵六", 8, 7777.77, Employee2.Status.BUSY),
new Employee2(104, "赵六", 8, 7777.77, Employee2.Status.FREE),
new Employee2(104, "赵六", 8, 7777.77, Employee2.Status.FREE),
new Employee2(105, "田七", 38, 5555.55, Employee2.Status.BUSY)
);
System.out.println("toList");
// Collectors.toList()
List<String> collect = emps.stream().map(Employee2::getName).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("toSet");
// 6.3.2、Collectors.toSet()
Set<String> collect2 = emps.stream().map(Employee2::getName)
.collect(Collectors.toSet());
collect2.forEach(System.out::println);
//6.3.3、Collectors.toCollection(HashSet::new)
System.out.println("toCollection");
HashSet<String> collect3 = emps.stream().map(Employee2::getName).collect(Collectors.toCollection(HashSet::new));
System.out.println(collect3);
System.out.println("maxBy");
//6.3.4、Collectors.maxBy()
Optional<Double> collect5 = emps.stream()
.map(Employee2::getSalary).collect(Collectors.maxBy(Double::compare));
System.out.println(collect5.get());
// 6.3.5、Collectors.minBy()
System.out.println("minBy");
Optional<Double> collect4 = emps.stream()
.map(Employee2::getSalary).collect(Collectors.minBy(Double::compare));
System.out.println(collect4);
// 6.3.6、Collectors.summingDouble()
System.out.println("summingDouble");
Double collect6 = emps.stream().collect(Collectors.summingDouble(Employee2::getSalary));
System.out.println(collect6);
// 6.3.7、Collectors.averagingDouble()
System.out.println("averagingDouble");
Double collect7 = emps.stream()
.collect(Collectors.averagingDouble((e)->e.getSalary()));
System.out.println(collect7);
// 6.3.8、Collectors.counting()
System.out.println("counting");
Long collect8 = emps.stream().collect(Collectors.counting());
System.out.println(collect8);
// 6.3.9、Collectors.summarizingDouble()
System.out.println("summarizingDouble");
// Long collect9 = emps.stream().collect(Collectors.summingDouble)
// 6.3.10、分组Collectors.groupingBy()
System.out.println("groupingBy");
Map<Employee2.Status, List<Employee2>> collect10
= emps.stream()
.collect(Collectors.groupingBy((e)->e.getStatus()));
System.out.println(collect10);
// 6.3.11、多级分组Collectors.groupingBy()
// 6.3.12、分区Collectors.partitioningBy()
System.out.println("partitioningBy");
// 6.3.13、组接字符串Collectors.joining()
System.out.println("joining");