简体   繁体   English

如何在Java中合并两个流?

[英]How to merge two streams in Java?

Suppose we have two streams as follows:假设我们有如下两个流:

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.

Is there any convenient way to merge the two streams to [13, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14] using the Java 8 stream API (the order doesn't matter).有没有什么方便的方法可以使用 Java 8 流 API 将两个流合并到 [13, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14] (顺序无关紧要) . Or can we only handle one stream at the same time?还是我们只能同时处理一个流?

Furthermore, if the two streams are object streams, how is it possible to keep only distinct objects, without overriding the equals() and hashCode() methods?此外,如果这两个流是对象流,如何在不覆盖equals()hashCode()方法的情况下只保留不同的对象? For example:例如:

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'}

We consider two students the same when their no is the same and regardless of the name (so May and Marry are the same person because their numbers are both "1").当他们的no相同no考虑name时,我们认为两个学生相同(因此 May 和 Marry 是同一个人,因为他们的编号都是“1”)。

I've found the distinct() method, but this method is based on Object#equals() .我找到了distinct()方法,但该方法基于Object#equals() If we are not allowed to overwrite the equals() method, how can we merge stream1 and stream2 to one stream which has no duplicate items?如果我们不允许覆盖equals()方法,我们如何将stream1stream2合并到一个没有重复项的流?

你可以使用concat()

IntStream.concat(stream1, stream2)

@Jigar Joshi has answered the first part of your question which is "how to merge two IntStream's into one" . @Jigar Joshi回答了你的问题的第一部分,即“如何将两个IntStream合并为一个”

Your other question of "how to merge two Stream<T> without overwriting the equals() and hashCode() method?" 你的另一个问题是“如何在不覆盖equals()hashCode()方法的情况下合并两个Stream<T> ?” can be done using the toMap collector, ie assuming you don't want the result as a Stream<T> . 可以使用toMap收集器完成,即假设您不希望结果为Stream<T> Example: 例:

Stream.concat(stream1, stream2)
      .collect(Collectors.toMap(Student::getNo, 
               Function.identity(), 
               (l, r) -> l, 
               LinkedHashMap::new)
      ).values();

if you want the result as a Stream<T> then one could do: 如果你想把结果作为Stream<T>那么可以做:

 Stream.concat(stream1, stream2)
       .collect(Collectors.collectingAndThen(
               Collectors.toMap(Student::getNo,
                    Function.identity(),
                    (l, r) -> l,
                    LinkedHashMap::new), 
                    f -> f.values().stream()));

This is possibly not as efficient as it can be but it's another way to return a Stream<T> where the T items are all distinct but without using overriding equals and hashcode as you've mentioned. 这可能不如它有效,但它是返回Stream<T>的另一种方式,其中T项都是不同的,但是没有使用覆盖的equalshashcode ,如上所述。

for first question you can use "flatMap"对于第一个问题,您可以使用“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}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM