Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 659
weaver Avatar asked Sep 30 '18 04:09

weaver


People also ask

How do I merge two streams in Java?

concat() in Java. Stream. concat() method creates a concatenated stream in which the elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel.

Where do streams merge?

A watershed, or drainage basin, is the area that collects water for a stream. As smaller streams flow downhill, they often merge together to form larger streams. These smaller streams are called tributaries.


1 Answers

@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, i.e. 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.

like image 165
Ousmane D. Avatar answered Sep 21 '22 02:09

Ousmane D.