Java8写一个共通方法,将两个类型不同且数据量不一致的stream输入按多个字段进行匹配,并返回匹配成功的两个stream输出数据。已知stream输入已按匹配字段排好序,使用了迭代器和循环来避免嵌套循环。
时间: 2023-06-18 13:02:12 浏览: 99
Java8 Stream对两个 List 遍历匹配数据的优化处理操作
3星 · 编辑精心推荐
可以使用Java 8中的Stream API来实现这个共通方法,具体实现如下:
```java
public static <T, R> List<Pair<T, R>> matchStreamsByFields(
Stream<T> stream1, Stream<R> stream2, Function<T, ?>[] matchingFields1, Function<R, ?>[] matchingFields2) {
List<Pair<T, R>> matchedPairs = new ArrayList<>();
Iterator<T> iterator1 = stream1.iterator();
Iterator<R> iterator2 = stream2.iterator();
while (iterator1.hasNext() && iterator2.hasNext()) {
T obj1 = iterator1.next();
R obj2 = iterator2.next();
boolean matched = true;
for (int i = 0; i < matchingFields1.length && matched; i++) {
Object field1 = matchingFields1[i].apply(obj1);
Object field2 = matchingFields2[i].apply(obj2);
matched = Objects.equals(field1, field2);
}
if (matched) {
matchedPairs.add(new Pair<>(obj1, obj2));
} else {
// 如果不匹配则将迭代器向前推进一步
if (compareFields(matchingFields1, obj1, matchingFields2, obj2) < 0) {
iterator2.previous();
} else {
iterator1.previous();
}
}
}
return matchedPairs;
}
// 比较两个对象的指定字段,用于推进迭代器
private static <T, R> int compareFields(Function<T, ?>[] fields1, T obj1, Function<R, ?>[] fields2, R obj2) {
for (int i = 0; i < fields1.length; i++) {
Object field1 = fields1[i].apply(obj1);
Object field2 = fields2[i].apply(obj2);
int cmp = Objects.compare(field1, field2, Comparator.nullsFirst(Comparator.naturalOrder()));
if (cmp != 0) {
return cmp;
}
}
return 0;
}
```
这个方法接受两个不同类型的Stream对象,以及两个数组,每个数组包含了要进行匹配的字段所对应的Function对象。两个Stream对象分别按照匹配字段进行排序,然后使用迭代器和循环来遍历两个Stream,按照匹配字段一一比较,如果全部匹配成功,则将这两个对象封装成一个Pair对象,并添加到结果列表中。如果不匹配,则需要将迭代器向前推进一步,以便继续匹配下一个对象。
注意,在比较两个对象的指定字段时,需要使用`Objects.compare`方法,并使用`Comparator.nullsFirst(Comparator.naturalOrder())`来处理空值的情况。另外,这个方法的返回值是一个包含了匹配成功的Pair对象的列表。你可以根据需要将其转换为其他类型的集合对象。
阅读全文