There is class A:
class A{
private String a;
private String b;
private String status;
/*
. getter & setter
*/
}
And I have a class B:
class B{
private List<List<A>> list;
}
I have to write a logic to iterate over the list of class A in class B to:
Make sure that the status of all the objects of A in the list is having a value of field status as "SUCCESS", if not then don't do step 2 and end the process
Get the value of field b when field a has a value of "test99" (This would be unique in the list)
Is it possible to do it using streams?
Yes, it is possible with Java 8 Streams but I would use more than just forEach():
list.stream()//1
.flatMap(List::stream)//2
.filter(obj->!"SUCCESS".equals(obj.getStatus()))//3
.findAny()//4
.ifPresentOrElse(o->System.out.println(o+" is not successfull"),()->//5
list.stream()//1
.flatMap(List::stream)//2
.filter(obj->"test99".equals(obj.getA()))//6
.map(obj->obj.getB())//7
.forEach(this::doSomething);//8
)
It does the following:
get a stream from list
convert each List in the stream to a Stream and make one stream out of all those streams containing all elements
get only the elements where status is not SUCCESS
get an Optional with an element where the status is not SUCCESS
Execute System.out.println(o+" is not successfull") if such an element exists (you can use ()->{} if you don't want to do anythin in that case) or
get only the elements where a is test99
get the b value of those elements
run a method (in this case doSomething()) with the value of b as a parameter (you could use collect() if you want to e.g get those element in a List
Related
I have a POJO like this.
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class Test {
private int a;
private String b;
}
I want to exclude the property 'a' if it has 0 value. String b is excluded with
#JsonInclude(JsonInclude.Include.NON_NULL)
Only way I could thing of is convert the int data type to Integer Object and set the value to NULL in the setter explicitly if it is 0.
Any other suggestions or correct solution will be appreciated
Option 1:
Do what you said: Change int to Integer and use #JsonInclude(Include.NON_NULL). Because primitive types have default values and their values cannot be compared to null you have to wrap the int to Integer. See Primitive Data Types. imho this is the cleaner way.
Option 2:
Use the way described in this answer and use #JsonInclude(Include.NON_DEFAULT) instead (see Jackson-annotations API), so that default values (and so also null values for objects) will be ignored.
Note:
If you only want to exclude the specific field (in your case the int/Integer - a - field) when it has a null-/default value and the other fields (in your case the String - b - field) should be included when they have null-/default values, put the annotation on field level.
I am trying to use Optional instead of standard null checks in java
#Data
public class InputObj {
private Double savings;
}
#Data
public class Result {
private String outputSavings;
}
public Result convertInputObjToResult(InputObj inputObj){
Result result = new Result();
Optional<InputObj> optionalInputObj = Optional.ofNullable(inputObj);
optionalInputObj.map(InputObj::getSavings).map(value -> util.convertRoundAndAbs(value,true)).ifPresent(result::setOutputSavings);
return result;
}
which is equivalent of below
public Result convertInputObjToResult(InputObj inputObj){
Result result = new Result();
if(inputObj != null){
if(inputObj.getSavings() != null){
result.setOutputSavings(util.convertRoundAndAbs(inputObj.getSavings(),true));
}
}
return result;
}
I wrote some test cases and I do not get any Null Pointer Exception but I am unable to understand that ifPresent condition is at end and map is before but still I don't get any NPE. Do you see any thing wrong with this code or how it can be improved? This is part of a spring boot application and #Data annotation is used for lombok.
Here's a link to further describe how the map operation works for the Java Optional class.
If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.
So in a case where you have a null value from the map method, it will automatically be converted to Optional.empty().
Then, taking a look at the ifPresent method
If a value is present, invoke the specified consumer with the value, otherwise do nothing.
So this is why you aren't getting any NPE's; the map operations are able to map null results or passed values to Optional.empty(), and the ifPresent operation doesn't execute if passed an empty Optional.
There is no issue with the code except for the typo “ optionalMembershipDetails”. Assuming you meant to use “ optionalInputObj”.
You need to read about java streams to understand the full concept. In a nutshell, operations are evaluated in lazy manner. So ifPresent call will trigger operations which appear before it. In this case, the object is wrapped inside optional, so each intermediate operation will pass another optional to the next operation. Having Optional prevents you getting NPE.
I find myself duplicating over and over the same java 8 expression:
In one method, I have:
List<Message> latestMessages = new ArrayList<>();
...
return latestMessages.stream().map(messageMapper::asMessageDto).collect(toList());
Then in another method of the same class, I have:
List<Message> messagesBetweenTwoUserAccounts = ...;
return messagesBetweenTwoUserAccounts.stream().map(messageMapper::asMessageDto).collect(toList());
The return type of both methods is: List<MessageDto>
I basically convert from a List<Message> to a List<MessageDto>.
Notice the duplicated expression:
stream().map(messageMapper::asMessageDto).collect(toList());
What would be the best way to factor out the above expression using java 8 constructs?
If you don't want to repeat the latestMessages.stream().map(messageMapper::asMessageDto).collect(toList()); multiple times, write a method that contains it :
public static List<MessageDto> transformMessages (List<Message> messages) {
return messages.stream().map(messageMapper::asMessageDto).collect(toList());
}
Now you can call it from multiple places without repeating that Stream pipeline code.
I don't know if that method should be static or not. That depends on where you are calling it from, and where messageMapper comes from (as Holger commented). You can add messageMapper as an argument if different invocations of the method require different mappers.
Given:
A class named B.
2 persistent records of class B, id = {"B1", "B2"}.
A class named A:
class A Extends %Persistent
{
Property rB As B;
ForeignKey FKB(rB) References B();
}
An instance of class A, named objA, with objA.rB = "B3" (which is an invalid value because B has no "B3" persistent record)
I want that:
When objA is going to be saved (objA.%Save()), substitute with an empty string the rB invalid value and save it.
So far:
I have tried to make the substitution using callback methods ( %OnBeforeSave), but it seems that %ValidateObject is being called before.
Is there a way of doing value changes before %ValidateObject using callback methods?
Thanks in advance.
You can modify objects in callback method %OnAddToSaveSet:
http://docs.intersystems.com/cache201511/csp/docbook/DocBook.UI.Page.cls?KEY=GOBJ_callbacks#GOBJ_cb_onaddtosaveset
Lets say I have a List of Car class - List
I want to iterate it and invoke a method. e.g. set().
How can I do it with stream()?
Simple, you don't even need a Stream :
List<Car> cars = ...;
cars.forEach(Car::set);
You could do it with a Stream if you insist :
cars.stream().forEach(Car::set);