Stream flatMap vs map - java

To filter a List we can use
a1.stream().filter(x->x>6).forEach(System.out::println);
and to filter two lists I used FlatMap
Stream<List<Integer>> s2=Stream.of(a1,a2);
s2.flatMap(x->x.stream()).sorted().filter(x->x>6).forEach(System.out::println);
but I tried filtering in this way for a single List
Stream<List<Integer>> s1=Stream.of(a1);
s1.map(x->x.stream()).filter(x->x>2).forEach(System.out::print);
I got an error--- The operator > is undefined for the argument type(s) Stream<Integer>, int
but when I use the flatMap in the map no error why
Stream<List<Integer>> s1=Stream.of(a1);
s1.flatMap(x->x.stream()).filter(x->x>2).forEach(System.out::print);

If you are calling map(x->x.stream()) on a Stream<List<Integer>>, you'll get a Stream<Stream<Integer>>. You cannot apply .filter(x->x>2) on the elements of that Stream, since those elements are Stream<Integer>s, and the > operator requires two numeric operands.
If you use flatMap instead of map, you are converting your Stream<List<Integer>> to a Stream<Integer> whose elements are all the elements of all the Lists of the original Stream. Therefore, you can apply the .filter(x->x>2) filter on them.

Stream<List<Integer>> s1 = Stream.of(a1);
s1.map(x -> x.stream()).filter(x -> x > 2).forEach(System.out::print);
This will give error as you are not using flat map so filtering not possible whole (Streams >2). You can try like this:
Stream<List<Integer>> s1 = Stream.of(a1);
s1.map(x -> x.stream()).filter(x -> x.findFirst().get() > 2).forEach(System.out::print);
As we cannot apply.filter(x->x>2) on we will requires two numeric operands. s1.map(x -> x.stream()).filter(x -> x.findFirst().get() > 2).forEach(System.out::print); if we will take this then filter will find find matching element value which is greater than 2. In short we have to use flatmap to find greater than 2 in those streams or any operation to fetch numeric operands from stream then only it work.

Related

Combine List of streams into one single stream

