Java8实现:Stream<A>和Stream<B>按照复数个匹配key进行匹配,将匹配成功的Stream<A>和Stream<B>以List<Pair<A,B>>的形式返回。已知Stream<A>和Stream<B>已经按匹配key排好序了,要求减少嵌套循环来提高性能
时间: 2023-12-02 19:05:41 浏览: 178
java8-Stream元素的匹配与查找.pdf
这个问题可以使用 Java 8 中的 Stream API 来实现,具体步骤如下:
1. 定义一个方法,接收两个参数,分别为 Stream<A> 和 Stream<B>:
```
public static <A, B, K extends Comparable<? super K>> List<Pair<A, B>> match(Stream<A> streamA, Stream<B> streamB, Function<A, List<K>> keysA, Function<B, List<K>> keysB) {
// ...
}
```
其中,`K extends Comparable<? super K>` 表示匹配 key 的类型必须是可比较的,`keysA` 和 `keysB` 分别为从 A 和 B 中提取匹配 key 的函数,这里使用 List<K> 的原因是可以支持复数个匹配 key。
2. 将 Stream<A> 和 Stream<B> 转换成 Map<K, List<A>> 和 Map<K, List<B>>,其中 K 为匹配 key 的类型:
```
Map<K, List<A>> mapA = streamA.flatMap(a -> keysA.apply(a).stream().map(k -> new Pair<>(k, a)))
.collect(Collectors.groupingBy(Pair::getKey, LinkedHashMap::new, Collectors.mapping(Pair::getValue, Collectors.toList())));
Map<K, List<B>> mapB = streamB.flatMap(b -> keysB.apply(b).stream().map(k -> new Pair<>(k, b)))
.collect(Collectors.groupingBy(Pair::getKey, LinkedHashMap::new, Collectors.mapping(Pair::getValue, Collectors.toList())));
```
这里使用 `flatMap` 方法将每个 A 和 B 对应的所有匹配 key 转换成 Pair<K, A> 和 Pair<K, B>,然后使用 `groupingBy` 方法对 Stream 进行分组,将具有相同匹配 key 的元素放到一个 List 中,并使用 LinkedHashMap 来保持原有顺序,最后使用 `mapping` 方法将 List<Pair<K, A>> 和 List<Pair<K, B>> 转换成 Map<K, List<A>> 和 Map<K, List<B>>。
3. 遍历 Map<K, List<A>>,对于每一个 key,将 List<A> 和 List<B> 进行匹配,将匹配成功的元素以 List<Pair<A,B>> 的形式返回:
```
List<Pair<A, B>> result = mapA.entrySet().stream()
.flatMap(entry -> {
K key = entry.getKey();
List<A> listA = entry.getValue();
List<B> listB = mapB.get(key);
if (listB == null) {
return Stream.empty();
}
return listA.stream().flatMap(a -> listB.stream().map(b -> new Pair<>(a, b)));
})
.collect(Collectors.toList());
```
这里使用 `flatMap` 方法对 Map 中的每个 entry 进行遍历,如果 mapB 中没有对应的 List<B>,则返回空 Stream;否则,将 List<A> 和 List<B> 进行匹配,将匹配成功的元素以 List<Pair<A,B>> 的形式返回。
完整的代码如下:
```
public static <A, B, K extends Comparable<? super K>> List<Pair<A, B>> match(Stream<A> streamA, Stream<B> streamB, Function<A, List<K>> keysA, Function<B, List<K>> keysB) {
Map<K, List<A>> mapA = streamA.flatMap(a -> keysA.apply(a).stream().map(k -> new Pair<>(k, a)))
.collect(Collectors.groupingBy(Pair::getKey, LinkedHashMap::new, Collectors.mapping(Pair::getValue, Collectors.toList())));
Map<K, List<B>> mapB = streamB.flatMap(b -> keysB.apply(b).stream().map(k -> new Pair<>(k, b)))
.collect(Collectors.groupingBy(Pair::getKey, LinkedHashMap::new, Collectors.mapping(Pair::getValue, Collectors.toList())));
return mapA.entrySet().stream()
.flatMap(entry -> {
K key = entry.getKey();
List<A> listA = entry.getValue();
List<B> listB = mapB.get(key);
if (listB == null) {
return Stream.empty();
}
return listA.stream().flatMap(a -> listB.stream().map(b -> new Pair<>(a, b)));
})
.collect(Collectors.toList());
}
```
注意:这里假设匹配 key 的类型是可比较的,如果不可比较,需要使用自定义的比较器来进行比较。此外,由于使用了 Stream API,代码的可读性和易于维护性得到了很大提升,但是需要注意 Stream 的惰性求值特性,需要在最后调用 collect 方法触发计算。
阅读全文