Little new to Java 8 style;
How effectively, we can code for the below statement by including all the null checks usin Java 8 API
search.getResource()
.getResults().get(0).getCustomer().getPhoneNumber()
I tried like following: (Looks little weird to me with Optional everywhere)
List<Result> results = search.getResource().getResults();
Optional<Result> optionalResult = Optional.of(results).orElse(new ArrayList<>()).stream().findFirst();
if(optionalResult.isPresent() && Optional.of(optionalResult.get().getCustomer()).isPresent()) {
Source source = Optional.of(optionalResult.get().getCustomer()).get();
Optional<List<Customer>> customers = Optional.of(source.getCustomers());
if(customers.isPresent() && customers.get().stream().findFirst().isPresent() &&
Optional.of(customers.get().stream().findFirst().get().getPhoneNumber()).isPresent())
dest.setNumber(Integer.parseInt(customers.get().stream().findFirst().get().getPhoneNumber())));
}
Could you please suggest me a better way of doing. Thanks!
You can use the map method of Optional class:
final Optional<String> optional = Optional.ofNullable(search.getResource())
.map(resource -> resource.getResults())
.map(results -> results.size() > 0 ? results.get(0) : null)
.map(result -> result.getCustomer())
.map(customer -> customer.getPhoneNumber());
optional.ifPresent(phoneNumber -> {
System.out.println(phoneNumber);
});
OT: Why don't you simply code null safe?
Coding null safe means that you never explicitly retun a (literal) null from a method or pass one in as a parameter. Furthermore you always do you null checks on local variables before you pass them around or return them.
On Map collections you use getOrDefault or computeIfAbsent to replace the null returned for missing keys with a Null Equivalent Constant of the expected type.
Usually passing null back and forth is a in band signal for an error condition which Java has exceptions for.
And no: passing around Optional is not a solution, but another incarnation of the problem. Optional is an elegant way to deal with variables than may contain null within a method.
Don't let it escape...
Related
I want to achieve the following:
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("someString", object.getObjectField().getValue());
If object.getObjectField() is null, then I get a NullPointerException. I can easily avoid it, with the following null check:
if(object.getObjectField() != null) {
linkedHashMap.put("someString", object.getObjectField().getValue());
} else {
linkedHashMap.put("someString", "N/A");
}
However, I was thinking to find a better and prettier implementation, using Java 8 Optional, but in this case I still receive a NullPointerException:
linkedHashMap.put("someString", Optional.ofNullable(object.getObjectField().getValue()).orElse("N/A");
What would be the right approach in this case?
but in this case I still receive a NullPointerException
That's because you would still be invoking getValue() even if getObjectField() is null.
You can use Optional.map to apply a function if present:
Optional.ofNullable(object.getObjectField()).map(ObjectType::getValue)
If you want to use a default value, you can just add the orElse after that:
Optional.ofNullable(object.getObjectField()).map(ObjectType::getValue)
.ofElse("N/A")
How to implement this in java8 and anyone please help me,i tried using streams but not working may be syntactically i was wrong.
I have tried:
list.stream().map(res->.get(s)).filter(res->res!=null && res.equalIgnoreCase("something"))
You can use a new java8 Collection.removeIf() method. The method works by applying the condition provided in the Predicate instance to all the elements in the Collection on which it is invoked. The elements which satisfy the condition are retained while the remaining are removed from the Collection.
list.removeIf(item -> {
String res = map.get(item);
return res != null && res.equalsIgnoreCase("smt");
});
I want to use Optional for handling null values, the "tricky" part which I cannot think of what is the best way to do - is that I want to do logging if value is null. I can achieve that with following code - but it feels awkward.
(Update: I have posted my own answer, with Optional from Java 9)
Lets say code looks like this:
// logLine.getSomeProperty returns Optional<String>
List<LogDetails> logDetails = logLine.getSomeProperty()
.map(this::extractLogDetails)
.orElseGet(() -> logError(logLine));
List<LogDetails> extractLogDetails(String s) {
List<LogDetails> logDetails = new ArrayList<>();
String sp = "(?:([A-Z0-9]{5,7})-([A-Z0-9]{9})-(.{4}))";
Pattern p = Pattern.compile(sp, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(s);
while (m.find()) {
logDetails.add(new LogDetails(m.group(1), m.group(2), m.group(3)));
}
return logDetails;
}
List<LogDetails> logError(LogLine logLine) {
log.error("Error while ... {} ", logLine));
persistence.setErrorStatus(logLine, FAILED_PARSING);
return new ArrayList<>();
}
It would do what I want, but I have several "problems" with it.
I found it odd, that method called orElseGet is used for logging
errors.
I could replace orElseGet with orElseThrow and logError there and DO NOT throw anything - which I don't like either.
logError method returns List which I don't use and it looks weird to return something from method which should be void.
Simply there must be better way
Cases where someProperty is not null, but there are no matches - I would like to log as well, but for that I would need another line of code to check if logDetails.size() == 0
The orElseGet is not really intended as an error handling mechanism, but as a way to generate a different default value in case the Optional instance is not carrying any.
If you want to check if the Optional is empty explicitly, simply use the Optional.isPresent() check, and do the logError() in that case.
What you need to think first is, if the Optional is empty, what do you want to do? Apart from logging the error, do you want to proceed with an empty list?
If yes then you could have something like this:
List<LogDetails> logDetails = logLine.getSomeProperty()
.map(this::extractLogDetails)
.orElseGet(Collections::emptyList);
After which you could do:
if (logDetails.isEmpty()) {
logError(logline);
}
Alternatively, if you do not want to have an empty list at all, you could keep things at optional level. This way, both cases where the getSomeProperty() is empty or when the generated list is empty are handled in the same way.
Optional<List<LogDetails>> logDetailsOpt = logLine.getSomeProperty()
.map(this::extractLogDetails)
.filter(list -> !list.isEmpty());
if (!logDetailsOpt.isPresent()) {
logError(logLine);
}
In both cases, logError() is not expected to return anything. It is doing what it is intended to do in its name, logging the error.
Rather than trying to overuse the functionality of Optional, try to make your intentions in your code clear. There is more value in readability.
Rather than changing result type or logging inside stream you can simply return partitioned Map. Then after obtaining the result, execute log function on the resulting map accordingly.
Map<Boolean, List<String>> map = Stream.of("a", "aaa", "aaaa")
----
.collect(() -> Collectors.partitioningBy(predicate))
----
While I am grateful for the answers, but I just recently find out, that Java 9 introduced new method to Optional and I like it best.
Here is example.
Optional.ofNullable(user).ifPresentOrElse( u -> logger.info("User is:" + u.getEmail()),
() -> logger.info("User not found"));
First I need to check if data is present in list then get else set default or empty value on a Java 8 stream.
Currently I am using below code without isPresent but I dont know how to use isPresent in java8.
I am trying something below which is not perfect:
String isScheme = (this.mapProgramApproaches.stream().findFirst().isPresent())? this.mapProgramApproaches.stream().findFirst().get().getIsScheme().toString() : "0";
Where as mapProgramApproaches this is set.
Don't use isPresent() (it makes no sense to run the Stream pipeline twice).
You can use map to map the value of the Optional to the required String, and then
use orElse() to return a default value when the Optional value is not present:
String isScheme = this.mapProgramApproaches.stream()
.findFirst()
.map(o->o.getIsScheme().toString())
.orElse("0");
Maybe you are looking for something like this:
String isScheme = this.mapProgramApproaches.stream()
.findFirst()
.map(p -> p.getIsScheme().toString())
.orElse("0");
I'm not sure about context in which you are doing this, but I suppose that you would like to check whether some object is scheme and then do something with that. In that case I would suggest implement it like this:
List<String> mapProgramApproaches = new ArrayList<>();
mapProgramApproaches.stream()
.filter(this::isScheme)
.findFirst()
.ifPresent(this::doYourCode)
.orElse(defaultValue);
It will make your code cleaner. And will help to avoid additional conditionals!
I need a cleaner solution to using an ImmutableSet. I have code that looks like
Set foo = ImmutableSet.copyOf(aGeoR.getFailed());
it works great when aGeoR.getFailed() returns one or more entries.
it fails when the returned set is null.
When its null, I need a
Set foo = ImmutableSet.of();
What is the clean way to do this?
This is phrased as a question about Guava and ImmutableSet, but the real issue here is with aGeoR.getFailed(). It is essentially never appropriate for a collection-returning method to return null. It should be returning an empty set to begin with (see Effective Java); and yeah, the fact that it isn't is going to cause some pain to users.
When I have to deal with an API like that, and I can't fix it or get it fixed, I do exactly what you showed in your revision of #Jherico's answer.
Set<FailedGeoR> failedOrNull = aGeoR.getFailed();
Set<FailedGeoR> failed = (failedOrNull == null)
? ImmutableSet.<FailedGeoR>of()
: ImmutableSet.copyOf(failedOrNull);
Set foo = aGeoR.getFailed();
foo = foo == null ? new HashSet() : ImmutableSet.copyOf(foo);
I would use an Optional:
Set<FailedGeoR> foo = Optional.ofNullable(aGeoR.getFailed())
.map(ImmutableSet::copyOf)
.orElse(ImmutableSet.of())
I agree #AgustÃn Ranieri, but if possible, I hope Guava add ofNull and copyOfNull methods, like Optional, and it's just do one more thing, when element is null or empty, always return ImmutableSet.of(), it's let me write less duplicates code.
// the foo always not be null
ImmutableSet<?> foo = ImmutableSet.copyOfNull(aGeoR.getFailed());