Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,课执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来进行执行操作。简而言之,Stream API提供了一种高效且易于使用的处理数据的方式
注意:
- Stream自己不会存储元素
- Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
- Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
创建Stream
Java8中的Collection接口被扩展,提供了两个获取流的方法:
- default Stream<E> stream():返回一个顺序流
- default Stream<E> parallelStream():返回一个并行流
//创建Stream
@Test
public void test1(){
//1.可以通过Collection系列集合提供的stream()-串行流或parallelStream()-并行流
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//2.通过Arrays中的静态方法stream()获取数组流
Employee[] emp = new Employee[10];
Stream<Employee> stream1 = Arrays.stream(emp);
//3.通过Stream类中的静态方法of()
Stream<String> stream2 = Stream.of("aa","bb","cc");
//4.创建无限流
//迭代
Stream<Integer> stream3 = Stream.iterate(0,x->x+2);
stream3.limit(10).forEach(System.out::println);
}
Stream的中间操作
@Test
public void test(){
Integer[] num = new Integer[]{1,2,3,4,5};
Arrays.stream(num)
.map(x->x*x)
.forEach(System.out::println);
}
/*
筛选与切片
filter-接收Lambda,从流中排除某些元素
limit-截断流,使其元素不超过给定数量,只要查到了给定数量的元素,就不会往下执行了
skip-跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流。与 limit(n)互补
distinct-筛选,通过流所生成的元素的hashCode()和equals()去除重复元素
*/
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99),
new Employee("李四",30,5000),
new Employee("王五",35,1111),
new Employee("赵六",42,2222),
new Employee("田七",19,9900),
new Employee("田七",19,9900),
new Employee("田七",19,9900)
);
//中间操作
//内部迭代:迭代操作由Stream API完成
@Test
public void test1(){
//中间操作 不会执行任何处理
Stream<Employee> stream = employees.stream()
.filter(e->{
System.out.println("StreamAPI的中间操作");
return e.getAge()>35;
});
//终止操作 一次性执行全部内容,即“惰性求值”
stream.forEach(System.out::println);
}
@Test
public void test2(){
employees.stream()
.filter(employee -> {
System.out.println("短路");
return employee.getSalary()>5000;
})
.limit(2)
.forEach(System.out::println);
}
@Test
public void test3(){
employees.stream()
.filter(employee -> {
System.out.println("短路");
return employee.getSalary()>5000;
})
.limit(2)
.forEach(System.out::println);
}
@Test
public void test4(){
employees.stream()
.skip(2)
.filter(employee -> employee.getSalary()>5000)
.distinct()
.forEach(System.out::println);
}
/*
映射
map-接收Lambda,将元素转换为其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每一个元素上,
并将其映射成一个新的元素
flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
*/
@Test
public void test5(){
List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
list.stream()
.map(s -> s.toUpperCase())
.forEach(System.out::println);
System.out.println("------------------");
employees.stream()
.map(employee -> employee.getName())
.forEach(System.out::println);
System.out.println("--------------------");
// Stream<Stream<Character>> stream = list.stream()
// .map(s -> filterCharacter(s));
// stream.forEach(sm->sm.forEach(System.out::println));//{{a,a,a},{b,b,b}}
System.out.println("--------------------");
Stream<Character> stream=list.stream()
.flatMap(s -> filterCharacter(s));//{a,a,a,b,b,b}
stream.forEach(System.out::println);
}
public Stream<Character> filterCharacter(String str){
List<Character> list =new ArrayList<>();
for (Character ch:str.toCharArray()){
list.add(ch);
}
return list.stream();
}
/*
排序
sort()——自然排序(Comparable)
sort(Comparator com)——定制排序
*/
@Test
public void test6(){
employees.stream()
.sorted((e1,e2)->{
if(e1.getAge()==e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else {
return -e1.getAge().compareTo(e2.getAge());
}
}).forEach(System.out::println);
}
Stream流的终止操作
/*
查找与匹配
allMatch——检查是否匹配所有元素
anyMatch——检查是否至少匹配一个元素
noneMatch——检查是否没有匹配所有元素
findFirst——返回第一个元素
findAny——返回当前流中的任意元素
count——返回六中元素的总个数
max——返回流中最大值
min——返回流中最小值
*/
List<Employee> employees = Arrays.asList(
new Employee("张三",18,9999.99d, Employee.Status.FREE),
new Employee("李四",30,5000d,Employee.Status.BUSY),
new Employee("王五",35,1111d, Employee.Status.VOATION),
new Employee("赵六",42,2222d, Employee.Status.FREE),
new Employee("田七",19,9900d, Employee.Status.BUSY)
);
@Test
public void test1(){
boolean bln = employees.stream()
.allMatch(employee -> employee.getStatus().equals(Employee.Status.BUSY));
System.out.println(bln);
boolean bln2 = employees.stream()
.anyMatch(employee ->employee.getStatus().equals(Employee.Status.BUSY));
System.out.println(bln2);
boolean bln3 = employees.stream()
.noneMatch(employee ->employee.getStatus().equals(Employee.Status.BUSY));
System.out.println(bln3);
Optional<Employee> first = employees.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
.findFirst();
System.out.println(first.get());
Optional<Employee> any = employees.stream()
.filter(employee -> employee.getStatus().equals(Employee.Status.FREE))
.findAny();
System.out.println(any);
}
@Test
public void test2(){
long count = employees.stream()
.count();
System.out.println(count);
Optional<Employee> max = employees.stream()
.max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(max.get());
Optional<Double> min = employees.stream()
.map(employee -> employee.getSalary())
.min((e1, e2) -> Double.compare(e1, e2));
System.out.println(min.get());
}
/*
规约
reduce(T identity,BinaryOperator)/reduce(BinaryOperator)——可以将流中元素反复结合起来,得到一个值
*/
@Test
public void test3(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer reduce = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println(reduce);
System.out.println("--------------------");
Double reduce1 = employees.stream()
.map(employee -> employee.getSalary())
.reduce(0d, (x, y) -> x + y);
Optional<Double> reduce2 = employees.stream()
.map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(reduce1);
System.out.println(reduce2.get());
}
/*
收集:
collect——将流转换为其他形式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
*/
@Test
public void test4(){
List<String> collect = employees.stream()
.map(employee -> employee.getName())
.collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("--------------------");
Set<String> collect1 = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
collect1.forEach(System.out::println);
System.out.println("-------------------");
HashSet<String> collect2 = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));
collect2.forEach(System.out::println);
System.out.println("-------------------");
Map<String, String> collect3 = employees.stream()
.map(Employee::getName)
.collect(Collectors.toMap(x -> x, y -> y));
for (String key:collect3.keySet()){
System.out.println(key+" "+collect3.get(key));
}
Optional<Double> collect4 = employees.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1, e2)));
System.out.println(collect4.get());
}
@Test
public void test5(){
//总数
Long collect = employees.stream()
.collect(Collectors.counting());
System.out.println(collect);
System.out.println("---------------");
//平均值
Double collect1 = employees.stream()
.map(employee -> employee.getSalary())
.collect(Collectors.averagingDouble(x->x));
Double collect2 = employees.stream()
.collect(Collectors.averagingDouble(employees -> employees.getSalary()));
System.out.println("平均值:"+collect1+" "+collect2);
System.out.println("--------------------");
//总和
Double collect3 = employees.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println("总和"+collect3);
System.out.println("--------------------");
//最大值
Optional<Employee> max = employees.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(max.get());
System.out.println("------------------");
//最小值
Optional<Employee> min = employees.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(min.get());
System.out.println("------------------");
}
//分组
@Test
public void test6(){
Map<Employee.Status, List<Employee>> collect = employees.stream()
.collect(Collectors.groupingBy(employee -> employee.getStatus()));
System.out.println(collect);
}
//多级分组
@Test
public void test7(){
Map<Employee.Status,Map<String,List<Employee>>> map = employees.stream()
.collect(Collectors.groupingBy(employee -> ((Employee)employee).getStatus(),Collectors.groupingBy(employee -> {
if(((Employee)employee).getAge()<=35){
return "青年";
}else if(((Employee)employee).getAge()<=50){
return "中年";
}else {
return "老年";
}
})));
System.out.println(map);
}
//分区 满足条件的一个区,不满足条件的一个区
@Test
public void test8(){
Map<Boolean, List<Employee>> collect = employees.stream()
.collect(Collectors.partitioningBy(employee -> employee.getSalary() > 8000));
System.out.println(collect);
}
@Test
public void test9(){
DoubleSummaryStatistics collect = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(collect.getMax());
System.out.println(collect.getAverage());
System.out.println(collect.getCount());
}
@Test
public void test10(){
String collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(",","==","----"));
System.out.println(collect);
}