通过索引比较两个列表的流



我有2个不同的列表:List1List2,我想对每个索引执行一个操作,其中元素具有相同的getName()值:

for (int i = 0; i < 5; i++) { 
if (list1.get(i).getName().equals(list2.get(i).getName())) {
// TODO
}
}

是否有一种方法可以使用Java流来做到这一点?我已经尝试了逻辑:

if (List1().stream().anymatch(x -> List2().stream().anymatch(y -> x.getName().equals(y.getName))))) {
// TODO
}

这可以工作,但是List1的第一个对象(索引)与List2的每个对象(索引)进行比较。

我需要的是List1的第一个对象(索引)与List2的第一个对象进行比较,第二个索引与第二个索引进行比较,以此类推。如何使用流而不是for循环来编写if逻辑

一种解决方案是使用第三方库,该库具有将流对压缩成单个对流的能力。使用这种方法,两个流将被压缩为包含元素对的单个流,具有相同名称的元素对将通过调用Stream.filter()保留,然后最后剩余的过滤元素对将对其应用该操作。

Stack Overflow回答使用JDK8与lambda (java.util.stream.Streams.zip)压缩流包含以这种方式压缩两个流的各种解决方案。

番石榴

Google的Guava库提供Streams.zip方法:

Streams.zip(list1.stream(), list2.stream(), Map::entry)
.filter(e -> e.getKey().getName().equals(e.getValue().getName()))
.forEachOrdered(e ->
System.out.println("Match: " + e.getKey() + ", " + e.getValue()));

StreamEx

StreamEx库提供多种压缩方法,包括StreamEx.zipEntryStream.zip:

EntryStream.zip(list1, list2)
.filterKeyValue((k, v) -> k.getName().equals(v.getName()))
.forKeyValue((k, v) -> System.out.println("Match: " + k + ", " + v));

一种方法是流式处理索引而不是列表,并使用List.get(i)从每个List中检索元素。

IntStream.range(0, list1.size())
.mapToObj(i -> Map.entry(list1.get(i), list2.get(i)))
.filter(e -> e.getKey().getName().equals(e.getValue().getName()))
.forEachOrdered(e ->
System.out.println("Match: " + e.getKey() + ", " + e.getValue()));

IntStream.range(0, list1.size())
.filter(i -> list1.get(i).getName().equals(list2.get(i).getName()))
.forEachOrdered(i ->
System.out.printf("Match at index %s: %s, %sn", i, list1.get(i), list2.get(i)));

注意,为了使这种方法有效,列表必须支持快速(例如恒定时间)随机访问。这通常意味着任何实现RandomAccess接口的列表,如ArrayListArrays.asList()

最新更新