本文介绍 java8 lambda表达式的技巧
NPE 的处理
入参判空
空引用空指针是无数个错误的来源
1 2 3 4 5 6 7
| @Test public void test2() { DogDO dogDO = getDog(); if (dogDO != null) { System.out.println(dogDO.getName() + ", " + dogDO.getAge()); } }
|
使用 Optional 是这样写的:
1 2 3 4 5
| @Test public void test3() { DogDO dogDO = getDog(); Optional.ofNullable(dogDO).ifPresent(d -> System.out.println(d.getName() + ", " + d.getAge())); }
|
函数返回值非空
普通的写法
1 2 3 4 5 6 7
| public DogDO playWithDog() { DogDO d = ...; if (d != null) { return d; } return new DogDO(); }
|
我们的函数返回时,保证不返回空,可以使用 orElse 与 orElseGet
对象做默认值用 orElse,方法返回值做默认值用 orElseGet
如下,确实简洁了很多
1 2 3 4 5
| public DogDO playWithDog() { DogDO d = ...; return Optional.ofNullable(d).orElse(new DogDO()); }
|
对应的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } public static <T> Optional<T> of(T value) { return new Optional<>(value); } public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } public T orElse(T other) { return value != null ? value : other; } public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get(); }
|
集合处理
将A类型集合转为B类型集合
下面是集合中的对象:DO 狗和 DTO 狗
1 2 3 4 5 6 7 8 9 10
| @Data public class DogDO { private String name; private Integer age; } @Data public class DogDTO { private String name; private Integer age; }
|
现在要对一个 DogDO 列表,将符合条件的拿出来,转为 DogDTO
列表,一般的写法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| /** * 将 dogDOList 转为 DogDTOList */ public List<DogDTO> convert(List<DogDO> dogDOList) { List<DogDTO> dogDTOList = new ArrayList<>(); if (CollectionUtils.isEmpty(dogDOList)) { return dogDTOList; } for (DogDO dogDO : dogDOList) { // 去掉空狗和未成年狗 if (dogDO == null || dogDO.getAge() < 18) { continue; } DogDTO dogDTO = new DogDTO(); dogDTO.setName(dogDO.getName()); dogDTO.setAge(dogDO.getAge()); dogDTOList.add(dogDTO); } return dogDTOList; }
|
使用 lambda 表达式可改为:
1 2 3 4 5 6 7 8
| public List<DogDTO> convert(List<DogDO> dogDOList) { return Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream().filter(Objects::nonNull).filter(d->d.getAge() > 18).map(e -> { DogDTO dogDTO = new DogDTO(); dogDTO.setName(e.getName()); dogDTO.setAge(e.getAge()); return dogDTO; }).collect(Collectors.toList()); }
|
提取单个属性
和上面的转换是一样的,只不过 map 中
是类型转换还是直接返回某个属性值
要从狗集合中抽出狗昵称,普通的写法是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public List<String> getNamesFromDogs(List<DogDO> dogDOList) { List<String> names = new ArrayList<>(); if (dogDOList == null || dogDOList.isEmpty()non) { return names; } for (DogDO dogDO : dogDOList) { if (dogDO == null) { continue; } names.add(dogDO.getName); } return names; }
|
Lambda 写法
1 2 3 4 5
| public List<String> getNamesFromDogs(List<DogDO> dogDOList) { return Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream(). filter(Objects::nonNull).map(DogDO::getName).collect(Collectors.toList()); }
|
可以看出用 lambda
表达式确实很简洁,逻辑上虽然没有普通写法那么清晰,不过习惯了还好
集合类型的转换
List 转 Map
列表转属性-对象的字典
现将一个狗列表转为 {id: 狗对象} 的字典,正常的写法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public Map<Integer, DogDO> convertDogListToMap(List<DogDO> dogDOList) { Map<Integer, DogDO> dogDOMap = new HashMap<>(); if (dogDOList == null || dogDOList.isEmpty()) { return dogDOMap; } for (DogDO dogDO : dogDOList) { if (dogDO == null) { continue; } if (dogDOMap.containsKey(dogDO.getId())) { continue; } dogDOMap.put(dogDO.getId(), dogDO); } return dogDOMap; }
|
使用 lambda 的写法
1 2 3
| public Map<Integer, DogDO> convertDogListToMap(List<DogDO> dogDOList) { return Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream().filter(Objects::nonNull).collect(Collectors.toMap(DogDO::getId, v -> v, (p1, p2) -> p1)); }
|
列表转属性-属性的字典
正常写法略,lambda写法如下
1 2 3 4
| public Map<Integer, String> convertDogListToMap(List<DogDO> dogDOList) { return Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream().filter(Objects::nonNull).collect(Collectors.toMap(DogDO::getId, DogDO::getName, (p1, p2) -> p1)); }
|
Set 转 Map 的过程同上
列表分组转字典
分成两组
现要按照是否大于18岁把狗子分成两组,正常的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public Map<Boolean, List<DogDO>> groupByAge(List<DogDO> dogDOList) { Map<Boolean, List<DogDO>> map = new HashMap<>(); map.put(true, new ArrayList<>()); map.put(false, new ArrayList<>()); if (dogDOList == null || dogDOList.isEmpty()) { return map; } for (DogDO dogDO : dogDOList) { if (dogDO == null) { continue; } map.get(dogDO.getAge() > 18).add(dogDO); } return map; }
|
Lambda 写法
1 2 3 4
| public Map<Boolean, List<DogDO>> groupByAge1(List<DogDO> dogDOList) { return Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream(). filter(Objects::nonNull).collect(Collectors.partitioningBy(p -> p.getAge() > 18)); }
|
分成多组
现要将狗列表按照毛色分成若干组,正常写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public Map<String, List<DogDO>> groupByColor(List<DogDO> dogDOList) { Map<String, List<DogDO>> map = new HashMap<>(); if (dogDOList == null || dogDOList.isEmpty()) { return map; } for (DogDO dogDO : dogDOList) { if (dogDO == null) { continue; } if (!map.containsKey(dogDO.getColor())) { map.put(dogDO.getColor(), new ArrayList<>()); } map.get(dogDO.getColor()).add(dogDO); } return map; }
|
Lambda 写法
1 2 3
| public Map<String, List<DogDO>> groupByColor1(List<DogDO> dogDOList) { return Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream().filter(Objects::nonNull).collect(Collectors.groupingBy(DogDO::getColor)); }
|
聚合查询
取集合中年龄最大的两只狗
1 2
| List<DogDO> top2Dogs = Optional.ofNullable(dogDOList).orElse(Collections.emptyList()).stream().filter(Objects::nonNull) .sorted(Comparator.comparingInt(DogDO::getAge)).limit(2).collect(Collectors.toList());
|
更多聚合查询见:Java8之22个lambda表达式用法入门示例超简单,这还不会你就out了
参考
JAVA8之妙用Optional解决判断Null为空的问题
干货,一文彻底搞懂
Java 的 Optional
Java8之22个lambda表达式用法入门示例超简单,这还不会你就out了
Java 中的 Lambda
List 转 Map 的多种方法详解