我有2个不同的列表:List1
和List2
,我想对每个索引执行一个操作,其中元素具有相同的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.zip
和EntryStream.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
接口的列表,如ArrayList
和Arrays.asList()
。