I would like to know how to pull out field and make it become a list using streams. For example, if I have a list of Pairs, Pair[2] { Pair<3,5>,Pair<5,7>}, I would like to make it become Integer[3] {3,5,7}. (After using Stream.distinct() to remove the dupicate 5) Pair class is provided if that is needed.
public class Pair<T,U> { private final T first; private final U second; public Pair(T first, U second){ this.first = first; this.second = second; } T first() { return this.first; } U second(){ return this.second; } @Override public String toString(){ return "<" + this.first + ", "+ this.second+">"; } }
Advertisement
Answer
You want to turn your stream of pairs into a stream of numbers; to do so, any given pair gets mapped into a variable number of items in the stream. .map
can only map one thing to one other thing. flatMap
, on the other hand, can map one thing to any number (even 0) things.
flatMap
turns an element of the stream, into a stream of whatever you want – these streams are then concatenated together to form a new single stream.
Thus, all you need to do is to turn a Pair<Integer, Integer>
instance into a stream representing the 2 integers. Java will do the rest:
pairs.stream().flatMap(pair -> Stream.of(p.first(), p.second())).distinct().forEach(System.out::println);
That would end up printing 3, 5, and 7, as desired.
NB: Pair is bad java style. Java is extensively nominal: Its designed around the notion that things are named. Those pairs of numbers represent something more specific than ‘a pair of numbers’. You should make a class that models that exact thing. The alternative is that we do away with, say, a Person
class and instead make a Tuple<String, Tuple<Integer, Integer, Integer>, String>
instead of a class with a field String name;
, LocalDate birthDate;
, and String studentId;
or whatnot. Clearly a bad idea.