假设我们有如下两个流:
IntStream stream1 = Arrays.stream(new int[] {13, 1, 3, 5, 7, 9});
IntStream stream2 = Arrays.stream(new int[] {1, 2, 6, 14, 8, 10, 12});
stream1.merge(stream2); // some method which is used to merge two streams.
有没有方便的方法通过使用Java 8流API将这两个流合并到[13, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14](顺序不事情)。或者我们可以同时只处理一个流吗?
此外,如果两个流都是对象流,如何在不重写
equals()
和 hashCode()
方法的情况下仅保留不同的对象?例如:
public class Student {
private String no;
private String name;
}
Student s1 = new Student("1", "May");
Student s2 = new Student("2", "Bob");
Student s3 = new Student("1", "Marry");
Stream<Student> stream1 = Stream.of(s1, s2);
Stream<Student> stream2 = Stream.of(s2, s3);
stream1.merge(stream2); // should return Student{no='1', name='May'} Student{no='2', name='Bob'}
只要他们的
no
相同,我们就认为他们是同一个学生。 (所以 May 和 Marry 是同一个人,因为他们的数字都是“1”)。
我找到了
distinct()
方法,但是这个方法是基于Object#equals()
的。如果我们不允许覆盖 equals()
方法,我们如何将 stream1
和 stream2
合并到一个没有重复项的流中?
@Jigar Joshi 已回答您问题的第一部分,即 “如何将两个 IntStream 合并为一个”。
您的另一个问题是“如何合并两个
Stream<T>
而不覆盖equals()
和hashCode()
方法?”可以使用 toMap
收集器来完成,即
假设您不希望结果为 Stream<T>
。
示例:
Stream.concat(stream1, stream2)
.collect(Collectors.toMap(Student::getNo,
Function.identity(),
(l, r) -> l,
LinkedHashMap::new)
).values();
如果您希望结果为
Stream<T>
那么可以这样做:
Stream.concat(stream1, stream2)
.collect(Collectors.collectingAndThen(
Collectors.toMap(Student::getNo,
Function.identity(),
(l, r) -> l,
LinkedHashMap::new),
f -> f.values().stream()));
这可能没有那么高效,但它是返回
Stream<T>
的另一种方式,其中 T
项都是不同的,但不使用覆盖 equals
和 hashcode
,正如您所提到的。
第一个问题 你可以使用“flatMap”
IntStream stream1 = Arrays.stream(new int[] {13, 1, 3, 5, 7, 9});
IntStream stream2 = Arrays.stream(new int[] {1, 2, 6, 14, 8, 10, 12});
List<Integer> result = Stream.of(stream1, stream2).flatMap(IntStream::boxed)
.collect(Collectors.toList());
//result={13, 1, 3, 5, 7, 9, 1, 2, 6, 14, 8, 10, 12}
编辑
感谢@Vinicius 的建议, 我们可以使用
Stream<Integer> result = Stream.of(stream1, stream2).flatMap(IntStream::boxed).distinct();
在这里,我们将根据
equals
方法获得所有不同元素的流。