如何在Java中合并两个流?

时间:2018-09-30 04:01:00

标签: java java-8 java-stream

假设我们有两个流,如下所示:

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相同的情况下是相同的,而与name无关(因此May和Marry是同一个人,因为他们的人数都是“ 1”)。

我已经找到了distinct()方法,但是该方法基于Object#equals()。如果不允许我们覆盖equals()方法,如何将stream1stream2合并到一个没有重复项的流中?

2 个答案:

答案 0 :(得分:9)

您可以使用concat()

IntStream.concat(stream1, stream2)

答案 1 :(得分:3)

@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和{{1})的另一种方式}。