文章目录
前言
之前,针对Stream
链式编程中的几个方法做了大致的说明。详情可以参考:
但实际业务中,总会存在很多复杂的思维,需要使用到Stream
,此时玩的不熟练总感觉无从下手。
今后开始写几种常用的逻辑方式。
定义数据接收类
因为要考虑使用集合,需要使用到自定义类对象,所以先从定义对象开始。
public class User {
private String name;
private BigDecimal age;
private Integer num;
public User(String name, BigDecimal age) {
this.name = name;
this.age = age;
}
public User(String name, BigDecimal age, Integer num) {
this.name = name;
this.age = age;
this.num = num;
}
// get/set
// toString()
}
定义数据集合
自定义数据集合,模拟数据库查询到的数据信息。
List<User> users = Arrays.asList(
new User("xj1", new BigDecimal(20),3),
new User("xj2", new BigDecimal(3),5),
new User("xj3", new BigDecimal(30),1),
new User("xj4", new BigDecimal(10),4));
数据筛选
这里时模拟数据,采取手动定义,所以数据一定存在
。
如果数据是从数据库中查询,此时这里的
users 集合 可能为 null
当出现null.stream()
时,会出现报错信息!为了保证代码的健壮性,需要对数据信息进行判空。
1、数据集合判空
常见的stream判空有两种。
1.1、Optional.isPresent()
System.out.println("-----> " + Optional.ofNullable(null).isPresent());
System.out.println("-----> " + Optional.ofNullable(new ArrayList<>()).isPresent());
允许结果:
-----> false
-----> true
可以通过Optional.ofNullable(集合别名).isPresent()
判断集合是否存在
,再通过返回 boolean
判断是否继续向下执行链式编程代码。
1.2、orElse 替换
还有一种方式,是如果存在空对象
,则将空对象进行替换操作
。如下所示:
public class Test {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("xj1", null),
new User("xj2", null),
new User("xj3", null),
new User("xj4", null));
System.out.println(Optional.ofNullable(users).orElse(new ArrayList<>()));
System.out.println(Optional.ofNullable(null).orElse(new ArrayList<>()));
}
}
当Optional.ofNullable
判断指定对象为null
时,则会执行orElse(new ArrayList<>())
进行替换,避免出现null.stream()
等NPE
问题。
2、排序 sorted
当将指定的集合转化为stream 流
后,此时就需要针对数据流进行排序
操作。可以采取sorted
实现。
List<User> users = Arrays.asList(
new User("xj1", new BigDecimal(20),3),
new User("xj2", new BigDecimal(3),5),
new User("xj3", null,1),
new User("xj4", new BigDecimal(10),4));
Optional.ofNullable(users)
.orElse(new ArrayList<User>())
.stream()
.sorted(Comparator.comparing(User::getNum)) // 根据编号从小到大排序(默认)
.forEach(e-> System.out.println(e)); // 只是为了打印流
3、数据过滤 filter
既然需要获取到指定的字段数据信息,如果明确要求不取为null的数据,此时则需要排序后的集合数据流进行数据的过滤,排除数据字段为null的数据信息。
List<User> users = Arrays.asList(
new User("xj1", new BigDecimal(20),3),
new User("xj2", new BigDecimal(3),5),
new User("xj3", null,1),
new User("xj4", new BigDecimal(10),4));
Optional.ofNullable(users)
.orElse(new ArrayList<User>())
.stream()
.sorted(Comparator.comparing(User::getNum))
.filter(x->x.getAge()!=null)
.forEach(e-> System.out.println(e)); // 只是为了打印流
4、获取第一个数据 findFirst().get()
通常来说,直接采取.findFirst().get()
,一般是获取到集合中的 元 对象
信息,如下所示:
List<User> users = Arrays.asList(
new User("xj1", new BigDecimal(20),3),
new User("xj2", new BigDecimal(3),5),
new User("xj3", null,1),
new User("xj4", new BigDecimal(10),4));
Optional.ofNullable(users)
.orElse(new ArrayList<User>())
.stream()
.sorted(Comparator.comparing(User::getNum))
.filter(x->x.getAge()!=null)
//.forEach(e-> System.out.println(e)); // 只是为了打印流
.findFirst().get();
System.out.println(user);
如果数据类对象元素很多,只是想单单获取其中的某个列的值,则可以多加一个map
进行映射。
获取指定
元对象
的指定属性
值。
List<User> users = Arrays.asList(
new User("xj1", new BigDecimal(20),3),
new User("xj2", new BigDecimal(3),5),
new User("xj3", null,1),
new User("xj4", new BigDecimal(10),4));
BigDecimal bigDecimal = Optional.ofNullable(users)
.orElse(new ArrayList<User>())
.stream()
.sorted(Comparator.comparing(User::getNum))
.filter(x -> x.getAge() != null)
//.forEach(e-> System.out.println(e)); // 只是为了打印流
.map(User::getAge)
.findFirst()
.get();
System.out.println(bigDecimal);
你以为这样就结束了?
你以为这样就结束了吗?接下来看一个极限栗子:
当你需要获取的列数据全是null,他会返回null吗?
List<User> users = Arrays.asList(
new User("xj1", null,3),
new User("xj2", null,5),
new User("xj3", null,1),
new User("xj4", null,4));
BigDecimal bigDecimal = Optional.ofNullable(users)
.orElse(new ArrayList<User>())
.stream()
.sorted(Comparator.comparing(User::getNum))
.filter(x -> x.getAge() != null)
//.forEach(e-> System.out.println(e)); // 只是为了打印流
.map(User::getAge)
.findFirst()
.get();
System.out.println(bigDecimal);
执行一下,你就会发现新大陆:
解决这个问题,也很简单,把.get()
换成.orElse(BigDecimal.ZERO)
List<User> users = Arrays.asList(
new User("xj1", null,3),
new User("xj2", null,5),
new User("xj3", null,1),
new User("xj4", null,4));
BigDecimal bigDecimal = Optional.ofNullable(users)
.orElse(new ArrayList<User>())
.stream()
.sorted(Comparator.comparing(User::getNum))
.filter(x -> x.getAge() != null)
//.forEach(e-> System.out.println(e)); // 只是为了打印流
.map(User::getAge)
.findFirst()
//.get()
.orElse(BigDecimal.ZERO);
System.out.println(bigDecimal);
2022.10.14扩展
sort()
默认是根据指定的字段进行升序
处理,但在实际业务开发中,往往除了升序可能还需要考虑降序操作。
那么降序又该如何操作?
测试的数据集合:
DmLoanRateTendency dmLoanRateTendency1 = new DmLoanRateTendency();
dmLoanRateTendency1.setEtlDate(DateUtil.parseDate("2022-10-14"));
DmLoanRateTendency dmLoanRateTendency2 = new DmLoanRateTendency();
dmLoanRateTendency2.setEtlDate(DateUtil.parseDate("2022-09-14"));
DmLoanRateTendency dmLoanRateTendency3 = new DmLoanRateTendency();
dmLoanRateTendency3.setEtlDate(null);
DmLoanRateTendency dmLoanRateTendency4 = new DmLoanRateTendency();
dmLoanRateTendency4.setEtlDate(DateUtil.parseDate("2022-08-14"));
List<DmLoanRateTendency> dmLoanRateTendencies = Arrays.asList(dmLoanRateTendency1,
dmLoanRateTendency2, dmLoanRateTendency3,dmLoanRateTendency4);
一般排序输出结果:
Date date = Optional.ofNullable(dmLoanRateTendencies).orElse(new ArrayList<DmLoanRateTendency>())
.stream()
.filter(x->x.getEtlDate()!=null)
.sorted(Comparator.comparing(DmLoanRateTendency::getEtlDate))
.map(DmLoanRateTendency::getEtlDate)
.findFirst().get();
System.out.println(DateUtil.formatDate(date));
2022-08-14
1、使用reversed()排序反转
// sorted 排序中的 Comparator 增加 reversed() 反转,表示降序
// 方式一:先升序排列,再降序
Date date2 = Optional.ofNullable(dmLoanRateTendencies).orElse(new ArrayList<DmLoanRateTendency>())
.stream()
.filter(x->x.getEtlDate()!=null)
.sorted(Comparator.comparing(DmLoanRateTendency::getEtlDate)
.reversed())
.map(DmLoanRateTendency::getEtlDate)
.findFirst().get();
System.out.println(DateUtil.formatDate(date2));
2022-10-14
2、使用Comparator.reverseOrder
// 方式二:Comparator.reverseOrder()
Date date3 = Optional.ofNullable(dmLoanRateTendencies).orElse(new ArrayList<DmLoanRateTendency>())
.stream()
.filter(x->x.getEtlDate()!=null)
.sorted(Comparator.comparing(DmLoanRateTendency::getEtlDate,
Comparator.reverseOrder()))
.map(DmLoanRateTendency::getEtlDate)
.findFirst().get();
System.out.println(DateUtil.formatDate(date3));