现象:
Lambda表达式简单使用
stream 使用场景
方法:
一. 不需要参数,直接返回值
() -> 1
二. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
三. 接受2个参数(数字),并返回他们的加值
(x, y) -> x +y
四. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
方法:
一:循环list设置值
userList.stream().peek(user -> {
user.setName("name");
user.setAge(11);
}).collect(Collectors.toList());
二:通过filter方法过滤list某些条件
过滤list
List<User> userCommonList = userList.stream().filter(a -> !a.getName().equals("zhangsan")).collect(Collectors.toList());
三:通过groupingBy可以指定字段分组list
根据sex参数分组list 使用set作为map的key
Map<String, List<User>> groupBySex = userList.stream().collect(Collectors.groupingBy(User::getSex));
Map<String, List<String>> = collect.stream().collect(Collectors.toMap(ActivationCodeRecord::getAgentId,each->Collections.singletonList(each.getUserOrderId()),(value1, value2) -> {
List<String> union = new ArrayList<>(value1);
union.addAll(value2);
return union;
}));
四:获取list某个字段组装新list
使用id组成一个新的list
List<String> userIdList = userList.stream().map(a -> a.getId()).collect(Collectors.toList());
使用id组成新list转字符串,分割
String userIdStr = userList.stream().map(a -> a.getId()).collect(Collectors.joining(","));
五:list某个字段简单求和
// 基础求和:
int sumAge = userList.stream().mapToInt(User::getAge).sum();
BigDecimal求和:
var count =
coupons.stream()
.map(Coupon::getDisCount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 子集合求数量总和
var options = list.stream()
.mapToInt(option ->
option .getChild().size()
).sum();
// 子集合字段求和
Integer sum = list.stream()
.map(User::getContent)
.flatMap(Collection::stream)
.map(UserChild::getCourseNumber)
.reduce(0, Integer::sum);
// 对象多字段操作求和
var totoalPrice =
commodities.stream()
.reduce(
BigDecimal.ZERO,
(x, y) ->
x.add(
(y.getLinePrice() == null
? BigDecimal.ZERO
: y.getLinePrice())
.multiply(
y.getNumber() == null
? BigDecimal.ZERO
: BigDecimal.valueOf(
y.getNumber()))),
BigDecimal::add);
六:list求最大值最小值
// 最小
Date minEntryDate = userList.stream().map(User::getEntryDate).min(Date::compareTo).get();
// 最大
Date maxEntryDate = userList.stream().map(User::getEntryDate).max(Date::compareTo).get();
// BigDecimal
var min = list.stream().map(User::getPrice).reduce(list.get(0).getPrice(),BigDecimal::min);
七:根据某个字段排序
单字段
userList.sort(Comparator.comparing(User::getId));
多字段排序,根据id,年龄排序
userList.sort(Comparator.comparing(User::getId).thenComparing(User::getAge));
八:list去重
可通过distinct方法进行去重
List<String> userList = new ArrayList<String>();
userList .add("1");
userList .add(“2”);
userList .add(“3”);
List<String> distinctIdList = userList .stream().distinct().collect(Collectors.toList());
-- 根据对象 一个值去重
return users.stream() .filter(distinctById(c-> c.getId()))
-- 去重复方法
private <T> Predicate<T> distinctById(Function<?super T,?> idExtractor){
var objectObjectHashMap = new HashMap<String,Boolean>();
return t -> objectObjectHashMap.putIfAbsent(idExtractor.apply(t).toString(),true)==null;
}
九:批量设置list列表字段为同一个值
userList.stream().forEach(a -> a.setAge(12));
十:List 转map
Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, a -> a,(k1,k2)->k1));
Map<String, String> userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getName);
十一:判断list是否包含某元素
boolean bool = userList.stream().anyMatch(a -> a.getName().equals(“张三”));
十二:判断两个list 哪些元素是新增的
List<Object> addCollect = nowLists.stream().filter(item -> (oldLists.parallelStream().noneMatch(old -> item.equals(old.toString())))).collect(Collectors.toList());
十三:判断两个list 哪些元素删除了
LinkedList<Object> deleteCollect = oldLists.stream().filter(old -> (nowLists.parallelStream().noneMatch(now -> now.equals(old.toString()))))
.collect(Collectors.toCollection(LinkedList::new));
十四:获取集合第一个
nowLists.stream().findFirst().ifPresent(detail -> System.out.println(detail));
十五:获取元素最后一个
List<String> list=List.of("1","22","333","444");
var result = list.stream().reduce((first, second) -> second).orElse(null);
十六:双重list转一层list
1:双重list转一层list
list.stream()
.flatMap(
l1 ->
l1.childrens().stream()
.map(
l2 ->
new MessageTemplateVO(
l1.getName(),
l1.getValue(),
l2.getName(),
l2.getAge(),
l2.getContent())))
.collect(Collectors.toList());
2:List<List<String>> 返回 List<String>:
var list1 = List.of("1", "2", "3");
var list2 = List.of("4", "5", "6");
List<List<String>> collect=new ArrayList<List<String>>();
collect.add(list1);
collect.add(list2);
System.out.println(collect);
var collect1 = collect.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(collect1);
十七:分割集合
/**
* 根据数量分割集合
* @param list 需要分割的集合
* @param splitSize 分割的大小
* @param <T>
* @return
*/
public static <T> List<List<T>> splitList(List<T> list, int splitSize) {
//判断集合是否为空
if (CollectionUtils.isEmpty(list)){
return Collections.emptyList();
}
//计算分割后的大小
int maxSize = (list.size() + splitSize - 1) / splitSize;
//开始分割
return Stream.iterate(0, n -> n + 1)
.limit(maxSize)
.parallel()
.map(a -> list.parallelStream().skip((long) a * splitSize).limit(splitSize).collect(Collectors.toList()))
.filter(b -> !b.isEmpty())
.collect(Collectors.toList());
}
创建流(Creating Streams)
从集合创建:
Collection.stream() 或 Collection.parallelStream()
Arrays.stream(T[])
Stream.of(…):接受可变数量的参数,创建包含这些参数的流。
Stream.empty():创建一个空流。
文件和IO操作:
Files.lines(Path, Charset):读取文件为行的流。
BufferedReader.lines():从BufferedReader中读取行的流。
数值范围:
IntStream.range(int startInclusive, int endExclusive)
IntStream.rangeClosed(int startInclusive, int endInclusive)
同样的方法还有 LongStream 和 DoubleStream。
中间操作(Intermediate Operations)
中间操作不会立即执行任何处理,而是返回一个新的流,该流在后续操作(如终端操作)中使用。中间操作是无副作用的,且可以链接在一起形成流水线。常见的中间操作包括:
筛选(Filtering):
filter(Predicate): 保留满足给定谓词的元素。
映射(Mapping):
map(Function<T, R>): 将每个元素应用给定函数,产生新的流,其中包含函数返回的结果。
flatMap(Function<T, Stream>): 将每个元素转换为一个流,然后将所有流连接成为一个流。
排序(Sorting):
sorted(): 自然排序(如果元素类型实现了Comparable接口)。
sorted(Comparator): 使用提供的比较器排序。
切片(Slicing):
limit(long maxSize): 截取前n个元素。
skip(long n): 跳过前n个元素。
** distinct()**: 去除重复元素。
其他:
peek(Consumer<? super T>): 用于调试,允许在流的每个元素上应用一个操作,但不会影响流的最终结果。
终端操作(Terminal Operations)
终端操作会导致流的实际计算发生,并产生一个结果或副作用。执行终端操作后,流就被使用完毕,不能再进行其他操作。常见的终端操作包括:
聚合(Reducing):
reduce(BinaryOperator): 通过二元操作符将流中的元素累积为一个单一结果。
collect(Collector<T, ?, R>): 收集流到一个结果容器中,如列表、集合、映射或其他复杂数据结构。
查找与匹配(Finding and Matching):
anyMatch(Predicate), allMatch(Predicate), noneMatch(Predicate): 检查流中是否存在至少一个、全部或没有元素满足给定谓词。
findFirst(), findAny(): 返回流中的第一个或任意一个元素(对于并行流有意义)。
count(): 计算流中元素的数量。
max(Comparator), min(Comparator): 返回流中最大或最小元素。
遍历(Iteration):
forEach(Consumer<? super T>): 对流中的每个元素应用给定的消费型函数。
归约到一个值(Reducing to a single value):
sum(), average(), summaryStatistics(), etc.: 仅适用于数值流,计算流中元素的总和、平均值、统计摘要等。
其他:
toArray(): 将流转换为数组。
短路操作(Short-circuiting Operations)
一些终端操作(如 findFirst()、anyMatch() 等)在找到足够的元素满足条件时就会停止处理流,这种特性称为短路。短路操作有助于提高效率,特别是在处理无限流或非常大的流时。
以上就是Java Stream API 中主要的方法分类。实际使用时,可以根据需要组合这些方法来实现高效、简洁的流式编程