flatMap()
flatMap 是 Stream API 中的一个中间操作方法,它用于将多个 Stream 合并为一个 Stream。该方法接受一个函数作为参数,这个函数将每个元素转换为一个新的 Stream,然后将所有新 Stream 合并为一个结果 Stream。
方法签名如下:
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
其中:
T是原始 Stream 的元素类型。R是新 Stream 的元素类型。mapper是一个函数,它将每个元素T转换为一个新的 Stream,这个函数的返回类型是Stream<? extends R>。
flatMap 方法的工作原理如下:
- 对于原始 Stream 中的每个元素,应用
mapper函数将其转换为一个新的 Stream。 - 将所有新的 Stream 合并为一个结果 Stream。
- 最终返回合并后的结果 Stream。
一般来说,flatMap 方法用于处理具有嵌套结构的数据。例如,一个 List 中包含了多个子列表,你可以使用 flatMap 方法将这些子列表合并为一个扁平化的 Stream。
示例:
假设有一个 List 包含多个子列表:
List<List<Integer>> listOfLists = List.of(
List.of(1, 2, 3),
List.of(4, 5),
List.of(6, 7, 8, 9)
);
你可以使用 flatMap 方法将这些子列表合并为一个扁平化的 Stream:
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<List<Integer>> listOfLists = List.of(
List.of(1, 2, 3),
List.of(4, 5),
List.of(6, 7, 8, 9)
);
List<Integer> flattenedList = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(flattenedList); // 输出结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
在上述代码中,我们使用 flatMap 方法将 listOfLists 中的多个子列表转换为一个扁平化的 Stream。最终,通过 collect 方法将结果收集到一个 List<Integer> 中。输出结果是一个扁平化的列表,包含了所有原始子列表中的元素。
总结:
flatMap 方法是 Stream API 中用于合并多个 Stream 的重要方法。它在处理嵌套结构的数据时非常有用,可以将多个子集合并为一个扁平化的 Stream,简化数据处理过程。
示例:
提示
需求:有一个多个房间的账单汇总List,一个对象为一个房间,每个房间里又有一个账单明细List,现在需要将所有明细扁平化为一个List,要求首先依据房间名称正序排列,然后每个房间里的账单明细由endDate正序排序:
// 查询到账单汇总表并将结果集依据房间名称正序排列
List<CaTalentApartmentContractBill> billList = billDao.findList(whereBillEntity)
.stream().sorted(Comparator.comparing(CaTalentApartmentContractBill::getRoomName))
.collect(Collectors.toList());
// 每个房间根据计租截止日期正序排列之后,返回为一个List
final List<CaTalentApartmentContractBillDetails> billDetailsList = billList
.stream()
.flatMap(bill -> bill
.getTalentApartmentContractBillDetailsList()
.stream()
.sorted(Comparator.comparing(CaTalentApartmentContractBillDetails::getEndDate))
)
.collect(Collectors.toList());
flatMap及Stream.of()、Stream.concat()的用法
List<Student> stuList = new ArrayList<>();
stuList.add(new Student("101", "Alice"));
stuList.add(new Student("102", "Bob"));
stuList.add(new Student("103", "John"));
/**
* 需求: Student里有很多属性,但我只需要其中的两个String类型的属性,将这两个属性放到一个Set<String>集合里
* 1.
* Stream.of() 方法是 java.util.stream.Stream 类中的一个静态方法,
* 它用于创建一个由指定元素构成的 Stream。该方法允许你在不依赖任何集合的情况下,
* 直接将指定的元素作为 Stream 进行处理。
* 2.
* 使用 Stream.concat() 方法来合并两个 Stream,而不是使用 Stream.of()。
* 这样,我们就可以把 name 和 rollNumber 分别作为两个不同的元素传入,然后将它们合并为一个 Stream。
*/
Set<String> nameAndRollNumberSet = stuList.stream()
.flatMap(student -> Stream.of(student.getStuId(), student.getStuName()))
.collect(Collectors.toSet());
Set<String> nameAndRollNumberSet2 = stuList.stream()
.flatMap(student -> Stream.concat(
Stream.of(student.getStuId()),
Stream.of(student.getStuName())))
.collect(Collectors.toSet());
// 输出结果
nameAndRollNumberSet.forEach(System.out::println);
System.out.println("----------------------------------");
nameAndRollNumberSet2.forEach(System.out::println);
flatMapToInt/ToLong/ToDouble
flatMapToInt, flatMapToLong, 和 flatMapToDouble 是 Stream API 中的特殊版本的 flatMap 方法。它们分别用于处理基本数据类型的 Stream(IntStream、LongStream 和 DoubleStream)。这些方法将 Stream 中的每个元素映射为一个基本数据类型的 Stream,然后将这些基本数据类型的 Stream 合并为一个结果 Stream。
这三个方法的工作原理类似于普通的 flatMap 方法,只不过它们处理的是基本数据类型而不是对象。由于它们返回的是基本数据类型的 Stream,因此在合并和处理过程中,避免了装箱和拆箱的开销,提高了性能。
以下是这三个方法的签名:
flatMapToInt方法:
IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper)
flatMapToLong方法:
LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper)
flatMapToDouble方法:
DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper)
其中,T 是原始 Stream 的元素类型。
示例:
假设有一个 List 包含多个字符串,每个字符串是由逗号分隔的整数序列:
List<String> listOfStrings = List.of("1,2,3", "4,5", "6,7,8,9");
你可以使用 flatMapToInt 方法将每个字符串转换为一个 IntStream,然后将所有 IntStream 合并为一个结果 IntStream:
import java.util.List;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
List<String> listOfStrings = List.of("1,2,3", "4,5", "6,7,8,9");
IntStream flattenedIntStream = listOfStrings.stream()
.flatMapToInt(s -> {
String[] numbers = s.split(",");
return IntStream.of(numbers)
.mapToInt(Integer::parseInt);
});
flattenedIntStream.forEach(System.out::println); // 输出结果:1 2 3 4 5 6 7 8 9
}
}
在上述代码中,我们使用 flatMapToInt 方法将 listOfStrings 中的每个字符串转换为一个 IntStream,然后通过 flatMapToInt 的结果 IntStream 将所有字符串中的整数合并为一个结果 IntStream。最终,通过 forEach 方法输出结果。
类似地,你可以使用 flatMapToLong 和 flatMapToDouble 方法来处理 LongStream 和 DoubleStream。
总结:
flatMapToInt, flatMapToLong, 和 flatMapToDouble 是 Stream API 中用于处理基本数据类型的 Stream 的特殊版本的 flatMap 方法。它们将多个基本数据类型的 Stream 合并为一个结果 Stream,避免了装箱和拆箱的开销,提高了性能。
排序
List里Date降序
// 对日期进行降序排序
List<MyObject> sortedList = list.stream()
.sorted(Comparator.comparing(MyObject::getDate).reversed())
.collect(Collectors.toList());
List只取日期最大的一个
- 1
final CaShopContractBillSettlement lastBill = billDao
.findList(whereShopContractBill)
.stream()
.max(Comparator.comparing(CaShopContractBillSettlement::getEndDate))
.orElse(null);
这段代码的作用是从数据库中查询一组符合条件的 CaShopContractBillSettlement 对象,然后通过流式操作找到具有最大结束日期(endDate)的对象。
让我解释一下每一步的含义:
billDao.findList(whereShopContractBill): 这是一个数据库查询操作,它使用billDao对象(可能是一个 DAO 或 Repository)调用findList方法,传入一个查询条件whereShopContractBill,返回了一组满足条件的CaShopContractBillSettlement对象。.stream(): 这将查询结果转换为一个流(Stream),使你可以使用流式操作对查询结果进行处理。.max(Comparator.comparing(CaShopContractBillSettlement::getEndDate)): 这一步使用流的max方法找到具有最大endDate的对象。Comparator.comparing(CaShopContractBillSettlement::getEndDate)创建了一个比较器,它根据endDate属性进行比较。然后,max方法根据这个比较器找到最大的对象。.orElse(null): 如果找到了最大的对象,则返回该对象;如果没有找到,则返回null。
所以,整个代码的目的是查询一组对象,并找到其中具有最大结束日期的对象。最后,如果找到了最大的对象,就返回该对象,否则返回 null。
- 2 对日期筛选之后进行取EndDate最大的一条
final CaShopContractBillSettlement lastBill = billSettlementDao
.findList(whereShopContractBill)
.stream()
.filter(bill -> !mainId.equals(bill.getReletId()))
.max(Comparator.comparing(CaShopContractBillSettlement::getEndDate))
.orElse(null);
分组
groupingBy
List<Long> amountList = xxx;
// 大于0的 总和一下输出Long
Long positiveAmount = amountList.stream().filter(amount -> amount.compareTo(0L) > 0).reduce(Long::sum).orElse(0L);
