java8_02_stream(一)创建流和中间操作的后续部分,jdk 1.8.0_91
三、终止操作
3.1 常见的八种操作
- allMatch——检查是否匹配所有元素
- anyMatch——检查是否至少匹配一个元素
- noneMatch——检查是否没有匹配的元素
- findFirst——返回第一个元素
- findAny——返回当前流中的任意元素
- count——返回流中元素的总个数
- max——返回流中最大值
- min——返回流中最小值
测试用例
public class Student {
private String name;
private Integer age;
private Integer score;
private Status status;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public Student() {
}
public Student(String name, Integer age, Integer score) {
this.name = name;
this.age = age;
this.score = score;
}
public Student(String name, Integer age, Integer score, Status status) {
this.name = name;
this.age = age;
this.score = score;
this.status = status;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (name != null ? !name.equals(student.name) : student.name != null) return false;
if (age != null ? !age.equals(student.age) : student.age != null) return false;
return score != null ? score.equals(student.score) : student.score == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (age != null ? age.hashCode() : 0);
result = 31 * result + (score != null ? score.hashCode() : 0);
return result;
}
public enum Status{
FREE,
BUSY,
HAPPY
}
}
代码示例
public class StreamDemo3 {
/*
测试数据集合
*/
List<Student> students = Arrays.asList(
new Student("张三",18,88, Student.Status.BUSY),
new Student("李四",18,80, Student.Status.BUSY),
new Student("王五",19,60, Student.Status.FREE),
new Student("王五",19,60, Student.Status.BUSY),
new Student("王五",19,60, Student.Status.HAPPY),
new Student("赵六",17,100, Student.Status.HAPPY)
);
@Test
public void test(){
boolean b = students.stream()
.allMatch(s -> s.getAge() > 17);
System.out.println(b);
}
@Test
public void test2(){
boolean b = students.stream()
.anyMatch(s->s.getAge()>17);
System.out.println(b);
}
@Test
public void test3(){
boolean b = students.stream()
.noneMatch(s->s.getAge()>100);
System.out.println(b);
}
@Test
public void test4(){
Optional<Student> studentOptional = students.stream()
.filter(s->s.getStatus().equals(Student.Status.BUSY))
.findFirst();
if (studentOptional.isPresent()){ // 判断是否为null,避免空指针异常
System.out.println(studentOptional.get()); //获得结果
}
}
@Test
public void test5(){
Optional<Student> studentOptional = students.stream()
.filter(s->s.getStatus().equals(Student.Status.BUSY))
.findAny(); // 满足条件的任意一个
if (studentOptional.isPresent()){
System.out.println(studentOptional.get());
}
Optional<Student> studentOptional2 = students.parallelStream()
.filter(s->s.getStatus().equals(Student.Status.BUSY))
.findAny();
if (studentOptional2.isPresent()){
System.out.println(studentOptional2.get());
}
}
@Test
public void test6(){
Long count = students.stream()
.filter(s->s.getStatus().equals(Student.Status.BUSY))
.count();
System.out.println(count);
}
@Test
public void test7(){
Optional<Student> maxScoreStudent = students.stream()
.filter(s->s.getStatus().equals(Student.Status.BUSY))
.max(Comparator.comparingInt(Student::getScore)); //等同于 .max((s1,s2)->Integer.compare(s1.getScore(),s2.getScore()));
System.out.println("busy状态,分数最多:" +maxScoreStudent.get());
}
@Test
public void test8(){
Optional<Student> studentOptional = students.stream()
.min(Comparator.comparingInt(Student::getAge)); //等同于 .min((s1,s2)-> Integer.compare(s1.getAge(),s2.getAge()));
if (studentOptional.isPresent())
System.out.println(studentOptional.get());
}
}
3.2 归约
reduce(T identity, BinaryOperator) / reduce(BinaryOperator):将流中的元素反复结合起来,得到一个值
@Test
public void test9(){
List<Integer> integerList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//求和操作
Integer sum = integerList.stream()
.reduce(0,Integer::sum); //reduce(初始因子,计算算法)
System.out.println(sum);
//学生分数总和
Optional<Integer> scoreSumOptional = students.stream()
.map(Student::getScore)
.reduce(Integer::sum); //没有初始因子,所以返回的Optional<T> 集合类,可以避免空指针异常
if (scoreSumOptional.isPresent())
System.out.println(scoreSumOptional.get());
}
@Test
public void test10(){
//需求:名字中,“五”字出现的次数
Optional<Integer> fiveOp = students.stream()
.map(Student::getName)
.flatMap(str ->{ //str->List<Character>-> Stream<Character>
List<Character> characters = new ArrayList<>();
for (Character ch : str.toCharArray()){
characters.add(ch);
}
return characters.stream();
})
.map(ch -> { // ‘五’出现一次,返回 1 ,
if (ch.equals('五') || ch == '五') { //注意 char使用单引号。换为双引号后容易出错
return 1;
} else return 0;
}
).reduce(Integer::sum); // 求和
System.out.println(fiveOp.get());
}
3.3 collect() 操作
collect():将流转换成其他形式。接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
@Test
public void testCollect(){
List<String> nameList = students.stream()
.map(Student::getName)
.collect(Collectors.toList());
nameList.forEach(System.out::println);
System.out.println("---------------------------");
Set<String> nameSet = students.stream()
.map(Student::getName)
.collect(Collectors.toSet());
nameSet.forEach(System.out::println);
System.out.println("---------------------------");
HashSet<String> nameHashSet = students.stream()
.map(Student::getName)
.collect(Collectors.toCollection(HashSet::new)); //没有toHashSet,只能 toCollection(HashSet::new)
nameHashSet.forEach(System.out::println);
System.out.println("---------------------------");
LinkedList<String> nameLinked = students.stream()
.map(Student::getName)
.collect(Collectors.toCollection(LinkedList::new));
nameLinked.forEach(System.out::println);
}
@Test
public void test11(){
Optional<Integer> integerMaxOptional = students.stream().map(Student::getScore).max(Integer::compareTo);
System.out.println(integerMaxOptional.get());
Optional<Student> minOp = students.stream()
.collect(Collectors.minBy((s1,s2)-> Integer.compare(s1.getAge(),s2.getAge())));
System.out.println("年龄最小的对象:"+ minOp.get());
Optional<Student> minOp2 = students.parallelStream()
.min(Comparator.comparingInt(Student::getAge));
System.out.println("年龄最小的对象:"+ minOp2.get());
IntSummaryStatistics iss = students.stream().collect(Collectors.summarizingInt(Student::getAge));
System.out.println(iss.getAverage()); //平均值
System.out.println(iss.getCount()); //个数
System.out.println(iss.getMax()); // 最大值
System.out.println(iss.getMin()); // 最小值
System.out.println(iss.getSum()); // 和
}
分组操作
@Test
public void test12(){
//普通分组
Map<Student.Status,List<Student>> groupByStatus = students.stream()
.collect(Collectors.groupingBy(Student::getStatus));
System.out.println(groupByStatus);
//多级分组
Map<Student.Status,Map<Integer,List<Student>>> manyGroup = students.stream()
.collect(Collectors.groupingBy(Student::getStatus,Collectors.groupingBy(Student::getAge)));
System.out.println(manyGroup);
Map<Student.Status,Map<String,List<Student>>> manyGroup2 = students.stream()
.collect(Collectors.groupingBy(Student::getStatus,Collectors.groupingBy(s ->{
if (s.getScore() < 60 ) return "未及格";
else if (s.getScore() > 80) return "优秀";
else return "普通";
})));
System.out.println(manyGroup2);
}
分区操作:true:xxx,flase:xxx
@Test
public void test13(){
//分区,分成满足条件的部分,和未满足条件的部分
Map<Boolean,List<Student>> partStudent = students.stream()
.collect(Collectors.partitioningBy(s-> s.getScore() > 75));
System.out.println(partStudent);
//多级分区 1->2->4 ...
Map<Boolean,Map<Boolean,List<Student>>> fourPart = students.stream()
.collect(Collectors.partitioningBy(s-> s.getScore() > 75,Collectors.partitioningBy( s2 -> s2.getAge() == 17 )));
System.out.println(fourPart);
}
连接操作
@Test
public void test14(){
String joinStr = students.stream()
.map(Student::getName)
.collect(Collectors.joining(","));
System.out.println(joinStr);
String joinStr2 = students.stream()
.map(Student::getName)
.collect(Collectors.joining(",","+","-"));
System.out.println(joinStr2);
}
总结
Stream使用总结
- 一个数据源(如集合) 如 执行一个查询,获得数据集合;
- 一个中间操作链,形成一条流的流水线;
- 一个终端操作,执行流水线,并能生成结果。(eg:count()、collect(toList()) )
常见中间操作
操作 | 返回类型 | 操作参数 | 函数描述符 |
---|---|---|---|
filter | Stream | Predicate | T-> boolean |
map | Stream | Function | T -> R |
limit | Stream | ||
sorted | Stream | Comparator | (T,T) ->int |
distinct | Stream |
常见终端操作
操作 | 类型 | 目的 |
---|---|---|
forEach | 终端 | 消费流中的每个元素并对其应用Lambda。返回void |
count | 终端 | 返回流中元素的个数。返回long |
collect | 终端 | 把流归约成一个集合,比如List、Map甚至是Integer。 |