JAVA8有一个新功能——流。笔者简单的看一下流。然后默默的闭上眼睛。感叹一声:这不是.NET里面的Linq吗?如果你们当中有谁做过.NET程序员的话,对于流的学习其实帮助是很大的。但是要明白你现在是在学JAVA的流。虽然他们的概念是有一点像。可是这也只是对你在理解流上面有一定的帮助。因为JAVA实现的方式却完成不一样子(不入流程序员的个人理解)。
好吧。那么流是什么呢?如果用书里面的方式解释的话,笔者可能也看不懂。做过开发的人员一般都会知道一些SQL语句吧,SELECT语句这个功能。相信大家一定都熟悉吧——SELECT是对数据库的数据进行操作。同样子JAVA也有数据啊。比如集合、数组。那么为什么JAVA不可能实现一套代码式的数据操作。如果这样子不知道大家会不会明白呢?(当然这不是官方,是不入流的程序员这样了理解的)
SQL语句里面有什么——SELECT、FORM、WHERE、ORDER BY、GROUP BY。这些都是对数据库里面数据操作的常规动作。JAVA8的流呢? 即然是流。那么说明必须把对应的数据变成一个流才行。关键方法stream()就是这个作用。 举例子来说明吧。笔者有一组字符数组,笔者相要查找出有含有 r 的字符。
1 packagecom.aomi;2
3 importjava.util.Arrays;4 importjava.util.List;5
6 public classMain {7
8 public static voidmain(String[] args) {9 //TODO Auto-generated method stub
10
11 List datas = Arrays.asList("red", "green", "bule");12
13 datas14 .stream()15 .filter(s -> s.contains("r"))16 .forEach(s ->System.out.println(s));17 }18
19 }
运行结果:

让我们想想如果是以前的话,要什么样子去实现呢?
1 packagecom.aomi;2
3 importjava.util.ArrayList;4 importjava.util.Arrays;5 importjava.util.List;6
7 public classMain {8
9 public static voidmain(String[] args) {10 //TODO Auto-generated method stub
11
12 List datas = Arrays.asList("red", "green", "bule");13
14 //datas15 //.stream()16 //.filter(s -> s.contains("r"))17 //.forEach(s -> System.out.println(s));
18
19 List vDatas = new ArrayList<>();20
21 for(String str : datas) {22 if (str.contains("r")) {23 vDatas.add(str);24 }25 }26
27 for(String str : vDatas) {28 System.out.println(str);29 }30
31 }32
33 }
相对以前来讲很直观表现代码的意思。同时代码量又小很多。
filter:用于过滤数据的,从下面的代码就可以明白,返回一个boolean型类的结果。
Stream filter(Predicate super T> predicate);
forEach:循环遍历回来的结果集合。代码看完就知道什么样子用了。
void forEach(Consumer super T> action);
JAVA的代很多都是很人性化的,所以只要从名字就可以明白他大概的功能了。
好了,笔者突然有一个想法——想要把时面的‘r’字符变成‘o’字符。
1 packagecom.aomi;2
3 importjava.util.Arrays;4 importjava.util.List;5
6 public classMain {7
8 public static voidmain(String[] args) {9 //TODO Auto-generated method stub
10
11 List datas = Arrays.asList("red", "green", "bule");12
13 datas.stream()14 .map(s -> s.replace('r', 'o'))15 .forEach(s ->System.out.println(s));16
17 }18
19 }
笔者去掉了filter方法,用了map。运行结果:

