Java8 List,Map的lambda 语法糖
1.list的循环
list使用前要进行非null判断
List<UserAccount> list = new ArrayList<>();
//普通循环-优点:可以知道当前循环的i的值
for(int i=0; i<list.size(); i++){
System.out.println(user.getId());
}
//增强for循环
for(UserAccount user:list){
System.out.println(user.getId());
}
//forEach循环list
list.forEach((UserAccount user) -> {
System.out.println(user.getId());
System.out.println(user.getUserName());
});
//forEach只有一行代码时 大括号可以省略,使代码更简洁
list.forEach((UserAccount user) -> System.out.println(user.getId()));
//再进行简写
list.forEach(user -> System.out.println(user.getId()));
2.List<Integer> 排序
List<Integer> list = Arrays.asList(1, 2, 3, 9, 11, 6);
//修改原来的list
//正序
list.sort(Comparator.naturalOrder());
//倒序
list.sort(Comparator.reverseOrder());
//如果不想改变原来的list,返回一个新的list可以使用
//正序
List<Integer> collect = list.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
//倒序
List<Integer> collect = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
3.list 对象 属性排序
List<UserAccount> list = new ArrayList<>();
//修改原来的list
//正序
list.sort(Comparator.comparing(UserAccount::getId));
//倒序
list.sort(Comparator.comparing(UserAccount::getId).reversed());
//如果不想改变原来的list可以使用下面的方法
//正序流操作-根据用户的id排序
List<UserAccount> collect = list.stream().sorted(Comparator.comparing(UserAccount::getId)).collect(Collectors.toList());
//倒序流操作-根据时间倒序
List<UserAccount> collect1 = list.stream().sorted((p1, p2) -> p2.getAddTime().compareTo(p1.getAddTime())).collect(Collectors.toList());
//排序并得到最大id的对象 ⚠️集合为空调用get()抛异常
UserAccount user = list.stream().max(Comparator.comparing(UserAccount::getId)).orElseThrow(()->new RuntimeException("集合为空"));
//排序并得到最小id的对象
UserAccount user2 = list.stream().min(Comparator.comparing(UserAccount::getId)).orElseThrow(()->new RuntimeException("集合为空"));
4.list 对象 根据对象属性过滤
//过滤 list中 用户邮箱为111的用户
List<UserAccount> lis = list.stream().filter(user -> user.getEmail().equals("111")).collect(Collectors.toList());
//返回符合表达式的集合的第一个对象
Optional<UserAccount> first = list.stream().filter(user -> user.getEmail().equals("111")).findFirst();
//判断是否有符合条件的值,然后在进行操作
first.ifPresent(a-> System.out.println(a));
5.list对象 根据对象的某个属性生成一个新的list
//获取邮箱字段集合
List<String> list = list.stream().map(UserAccount::getEmail).collect(Collectors.toList());
6.分组,和排序
//根据id分组
final Map<Integer, List<UserAccount>> collect = list.stream().collect(Collectors.groupingBy(UserAccount::getId));
//分组并根据key 排序
TreeMap<Integer, List<Order>> treeMap = subOrders.stream().collect(Collectors.groupingBy(Order::getRefId, TreeMap::new, Collectors.toList()));
//如果需要倒序
NavigableMap<Integer, List<Order>> integerListNavigableMap = subOrders.stream().collect(Collectors.groupingBy(Order::getRefId, TreeMap::new, Collectors.toList())).descendingMap();
//分组统计每个部门人数
Map<Integer, Long> deptCountMap = userList.stream()
.collect(Collectors.groupingBy(UserAccount::getDeptId, Collectors.counting()));
//分组,拿到每个部门最大年龄用户
Map<Integer, Optional<UserAccount>> maxAgeMap = userList.stream()
.collect(Collectors.groupingBy(UserAccount::getDeptId,
Collectors.maxBy(Comparator.comparingInt(UserAccount::getAge))));
// key:部门id value:该部门所有用户name集合
Map<Integer, List<String>> deptNameMap = userList.stream()
.collect(Collectors.groupingBy(
UserAccount::getDeptId,
Collectors.mapping(UserAccount::getUserName, Collectors.toList())
));
//groupingBy 默认 HashMap;可以指定容器,TreeMap 有序、LinkedHashMap 保序
7.list 转 map
//map 的key 和value 都是属性值
Map<String, String> map = list.stream().collect(Collectors.toMap(UserAccount::getId, UserAccount::getUserName));
//key为属性 value为对象本身
Map<String, UserAccount> map = userList.stream().collect(Collectors.toMap(UserAccount::getId, t->t));
//或
Map<String, UserAccount> map = userList.stream().collect(Collectors.toMap(UserAccount::getId, Function.identity()));
//如果在转换的过程中, list对象的属性作为map的key时有重复 会报错,java.lang.IllegalStateException: Duplicate key
//可以用下面的方法解决
//1.字符串value拼接
Map<String, String> map = list.stream().collect(Collectors.toMap(UserAccount::getId, UserAccount::getUserName, (old,newK)->old+","+newK));
//或取新值或老值(对象场景使用)
Map<String, String> map2 = list.stream().collect(Collectors.toMap(UserAccount::getId, UserAccount::getUserName, (old,newK)->newK));
Map<String, UserAccount> map3 = list.stream().collect(Collectors.toMap(UserAccount::getId, t->t, (old, newK)->newK));
//还可以排序 这里根据key排序 注意这里的返回值不同
TreeMap<String, UserAccount> collect = list.stream().collect(Collectors.toMap(UserAccount::getId, t->t, (old, newK)->newK, TreeMap::new));
8.map 转list
//key list
Map<String, UserAccount> map = new HashMap<>();
List<String> strings = new ArrayList<>(map.keySet());
//value对象list
Map<String, UserAccount> map = new HashMap<>();
List<UserAccount> list = map.entrySet().stream().map(e -> e.getValue()).collect(Collectors.toList());
9.匹配计算:
// 是否存在任意一条满足条件
boolean hasAdult = userList.stream().anyMatch(u -> u.getAge() >= 18);
// 是否全部满足条件
boolean allAdult = userList.stream().allMatch(u -> u.getAge() >= 18);
// 是否全部不满足
boolean noneAdult = userList.stream().noneMatch(u -> u.getAge() >= 18);
//不仅仅求和,一次性拿到 总数、总和、最大、最小、平均值。
IntSummaryStatistics stat = userList.stream()
.mapToInt(UserAccount::getAge)
.summaryStatistics();
long count = stat.getCount();
int maxAge = stat.getMax();
int minAge = stat.getMin();
double avg = stat.getAverage();
int sumAge = stat.getSum();
// 嵌套集合扁平化
List<Order> orderList = new ArrayList<>();
List<OrderItem> allItemList = orderList.stream()
.flatMap(order -> order.getItemList().stream())
.collect(Collectors.toList());
10.distinct 去重 + 自定义对象去重
// 基础类型直接去重
list.stream().distinct().collect(Collectors.toList());
// 对象按id去重(业务常用写法)⚠️不支持并行流,Predicate对象不可复用给多个stream
List<UserAccount> distinctUser = userList.stream()
.filter(distinctByKey(UserAccount::getId))
.collect(Collectors.toList());
// 工具方法
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
11.partitioningBy 分区(按布尔条件分成两组)
Map<Boolean, List<UserAccount>> partMap = userList.stream()
.collect(Collectors.partitioningBy(u -> u.getAge() >= 18));
List<UserAccount> adult = partMap.get(true);
List<UserAccount> child = partMap.get(false);
12.joining 字符串拼接
String nameStr = userList.stream()
.map(UserAccount::getUserName)
.collect(Collectors.joining(",", "[", "]"));
//输出:[张三,李四,王五]
13. peek 调试 / 中间消费(debug 打印日志)
//peek仅调试打印,不能修改外部变量,中间操作,没有终端操作不会执行
List<UserAccount> result = userList.stream()
.filter(u -> u.getAge()>10)
.peek(u -> System.out.println("过滤后:"+u.getUserName()))
.collect(Collectors.toList());
14.Optional完整用法,解决NPE坑
Optional<UserAccount> opt = userList.stream().filter(u->u.getAge()>10).findFirst();
//1.存在才执行
opt.ifPresent(user -> System.out.println(user.getUserName()));
//2.为空给默认值
UserAccount user = opt.orElse(new UserAccount());
//3.为空动态生成对象,orElseGet 只有空才new对象,性能优于orElse
UserAccount user2 = opt.orElseGet(UserAccount::new);
//4.为空抛异常(业务校验非常常用)
UserAccount user3 = opt.orElseThrow(() -> new RuntimeException("用户不存在"));
//5.optional继续map转换
opt.map(UserAccount::getUserName).ifPresent(System.out::println);
// ❌不推荐直接 opt.get(),空直接抛NoSuchElementException
15.Map原生lambda方法,无需转stream
Map<String,Integer> map = new HashMap<>();
//遍历map
map.forEach((k,v)-> System.out.println(k + ":" + v));
//key不存在才put
map.putIfAbsent("a",100);
//获取key,不存在返回默认值
Integer val = map.getOrDefault("a",0);
//缓存场景高频,key不存在执行函数生成value
map.computeIfAbsent("key", k -> buildValue(k));
⚠️生产环境避坑总结
- 集合为null直接调用stream()会NPE;安全写法:
List<UserAccount> safeList = Optional.ofNullable(list).orElse(Collections.emptyList()); - Collectors.toMap key重复直接抛异常,必须提供合并函数。
- 不要直接调用Optional.get(),空集合抛出异常;优先orElse / orElseThrow。
- stream中间操作(filter/map/peek)是懒加载,没有终端操作代码不会执行。
- Collectors.toList() jdk8返回可变ArrayList,可以add/remove;需要不可变集合使用collectingAndThen包装。
- parallelStream并行流谨慎使用,不要操作非线程安全集合,会产生数据错乱。
- findFirst保证有序流第一条;findAny适合不关心顺序场景,并行流性能更好。
待续....

浙公网安备 33010602011771号