java8 stream collect different list - java-8

I want to convert the input list to different list after filter. Please let know how to implement in java8 stream.
I tried something like below, it gave compilation error "p cannot be resolved to a variable" in getOutput() in collect().
List<Output> outputList= inputList.stream()
.filter(p -> p.param1==10)
.collect(Collectors.toList(getOutput(p)));
private Output getOutput(Input inp){
Output out = new Output();
out.value1= inp.value1;
---
---
}

As suggested by the comments you can do something like this
List<Output> outputList= inputList.stream()
.filter(p -> p.param1==10)
.map(j -> getOutput(j))
.collect(Collectors.toList());
So after the filter you convert the objects to your other type and finally collect. Alternatively, you can use the mapping collector to transform your objects into another kind and then collect them like below
List<Output> outputList= inputList.stream()
.filter(p -> p.param1==10)
.collect(Collectors.mapping(j -> getOutput(j), Collectors.toList()));

Related

Java 8 Streams : Add validation to avoid duplicate keys

The following code throws Exception when it tries to add a duplicate id. How can I modify the code to avoid duplicates?
return Optional.ofNullable(list)
.isPresent() ? (list.stream()
.collect(Collectors.toMap(ViewObject::getId, viewObject -> viewObject))) : new HashMap<>();
There is an overload of toMap which allows to specify mergeFunction:
Collectors.toMap(ViewObject::getId,
viewObject -> viewObject,
(a, b) -> a // Resolve the duplicates here
)
Additionally, Optional.ofNullable(list).isPresent() seems to be unnecessary. You can completely skip it by initializing the list if it is null. Optionals should be used in the method signature and not inside the method body.

Spring Reactor Set of Sets Combine to a Set

I'm trying to figure out how to get a Mono<Set<Customer>> from Flux<Order> .
Given that Order contains Set<Customer>
I've been trying to read all over and here is the closest i can get but it still wont compile. Can someone offer a hand please. In following example, orderService.getAll(orderCriteria) returns Flux<Order>
final Mono<Set<Customer>> customerSetMono = orderService
.getAll(orderCriteria)
.map(order -> order.getCustomers())
.collect(Collectors.toSet()) //Mono<Set<Set<Customer>>
.flatMap(
customerSet -> customerSet.stream()
.flatMap(customers -> customers.stream()))
.collect(Collectors.toSet());
You're facing a list inside a list scenario but in a reactive context. So, all you need to do is use a proper variant of flatMap. Here's how your code should look like
orderService.getAll(orderCriteria) // Flux<Order>
.flatMapIterable(Order::getCustomers) // Flux<Customer>
.collect(Collectors.toSet()); // Mono<Set<Customer>>

List of lists and Java 8

I have a list of class R with list of other class P
List<R> rList = getRListFromDb();
I would like to get the all the P objects in another list
List<P> result = new ArrayList<>();
I tried these, but giving me Class cast exception, saying class P cannot be converted to class R. By the way I have seen issue given below, but tried and could not figure it out.
How can I turn a List of Lists into a List in Java 8?
1. rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
2. rList.forEach(r -> result.addAll(r.getP()));
I would like to what is incorrect here and also would like to know different ways of getting this done in Java 8.
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
would work if you didn't use flatMap (since addAll requires a Collection, but flatMap transforms your Stream<List<P>> to a Stream<P>.
This would work:
rList.stream().map(R::getP).forEach(result::addAll);
With flatMap it should be:
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::add);
That said, the correct way is to use collect:
List<P> result = rList.stream()
.map(R::getP)
.flatMap(List::stream)
.collect(Collectors.toList());
or
List<P> result = rList.stream()
.flatMap(r -> r.getP().stream())
.collect(Collectors.toList());

Using streams/collect to transform a Map

I am trying to convert a Map to another Map where the new key is simply the original key toString(). With the streams API I do this as follows:
mapMap.entrySet().stream().collect(Collectors.toMap(
(Map.Entry entry) -> entry.getKey().toString(),
(Map.Entry entry) -> entry.getValue()
));
The problem is that this doesn't preserve the internal Map type. I don't mind returning a TreeMap if the original map happens to be a HashMap, but the other way around is a problematic as sorting of the elements is removed. I've been fooling around with variations of the above code to get this done, but I don't seem to get very far. Right now, I have written it without streams, as follows:
TreeMap<String, Integer> stringMap = new TreeMap<>();
for (OriginalType t: originalMap.keySet()) {
stringMap.put(t.toString(), originalMap.get(t));
}
Can anyone put me in the right direction to do this with streams?
Thanks
There is an overload of Collectors.toMap which will allow you to specify which type of map you want returned.
mapMap.entrySet().stream().collect(Collectors.toMap(
(Map.Entry entry) -> entry.getKey().toString(),
(Map.Entry entry) -> entry.getValue(),
(val1, val2) -> { throw new RuntimeException("Not expecting duplicate keys"); },
() -> new TreeMap<>()
));
(A note about the third argument: it is intended as a function which will merge two values together that have the same key. When I don't expect these things to happen, I prefer to throw an exception.)

How to convert List<List<Double>> to List<Double[]> and to List<double[]> with Java 8 stream API?

I got stuck with this problem.
I've found similar answers here, but none of those solves the problem.
Should I use mapToDouble() here? Is there anything like "mapToDoubleArray"?
To convert a List<List<Double>> into a List<double[]>, you need to map each inner list into a double array using mapToDouble combined with toArray() (which is the "mapToDoubleArray" operation you are looking for).
List<double[]> res =
myList.stream()
.map(l -> l.stream().mapToDouble(d -> d).toArray())
.collect(toList());
If you want a List<Double[]> instead, you can simply use .map(list -> list.toArray(new Double[list.size()])).

Resources