前言
JDK是Java Development Kit英文首字母大写缩写,是 Sun 公司(已被 Oracle 收购)针对 Java 开发员的软件开发工具包。自从 Java 推出以来,JDK 已经成为使用最广泛的 Java SDK。从JDK8版本开始新增了Stream流式API的功能,该功能特性最大的优势就是能够大大降低代码量和提高可读性。
jdk stream filter的使用
filter是stream api用的最多的功能,它主要作用是可以根据多个条件过滤集合元素数据,下面看个示例:
1、先定义一个测试用的POJO类:
// 定义一个测试用的POJO
@Data
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
2、测试filter代码:
public class StreamDemo {
public static void main(String[] args) {
//测试filter
testFilter();
}
private static void testFilter(){
List<Student> studentList = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
// 过滤后的集合
List<Student> filterAgeStudentList = studentList.stream()
// 过滤年龄小于30岁的
.filter(student -> student.getAge() < 30)
// 过滤年龄大于于20岁的
.filter(student -> student.getAge() > 20)
// 保存到新的集合
.collect(Collectors.toList());
System.out.println(filterAgeStudentList);
}
}
3、控制台输出截图:
jdk stream toMap的使用
1、toMap主要作用是将集合内元素按某个属性转换为Map,示例代码如下:
public class StreamDemo {
public static void main(String[] args) {
testToMap();
}
private static void testToMap() {
List<Student> studentList = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
Student wangwu2 = new Student("wangwu", 50);
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
studentList.add(wangwu2);
Map<String, Student> nameMap = studentList.stream()
// 1、Collectors.toMap(第一个参数表示key, 第二个参数表示val(固定写法), 第三个参数表示重复key的处理策略(可覆盖,可丢弃))
// 2、第三个参数可以不写,如果不写第三个策略参数,如果集合元素中存在重复的key,会报错java.lang.IllegalStateException: Duplicate key
// 3、覆盖策略决定数据去留,如果选择oldKey表示保留先处理的元素,新进来的丢弃,选择newKey则反之
.collect(Collectors.toMap(Student::getName, Function.identity(), (oldKey, newKey) -> oldKey));
System.out.println(nameMap);
}
}
2、控制台输出截图:
3、toMap使用注意事项:
1、Collectors.toMap(第一个参数表示key, 第二个参数表示val(固定写法), 第三个参数表示重复key的处理策略(可覆盖,可丢弃));
2、第三个参数可以不写,如果不写第三个策略参数,如果集合元素中存在重复的key,会报错java.lang.IllegalStateException: Duplicate key,建议第三个参数要写;
3、覆盖策略决定数据去留,如果选择oldKey表示保留先处理的元素,新进来的丢弃,选择newKey则反之;
jdk stream groupBy的使用
1、groupBy的主要作用是将集合内元素按照某个属性相同的值进行分组,类似sql的group by语句,示例代码如下:
public class StreamDemo {
public static void main(String[] args) {
testGroupBy();
}
private static void testGroupBy() {
List<Student> studentList = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
Student wangwu2 = new Student("wangwu", 50);
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
studentList.add(wangwu2);
Map<String, List<Student>> nameMap = studentList.stream()
// 按名称相同的分组
.collect(Collectors.groupingBy(Student::getName));
System.out.println(nameMap);
}
}
2、控制台输出截图:
3、注意返回类型是Map<key, List>结构,可以看到两个名称为wangwu的分组到了一个集合中。
jdk stream map和distinct去重的使用
1、map主要作用是从集合对象元素提取对象某个属性,distinct主要作用是对集合元素进行去重,通过map和distinct是搭配使用的,所以放到一块演示,示例代码如下:
public class StreamDemo {
public static void main(String[] args) {
testMap();
}
private static void testMap() {
List<Student> studentList = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
Student wangwu2 = new Student("wangwu", 50);
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
studentList.add(wangwu2);
List<String> nameList = studentList.stream()
//提取名称
.map(Student::getName)
//可以加上去重的支持
.distinct()
.collect(Collectors.toList());
System.out.println(nameList);
}
}
2、控制台输出截图如下:
3、可以看到wangwu被成功去重,只保留一个。
jdk stream flatmap的使用
1、flatmap主要作用是将集合元素拉平,例如将List<List>嵌套的二维集合拉平为List一维集合,主要作用是拉平降维,代码示例如下:
public class StreamDemo {
public static void main(String[] args) {
testFlatMap();
}
private static void testFlatMap() {
Map<String, List<Student>> studentMap = new HashMap<>();
Student zhangsan1 = new Student("zhangsan", 20);
Student zhangsan2 = new Student("zhangsan", 21);
Student lisi1 = new Student("lisi", 20);
Student lisi2 = new Student("lisi", 21);
Student wangwu1 = new Student("wangwu", 20);
Student wangwu2 = new Student("wangwu", 21);
//
List<Student> lisiList = new ArrayList<>();
List<Student> wangwuList = new ArrayList<>();
List<Student> zhangsanList = new ArrayList<>();
//添加到list
lisiList.add(lisi1);
lisiList.add(lisi2);
wangwuList.add(wangwu1);
wangwuList.add(wangwu2);
zhangsanList.add(zhangsan1);
zhangsanList.add(zhangsan2);
//添加到map
studentMap.put("zhangsan", zhangsanList);
studentMap.put("lisi", lisiList);
studentMap.put("wangwu", wangwuList);
//二维数组
Collection<List<Student>> values = studentMap.values();
//将二维集合转为一维,通过flatMap进行拉平
List<Student> studentList = values.stream().flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(studentList);
}
}
2、控制台输出截图如下:
3、很多人会问flatmap跟map的区别,实际上flatmap跟map作用完全不一样,没什么可比较的,如果一定要说个区别那就是:map输入集合和输出集合元素数量是相同的,map不会改变元素数量,flatmap可以改变输入和输出的元素数量;
jdk stream max/min/count/sum等聚合函数的使用
1、聚合函数主要作用就是对某些维度进行统计,代码示例如下:
public class StreamDemo {
public static void main(String[] args) {
testAggregation();
}
private static void testAggregation() {
List<Student> studentList = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
Student wangwu2 = new Student("wangwu", 50);
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
studentList.add(wangwu2);
//统计年龄总和
int totalAge = studentList.stream().mapToInt(Student::getAge).sum();
//统计名称为wangwu的人数
long wangwuCount = studentList.stream().filter(ele -> "wangwu".equals(ele.getName())).count();
//统计年龄最大的学生
Student ageMaxStudent = studentList.stream().max(Comparator.comparingInt(Student::getAge)).get();
//统计年龄最小的学生
Student ageMinStudent = studentList.stream().min(Comparator.comparingInt(Student::getAge)).get();
//按名称统计不同名称数量
Map<String, Long> groupByName = studentList.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));
System.out.println(String.format("totalAge=%s, wangwuCount=%s, ageMaxStudent=%s, ageMinStudent=%s, groupByName=%s",
totalAge, wangwuCount, ageMaxStudent.getAge(), ageMinStudent.getAge(), groupByName));
}
}
2、控制台输出截图如下:
jdk stream allMatch、anyMatch的使用
1、allMatch、anyMatch主要作用是对集合元素进行整体条件判断,是否全部满足条件、或任意一个满足条件,这两个API也是很常用的,示例代码如下:
public class StreamDemo {
public static void main(String[] args) {
testMatch();
}
private static void testMatch() {
List<Student> studentList = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
Student wangwu2 = new Student("wangwu", 50);
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
studentList.add(wangwu2);
//校验集合每个元素都匹配
boolean allMatch = studentList.stream().allMatch(ele -> "zhangsan".equals(ele.getName()));
//校验集合任意1个元素匹配
boolean anyMatch = studentList.stream().anyMatch(ele -> "zhangsan".equals(ele.getName()));
System.out.println(String.format("allMatch=%s, anyMatch=%s", allMatch, anyMatch));
}
}
2、控制台输出截图如下:
jdk stream concat的使用
1、concat作用主要是将两个集合合并后进行一次性流式处理,示例代码如下:
public class StreamDemo {
public static void main(String[] args) {
testConcat();
}
private static void testConcat() {
//集合1
List<Student> studentList1 = new ArrayList<>();
Student zhangsan = new Student("zhangsan", 20);
Student lisi = new Student("lisi", 25);
Student wangwu = new Student("wangwu", 40);
Student wangwu2 = new Student("wangwu", 50);
studentList1.add(zhangsan);
studentList1.add(lisi);
//集合2
List<Student> studentList2 = new ArrayList<>();
studentList2.add(wangwu);
studentList2.add(wangwu2);
//两个集合的流
Stream<Student> stream1 = studentList1.stream();
Stream<Student> stream2 = studentList2.stream();
//将两个集合流合并一起
Stream<Student> concatStream = Stream.concat(stream1, stream2);
//合并后遍历
concatStream.forEach(System.out::println);
}
}
2、控制台输出截图如下:
---------- 正文结束 ----------
长按扫码关注微信公众号
Java软件编程之家