How to iterate nested lists with lambda streams?
Date : March 29 2020, 07:55 AM
Hope this helps I am afraid that using streams and lambdas, your performance may suffer. Your current solution returns the first valid and parse-able node, however it is not possible to interrupt an operation on stream such as for-each ( source). Also, because you can have two different outputs (returned result or thrown exception), it won't be possible to do this with single line expression. public static Result match(Response rsp) throws Exception {
Map<Boolean, List<Object>> collect = rsp.getFirstNodes().stream()
.flatMap(firstNode -> firstNode.getSndNodes().stream()) // create stream of SndNodes
.filter(SndNode::isValid) // filter so we only have valid nodes
.map(node -> {
// try to parse each node and return either the result or the exception
try {
return parse(node);
} catch (ParseException e) {
return e;
}
}) // at this point we have stream of objects which may be either Result or ParseException
.collect(Collectors.partitioningBy(o -> o instanceof Result)); // split the stream into two lists - one containing Results, the other containing ParseExceptions
if (!collect.get(true).isEmpty()) {
return (Result) collect.get(true).get(0);
}
if (!collect.get(false).isEmpty()) {
throw (Exception) collect.get(false).get(0); // throws first exception instead of last!
}
return null;
}
private static class IntermediateResult {
private final SndNode node;
private final Result result;
private final List<ParseException> exceptions;
private IntermediateResult(SndNode node, Result result, List<ParseException> exceptions) {
this.node = node;
this.result = result;
this.exceptions = exceptions;
}
private Result getResult() throws ParseException {
if (result != null) {
return result;
}
if (exceptions.isEmpty()) {
return null;
}
// this will show all ParseExceptions instead of just last one
ParseException exception = new ParseException(String.format("None of %s valid nodes could be parsed", exceptions.size()));
exceptions.stream().forEach(exception::addSuppressed);
throw exception;
}
}
public static Result match(Response rsp) throws Exception {
return Stream.concat(
Arrays.stream(new SndNode[] {null}), // adding null at the beginning of the stream to get an empty "aggregatedResult" at the beginning of the stream
rsp.getFirstNodes().stream()
.flatMap(firstNode -> firstNode.getSndNodes().stream())
.filter(SndNode::isValid)
)
.map(node -> new IntermediateResult(node, null, Collections.<ParseException>emptyList()))
.reduce((aggregatedResult, next) -> {
if (aggregatedResult.result != null) {
return aggregatedResult;
}
try {
return new IntermediateResult(null, parse(next.node), null);
} catch (ParseException e) {
List<ParseException> exceptions = new ArrayList<>(aggregatedResult.exceptions);
exceptions.add(e);
return new IntermediateResult(null, null, Collections.unmodifiableList(exceptions));
}
})
.get() // aggregatedResult after going through the whole stream, there will always be at least one because we added one at the beginning
.getResult(); // return Result, null (if no valid nodes) or throw ParseException
}
private static class ParsedNode {
private final Result result;
private ParsedNode(Result result) {
this.result = result;
}
}
public static Result match(Response rsp) throws Exception {
return rsp.getFirstNodes().stream()
.flatMap(firstNode -> firstNode.getSndNodes().stream())
.filter(SndNode::isValid)
.map(node -> {
try {
// will parse all nodes because of flatMap
return new ParsedNode(parse(node));
} catch (ParseException e ) {
return new ParsedNode(null);
}
})
.filter(parsedNode -> parsedNode.result != null)
.findFirst().orElse(new ParsedNode(null)).result;
}
|
How to convert List<Object[]> to Map<String,BigInteger> with Streams & Lambda Java8
Tag : java , By : Pitmairen
Date : March 29 2020, 07:55 AM
I hope this helps you . I have the data as: Map<String, BigInteger> map =
fromDB().stream()
.collect(Collectors.toMap(
o -> (String) o[0],
o -> (BigInteger) o[1],
(b1, b2) -> b2
));
|
How to filter nested streams in Java 8 with lambda productions
Date : March 29 2020, 07:55 AM
around this issue You can use allMatch(predicate) to determine if all deals of an option are red: List<Deal> output =
dl.stream()
.filter(d -> d.getDealop().stream().allMatch(po -> po.getColor().equals("red")))
.collect(Collectors.toList());
|
How can i loop trough nested objects and validate some calculations with lambda and streams
Date : March 29 2020, 07:55 AM
around this issue Use Stream.of to create Category stream and then filter objects with rootCategory is not null int sum = Stream.of(obj1, obj2, obj3)
.filter(o -> Objects.nonNull(o.getRootCategory()))
.mapToInt(c -> c.getQty() * c.getPrice())
.sum();
|
Using streams and lambda expressions to replace a nested for loop to enter into a nested list
Tag : java , By : Star Gryphon
Date : March 29 2020, 07:55 AM
it helps some times Instead of directly translating your for loops to forEach, look at what your for loops are doing on a higher level of abstraction. They are transforming each element of your lists to another element. Whenever you see transformations like this, map is what you should call. List<List<GrayscalePixel>> grayscalePhoto =
photo.stream().map(x ->
x.stream().map(RGBpixel::convertToGrayscale).collect(Collectors.toList())
).collect(Collectors.toList());
|