map:相当于SQL中的 SELECT关键字有一点像。用于把结果变成你希望的样子。看一下代码
Stream map(Function super T, ? extends R> mapper);
是一个function的函数式接口。函数描述符:T -> R。
显示这样子的例子有一点简单。在实际的开发过程中我们往往都是一大波数据对象。这样子笔者定义一个学生类。
packagecom.aomi;public classStudent {privateString name;private intSex;privateString phone;private intscore;publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public intgetSex() {returnSex;
}public void setSex(intsex) {
Sex=sex;
}publicString getPhone() {returnphone;
}public voidsetPhone(String phone) {this.phone =phone;
}public intgetScore() {returnscore;
}public void setScore(intscore) {this.score =score;
}
}
在来写一个数据源吧。
1 packagecom.aomi;2
3 importjava.util.ArrayList;4 importjava.util.Arrays;5 importjava.util.List;6
7 public classMain {8
9 public static ListgetSources()10 {11 List students =new ArrayList<>();12
13 Student stu1 = newStudent();14
15 stu1.setName("lucy");16 stu1.setSex(0);17 stu1.setPhone("13700227892");18 stu1.setScore(9);19
20 Student stu2 = newStudent();21 stu2.setName("lin");22 stu2.setSex(1);23 stu2.setPhone("15700227122");24 stu2.setScore(9);25
26 Student stu3 = newStudent();27 stu3.setName("lili");28 stu3.setSex(0);29 stu3.setPhone("18500227892");30 stu3.setScore(8);31
32 Student stu4 = newStudent();33
34 stu4.setName("dark");35 stu4.setSex(1);36 stu4.setPhone("16700555892");37 stu4.setScore(6);38
39
40 students.add(stu1);41 students.add(stu2);42 students.add(stu3);43 students.add(stu4);44
45 returnstudents;46 }47
48 }
笔者定义了四个学生。这样子时候笔者想看看学分(Score)大于6同学的名字有哪一些。从上面代码我们可以看到除了第四个同学drak之后,其他都是合格的。 让我们看一下代码
1 packagecom.aomi;2
3 importjava.util.ArrayList;4 importjava.util.List;5 import staticjava.util.stream.Collectors.toList;6
7 public classMain {8
9 public static voidmain(String[] args) {10 //TODO Auto-generated method stub
11
12 List stus =getSources();13
14 List names =stus.stream()15 .filter(stu -> stu.getScore() > 6)16 .map(stu ->stu.getName())17 .collect(toList());18
19 for(String name : names) {20 System.out.println(name);21 }22
23 }24
25 public static ListgetSources() {26 List students = new ArrayList<>();27
28 Student stu1 = newStudent();29
30 stu1.setName("lucy");31 stu1.setSex(0);32 stu1.setPhone("13700227892");33 stu1.setScore(9);34
35 Student stu2 = newStudent();36 stu2.setName("lin");37 stu2.setSex(1);38 stu2.setPhone("15700227122");39 stu2.setScore(9);40
41 Student stu3 = newStudent();42 stu3.setName("lili");43 stu3.setSex(0);44 stu3.setPhone("18500227892");45 stu3.setScore(8);46
47 Student stu4 = newStudent();48
49 stu4.setName("dark");50 stu4.setSex(1);51 stu4.setPhone("16700555892");52 stu4.setScore(6);53
54 students.add(stu1);55 students.add(stu2);56 students.add(stu3);57 students.add(stu4);58
59 returnstudents;60 }61
62 }
运行结果:

当我们看到这个例子的时候,我们就可以确定map是做什么。就是用于最后确定返回数据类型。在这个代码中。笔者又用到了一个叫collect的方法。
collect:用于收集数据的功能。即是把相关的数据汇总成为另一种数据。
笔者传入是toList()方法。把最后数据变成一个集合。这个方法是Collectors类的一个静态方法。当然Collectors类里面有很多静态方法。如果你们去看一下他的代码。你就会发现他的方法名字好像都是在对数据操作的样子。没有错。以后我们开发过程都会用到Collectors类的方法集。
记得引用下面代码
import static java.util.stream.Collectors.toList;
从上面的几个例子来看。让笔者感觉如下
stream相关于SQL里面的FROM
filter相当于SQL里面的WHERE.
map相当于SQL里面的SELECT
那么其他呢?比如 order by或 group by 。让我们接着看吧。
现在笔者想在按学分(Score)高到低排序并且只显示学生名和学分呢?
packagecom.aomi;import staticjava.util.Comparator.comparing;import staticjava.util.stream.Collectors.toList;importjava.util.ArrayList;importjava.util.List;public classSMain {public static voidmain(String[] args) {//TODO Auto-generated method stub
List stus =getSources();
List names =stus.stream()
.sorted(comparing(Student::getScore).reversed())
.map(stu-> "学名:"+stu.getName()+" 学分:"+stu.getScore())
.collect(toList());for(String name : names) {
System.out.println(name);
}
}public static ListgetSources() {
List students = new ArrayList<>();
Student stu1= newStudent();
stu1.setName("lucy");
stu1.setSex(0);
stu1.setPhone("13700227892");
stu1.setScore(9);
Student stu2= newStudent();
stu2.setName("lin");
stu2.setSex(1);
stu2.setPhone("15700227122");
stu2.setScore(9);
Student stu3= newStudent();
stu3.setName("lili");
stu3.setSex(0);
stu3.setPhone("18500227892");
stu3.setScore(8);
Student stu4= newStudent();
stu4.setName("dark");
stu4.setSex(1);
stu4.setPhone("16700555892");
stu4.setScore(6);
students.add(stu1);
students.add(stu2);
students.add(stu3);
students.add(stu4);returnstudents;
}
}
运行结果:

