Use the class name. For example:
latestEvent.map(AssetEvent::getTimestamp).ifPresent(latestList::add);
Assuming AssetEvent is the name of the class having the getTimestamp method.
Videos
A method reference (List::forEach) can't take an argument so you can't compose them. On the other hand you can pass a method reference as an argument to a "normal" method call (l.forEach(BufferedImage::flush)).
I don't think you can do much better than your second to last option.
It's less hassle all around to use empty lists instead of nulls. Optional makes it easy:
Optional.ofNullable(list)
.orElseGet(Collections::emptyList)
.forEach(BufferedImage::flush);
What about use enum to declare all fields from Request and use it as common part of the code. I did not check it, this is only to show my approach:
public enum RequestField {
PLANT_ID(Request::getPlantId, (val, campaign) -> campaign.plant.id::contains),
TITLE(Request::getTitle, (val, campaign) -> campaign.title::containsIgnoreCase),
CAMPAIGN_NUMBER(Request::getCampaignNumber, (val, campaign) -> campaign.campaignNumber::like),
// ... more fields here ...
;
private final Function<Request, Optional<Object>> get;
private final BiFunction<Object, Campaign, BooleanExpression> map;
RequestField(Function<Request, Object> get, BiFunction<Object, Campaign, BooleanExpression> map) {
this.get = get.andThen(Optional::ofNullable);
this.map = map;
}
public static List<BooleanExpression> getBooleanExpressions(Request request, Campaign campaign) {
if (request == null)
return Collections.emptyList();
List<BooleanExpression> res = new LinkedList<>();
for (RequestField field : values())
field.get.apply(request)
.map(r -> field.map.apply(r, campaign))
.ifPresent(res::add);
return res.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(res);
}
}
And your client code will be looking like:
List<BooleanExpression> booleanExpressions = RequestField.getBooleanExpressions(request, campaign);
P.S. Your last code could be look like:
if (request.getLockVehicle() != null)
expressionMapping.add(request.getLockVehicle() ? campaign.lockVehicle.isNotNull() : campaign.lockVehicle.isNull());
The aim of using Optional is informing who is calling that method / parameter that it could be null.
In the first part of your code, you are not getting any advantage from this, you are just rewriting some code wrapping it around Optional logic but, as you said, without any "reusable" purpose.
A useful way is using it as returning value of a method: for example, if you know that your title could be null, you can refactor your getter like
public Optional<String> getTitle(){
return Optional.ofNullable(this.title); //I'm guessing the 'title' variable here
}
This will help you: every time you call getTitle() , you will know that could be null, because you are obtaining an Optional<String> instead of a String.
This will bring then you to:
request.getTitle().ifPresent(title-> title.doSomething())
// you can also add something like .orElse("anotherStringValue")
The second example could be reworked as the first one, making the return of getLockVehicle() as Optional<Boolean>, even if I suggest here setting that with a default value in your class, probably to false... Optional<Boolean> is pretty senseless imho
Hope this helps clearing your mind