简体   繁体   中英

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). 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? 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").

I've found the distinct() method, but this method is based on 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?

你可以使用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" .

Your other question of "how to merge two Stream<T> without overwriting the equals() and hashCode() method?" can be done using the toMap collector, ie assuming you don't want the result as a 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.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.

for first question you can use "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}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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