关于上面sorted的用法。笔者上面已经讲过了。
现在笔者想看看男女各位的学习情况。又要如何。来分个组吧。
1 packagecom.aomi;2
3 import staticjava.util.stream.Collectors.groupingBy;4
5 importjava.util.ArrayList;6 importjava.util.List;7
8 public classSMain {9
10 public static voidmain(String[] args) {11 //TODO Auto-generated method stub
12
13 List stus =getSources();14
15 stus.stream()16 .collect(groupingBy(ss ->ss.getSex())).17 forEach((Integer sex, List students) ->{18 System.out.println("sex:" +sex);19
20 for(Student student : students) {21 System.out.println("name:" + student.getName() + " score:" +student.getScore());22 }23 });24
25 }26
27 //去掉学生源的方法。太多了影响查看
28 }
结果:

即然都分组了。那就笔者在做一个业务。查看男女个组的人数。
packagecom.aomi;import staticjava.util.stream.Collectors.groupingBy;importjava.util.ArrayList;importjava.util.List;importjava.util.stream.Collectors;public classSMain {public static voidmain(String[] args) {//TODO Auto-generated method stub
List stus =getSources();
stus.stream().collect(groupingBy(ss->{if (ss.getSex() == 0)return "女";else
return "男";
}, Collectors.counting()))
.forEach((String sex, Long count)->{
System.out.println("sex:" + sex + " count:" +count);
});
}
......
.....//去掉数据源
.....
}
运行结果:

在来一个分组之后,男女个组的总分。
packagecom.aomi;import staticjava.util.stream.Collectors.groupingBy;importjava.util.ArrayList;importjava.util.List;importjava.util.stream.Collectors;public classSMain {public static voidmain(String[] args) {//TODO Auto-generated method stub
List stus =getSources();
stus.stream().collect(groupingBy(ss->{if (ss.getSex() == 0)return "女";else
return "男";
}, Collectors.summingLong(t->t.getScore())))
.forEach((String sex, Long sum)->{
System.out.println("sex:" + sex + " count:" +sum);
});
}
。。。。。
}
运行结果:

通过这俩个例子,我们就可以明白一个道理。groupingBy的第二个参数,是一个任何型类的收集器。也就是说分组之后,你可以在进行对分组之后的结果进处理。
好了。你们有没有感觉跟SQL语句的功能很像呢?如下
stream相关于SQL里面的FROM
filter相当于SQL里面的WHERE.
map相当于SQL里面的SELECT
sorted相当于SQL里面的Order BY
Collectors.groupingBy相当于SQL里面的GROUP BY
Collectors.summingLong相当于SQL里面的SUM函数。只不过他又加了一步结果转为Long类型
Collectors.counting相当于SQL里面的COUNT函数
理解了上面代码的基础用法的概念之后,我们接下要一步步去看看JAVA8流的思想。
本文介绍了Java 8引入的新特性——流(Stream),通过对比.NET的Linq,阐述了流的基本概念和用法。通过实例展示了如何使用filter、map和forEach等方法对数据进行操作,以及如何利用collect进行数据收集。此外,还探讨了sorted、groupingBy等方法在数据排序和分组中的应用,进一步揭示了Java 8流与SQL操作的相似性。文章深入浅出地讲解了流的使用,帮助读者更好地理解和掌握这一强大的新特性。

被折叠的 条评论
为什么被折叠?



