Java8新特性之三:Stream API

时间:2023-01-10 09:54:38


Java8新特性之三:Stream API

  • ​​什么是Stream​​
  • ​​Stream操作三个步骤​​
  • ​​第一步创建流​​
  • ​​中间操作​​
  • ​​筛选与切片​​
  • ​​Stream中间操作--映射​​
  • ​​排序​​
  • ​​终止操作​​
  • ​​查找与匹配​​
  • ​​规约​​
  • ​​收集​​

什么是Stream

Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式。Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找过滤筛选等操作,在新版的JPA中,也已经加入了Stream

流(Stream): 是数据渠道,用于操作数据源(集合,数组等)所生成的元素序列.
集合讲的是数据,流讲的是计算
注意:

  • Stream 自己不会存储元素
  • Stream 不会改变源对象,相反,他们会返回一个持有结果的新Stream
  • Stream 操作是延迟执行的,这意味着他们会等到需要要结果的时候才执行

Java8新特性之三:Stream API

Stream操作三个步骤

Stream有如下三个操作步骤:

一、创建Stream

从一个数据源,如集合、数组中获取流。

二、中间操作

一个操作的中间链,对数据源的数据进行操作。

三、终止操作

一个终止操作,执行中间操作链,并产生结果。

要注意的是,对流的操作完成后需要进行关闭操作(或者用JAVA7的try-with-resources)。

第一步创建流

  • 可以通过Collection系列集合提供的stream()或者parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
  • 通过Arrays中的静态方法stream()获取数组流
Employee[] employees = new Employee[10];
Stream<Employee> stream1 = Arrays.stream(employees);
  • 通过Stream 类中的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
  • 创建无限流
  • 迭代
  • 生成
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x +2 );
@Test
public void test1(){
//1可以通过Collection系列集合提供的stream()或者parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//2.通过Arrays中的静态方法stream()获取数组流
Person[] people = new Person[10];
Stream<Person> stream1 = Arrays.stream(people);

//3.通过Stream 类中的静态方法of()
Stream<String> stringStream = Stream.of("11", "bb", "cc");
//4创建无限流
//迭代
Stream<Integer> integerStream = Stream.iterate(0, (x) -> x + 2);
integerStream.limit(10).forEach(System.out::println);

//生成
Stream.generate(()->Math.random())
.limit(5).forEach(System.out::println);


}

中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理称为“惰性求值”

Java8新特性之三:Stream API

筛选与切片

filter:接收Lambda,从流中排除某些操作;
limit:截断流,使其元素不超过给定对象
skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
distinct:筛选,通过流所生素。需要重新hashcode()和equals()方法;

@Test
public void test2(){
Stream<Person> personStream = personLists.stream().filter((e) -> {
System.out.println("========"+e.getName());
return e.getAge() > 35;
});
personStream.forEach(System.out::println);

System.out.println("++++++++++");
personLists.stream().limit(2).forEach(System.out::println);
System.out.println("++++++++++");
personLists.stream().skip(2).forEach(System.out::println);
System.out.println("++++++++++");
personLists.stream().distinct().forEach(System.out::println);
}

Stream中间操作–映射

  • map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap–接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
@Test
public void test3(){
Stream.of("aaa","bbb","ccc")
.map((x)->x.toUpperCase())
.forEach(System.out::println);

personLists.stream()
.map(Person::getName)
.forEach(System.out::println);

}

排序

sorted():自然排序
sorted(Comparator com):定制排序

@Test
public void test4(){
// 自然排序
List<String> list = Arrays.asList( "bbb", "ccc" ,"aaa", "ddd");
list.stream().sorted().forEach(System.out::println);

//定制排序

// 定制排序
personLists.stream().sorted((person1,person2)->{
if(person1.getAge()==person2.getAge()){
return 0;
}else {
return person1.getAge()-person2.getAge();
}
}).forEach(System.out::println);

}

终止操作

执行下列操作后,Stream流就会进行终止执行

查找与匹配

allMatch:检查是否匹配所有元素
anyMatch:检查是否至少匹配一个元素
noneMatch:检查是否一个都没匹配
findFirst:返回第一个元素
findAny:返回当前流中任意一个元素
count:返回流中元素的个数
max:返回当前流中最大值
min:返回当前流中最小值
forEach:内部迭代

@Test
public void test5(){
boolean b=personLists.stream().allMatch((person)->{
return person.getAge()>40;
});
System.out.println(b);

boolean b2=personLists.stream().anyMatch((person)->{
return person.getAge()>40;
});
System.out.println(b2);

boolean b3=personLists.stream().noneMatch((person)->{
return person.getAge()>40;
});
System.out.println(b3);

System.out.println(personLists.stream().findFirst());

System.out.println(personLists.stream().findAny());

System.out.println(personLists.stream().count());

System.out.println(personLists.stream().max((person1, persion2) -> {
return person1.getAge() - persion2.getAge();
}));


}

规约

格式:reduce(T identity, BinaryOperator) / reduce(BinaryOperator)

可以将流中元素反复结合,得到一个新值

这个reduce,其实有点类似于Hadoop中的mapReduce,先做map操作,然后做reduce操作

@Test
public void test6(){
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer integer =list.stream().reduce( 10,(x,y)->{
return x+y;
});
System.out.println(integer); //65


Optional<Float> salOptional = personLists.stream().map(Person::getSalary).reduce(Float::sum);

System.out.println(salOptional.get()); //2553.0
}

收集

Collection将流转换成其它形式,接收一个Collector接口实现,用于给Stream中元素做汇总的方法

格式:collect(Collector c)

Collector接口实现方法的实现决定了如何对流执行收集操作(如收集到List,Set,Map)。但是Collectors实用类提供了很多静态方法,可以方便地创建常用收集器实例

@Test
public void test7(){
// 收集放入list中
List<String> list = personLists.stream().map(Person::getName).collect(Collectors.toList());
list.forEach(System.out::println);


Set<String> strings= personLists.stream().map(Person::getName).collect(Collectors.toSet());
System.out.println(strings);

HashSet<String> hashSet = personLists.stream().map(Person::getName).collect(Collectors.toCollection(HashSet::new));
System.out.println(hashSet);

}
@Test
public void test8(){
//总数
Long ages = personLists.stream().collect(Collectors.counting());
System.out.println(ages);

//平均数
Double floatsal = personLists.stream().collect(Collectors.averagingDouble(Person::getSalary));
System.out.println(floatsal);

//合计
Double sumsal = personLists.stream().collect(Collectors.summingDouble(Person::getSalary));
//最大值
Optional<Person> max = personLists.stream().collect(Collectors.maxBy((p1,p2)->Float.compare(p1.getSalary(),p2.getSalary())));
System.out.println(max.get());
//最小值
Optional<Person> min = personLists.stream().collect(Collectors.minBy((p1,p2)->Float.compare(p1.getSalary(),p2.getSalary())));
System.out.println(min.get());

}

@Test
public void test9(){
Map<Integer, List<Person>> listMap = personLists.stream().collect(Collectors.groupingBy(Person::getAge));
System.out.println(listMap);
}

@Test
public void test10(){
Map<String, Map<String, List<Person>>> stringMapMap = personLists.stream()
.collect(Collectors.groupingBy(Person::getName, Collectors.groupingBy((p) -> {
if (p.getAge() <= 35) {
return "青年";
} else if (p.getAge() <= 50) {
return "中年";
} else {
return "老年";
}
})));
System.out.println(stringMapMap);
}

@Test
public void test11(){
DoubleSummaryStatistics summaryStatistics = personLists.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println(summaryStatistics.getAverage());
System.out.println(summaryStatistics.getMax());
}

//分区
@Test
public void test12(){
Map<Boolean, List<Person>> booleanListMap = personLists.stream().collect(Collectors.partitioningBy((p) ->
p.getSalary() > 300f
));
System.out.println(booleanListMap);
}
//连接
@Test
public void test13(){
String collect = personLists.stream().map(Person::getName).collect(Collectors.joining(",", "@@@", "==="));
System.out.println(collect);
}

Java8新特性之三:Stream API