I have a List<Stream<String>> that I get by doing a series of transactions.
The list size is dynamic (Maximum 3 elements) so I can't do:
Stream<String> finalStream = Stream.concat(list.get(0),Stream.concat(list.get(1),list.get(2));
I need to concatenate the list of Streams into one single Stream<String>.
Is there any simple way to do this?
If you have a list of lists, or a stream of streams, or any collection of collections, you can use flatMap to, well, flatten them. flatMap applies a mapping function which must return a stream to an input and streams each element of the result of the mapping function.
In your case, you could do:
var finalStream = list.stream().flatMap(x -> x);
x -> x is the identify function which returns the input unmodified. If you prefer, you can replace it with the expression Function.identity().

How to convert List<Optional<Type>> into List<Type>

I have extracted values from a Map into a List but got a List<Optional<TXN_PMTxnHistory_rb>>, and I want to convert it into List<TXN_PMTxnHistory_rb>.
My code:
List<Optional<TXN_PMTxnHistory_rb>> listHistory_rb6 =
listHistory_rb5.values()
.stream()
.collect(Collectors.toList());
I'd like to obtain a List<TXN_PMTxnHistory_rb>.
Filter out all the empty values and use map to obtain the non-empty values:
List<TXN_PMTxnHistory_rb> listHistory_rb6 =
listHistory_rb5.values()
.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
It's possible to do this using a method called flatMap on the stream of Optionals which will remove any 'empty' Optionals.
List<TXN_PMTxnHistory_rb> listHistory_rb6 =
listHistory_rb5.values()
.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
Flatmap is essentially performing two things - "mapping" and "flattening". In the mapping phase it calls whatever method you've passed in and expects back a new stream - in this case each Optional in your original List will become a Stream containing either 1 or 0 values.
The flatten phase will then create a new Stream containing the results of all the mapped Streams. Thus, if you had 2 Optional items in your List, one empty and one full, the resulting Stream would contain 0 elements from the first mapped Stream, and 1 value from the second.
Another option is to get all values and then filter out nulls:
List<TXN_PMTxnHistory_rb> listHistory_rb6 =
listHistory_rb5.values().stream()
.map(opt -> opt.orElse(null))
.filter(Objects::nonNull)
.collect(Collectors.toList());

java 8 make a stream of the multiples of two

I'm practicing streams in java 8 and im trying to make a Stream<Integer> containing the multiples of 2. There are several tasks in one main class so I won't link the whole block but what i got so far is this:
Integer twoToTheZeroth = 1;
UnaryOperator<Integer> doubler = (Integer x) -> 2 * x;
Stream<Integer> result = ?;
My question here probably isn't related strongly to the streams, more like the syntax, that how should I use the doubler to get the result?
Thanks in advance!
You can use Stream.iterate.
Stream<Integer> result = Stream.iterate(twoToTheZeroth, doubler);
or using the lambda directly
Stream.iterate(1, x -> 2*x);
The first argument is the "seed" (ie first element of the stream), the operator gets applied consecutively with every element access.
EDIT:
As Vinay points out, this will result in the stream being filled with 0s eventually (this is due to int overflow). To prevent that, maybe use BigInteger:
Stream.iterate(BigInteger.ONE,
x -> x.multiply(BigInteger.valueOf(2)))
.forEach(System.out::println);
Arrays.asList(1,2,3,4,5).stream().map(x -> x * x).forEach(x -> System.out.println(x));
so you can use the doubler in the map caller

turn string separated by spaces to arraylist of integers in one line

Say I have the String "5 12 4". I'd like to turn that into an ArrayList of Integers containing 5,12 and 4 in a single functional line.
I feel there should be a way to do this by combining split(" "), turning it into a stream, using mapToInt(s->Integers.parseInt(s)) and collect(Collectors.toList()). Something like:
ArrayList<Integer> nextLine = Arrays.stream(inputLine.split(" "))
.mapToInt(s->Integer.parseInt(s))
.collect(Collectors.toList());
But that does not work, because mapToInt give me ints instead of Integers.
I know how to do it using a loop. I would like a way to do it in a single stream operation if it exists.
You can use Integer#valueOf. Note you should use Stream#map and not Steam#mapToInt though:
List<Integer> nextLine =
Arrays.stream(inputLine.split(" "))
.map(Integer::valueOf)
.collect(Collectors.toList());
mapToInt returns an IntStream and you cannot accumulate primitive elements into a ArrayList<T> therefore you can utilise the map operation which would yield a Stream<Integer> and then you can accumulate the elements into a ArrayList<T>.
That said, even if you change .mapToInt(s -> Integer.parseInt(s)) to .map(s -> Integer.parseInt(s)) your code still will not compile as the receiver type for the result is of type ArrayList<Integer> whereas the collect terminal operation will return a List<Integer> in this specific case.
Therefore to solve the remaining issue you can either have the receiver type as List<Integer> or leave the receiver type as is and then do .collect(Collectors.toCollection(ArrayList::new)); for the reduction operation yielding a specific List implementation.
Another variant to the already posted answer would be:
ArrayList<Integer> resultSet =
Pattern.compile(" ")
.splitAsStream(inputLine)
.map(Integer::valueOf)
.collect(Collectors.toCollection(ArrayList::new));

findFirst() for Java streams, but for n elements?

I want to collect the first n elements from a stream, without iterating through the entire thing. Is there a standard method that does this? Ala
MyList.stream()
.filter(x -> predicate(x))
.findFirstN(100)
would return a collection of up to 100 elements from the stream? My alternative is to evaluate the entire stream and then sample from the result, but that doesn't take advantage of the lazy evaluation inherent to streams.
MyList.stream()
.filter(x -> predicate(x))
.limit(100)

Categories

Resources