Trying to apply multiple filters based on condition, pseudo code is:
if TypeA exception
then throw TypeA Exception
if TypeB
then throw TypeB Exception
else TypeC Exception.
I don't know how to do it using filters based on condition:
List<InvalidArgumentException> invalidEx = e.getInvalidException();
return invalidEx.stream()
.filter (ic -> {
if(ic.getInvalidExcepType().equals(ExceptionType.TypeA)) {
return (RuntimeException) new TypeAException(e);
} else if (ic.getInvalidExcepType().equals(ExceptionType.TypeB))
return (RuntimeException) new TypeBException(e);
}).orElse (new TypeCException(e));
Instead of using filter, which just returns all the elements in the Stream that match the given predicate, you need to use map:
return invalidEx.stream()
.map(ic -> {
if(ic.getInvalidExcepType().equals(ExceptionType.TypeA)) {
return (RuntimeException) new TypeAException(e);
} else if (ic.getInvalidExcepType().equals(ExceptionType.TypeB)) {
return (RuntimeException) new TypeBException(e);
} else {
return new TypeCException(e);
}
}).collect(Collectors.toList());
(Or some other terminal operation)
As others said, you want to use map instead of filter, on the other hand if you have a lot of possible ExceptionTypes and want to create something that resolves them without a really long chain of ifs, I believe you could create something like this.
class ExceptionResolver {
private static Map<ExceptionType, Function<InvalidArgumentException, RuntimeException>> exceptionMapping = new HashMap<>();
static {
exceptionMapping.put(ExceptionType.TypeA, TypeAException::new);
exceptionMapping.put(ExceptionType.TypeB, TypeBException::new);
}
static RuntimeException resolveException(ExceptionType type, InvalidArgumentException e) {
return exceptionMapping.get(type).apply(e);
}
}
And then use it like this
List<InvalidArgumentException> invalidEx = e.getInvalidException();
return invalidEx.stream()
.map(f -> ExceptionResolver.resolveException(f.getInvalidExceptionType(), f));
Suppose I have a function with such signature:
public static <T> List<Future<T>> invokeAll(Stream<Callable<T>> tasks) {
... submit given tasks using executor ...
}
and I have a stream of data, which should be "wrapped" into callable and passed to this function. Naive mapping like below does not work:
Stream<String> ids = Stream.of("1", "2", "3");
invokeAll(ids.map((id) -> {
// Do a long computation with given ID...
return Boolean.TRUE; // Compilation error: Type mismatch: cannot convert from Boolean to Callable<Object>
}));
One solution would be to return lambda that returns lambda:
invokeAll(ids.map((id) -> {
return () -> {
// Do a long computation with given ID...
return Boolean.TRUE;
};
}));
another (in some way equivalent) is to use helper function:
public static <T> Callable<T> createCallable(T id) {
return () -> {
return id;
};
}
invokeAll(ids.map(ThisClass::createCallable));
but maybe there is better / shorter way of doing the same? E.g. somehow tell the compiler that it needs to create a Callable that returns a given value:
invokeAll(ids.map((Function<String, Callable<Boolean>>) (id) -> {
// Do a long computation with given ID
return Boolean.TRUE;
}));
Thanks for any suggestion.
Let's ignore lambdas for a moment, because I think they're the source of the confusion. Let's use good old anonymous classes:
invokeAll(
ids.map(
new Function<String, Callable<Boolean>>()
{
#Override
public Callable<Boolean> apply(String str)
{
return new Callable<Boolean>()
{
#Override
public Boolean call() throws Exception
{
return Boolean.TRUE;
}
};
}
}
)
);
What you're effectively asking is "how I can automatically do this:"
invokeAll(
ids.map(
new Function<String, Callable<Boolean>>()
{
#Override
public Callable<Boolean> apply(String str)
{
return Boolean.TRUE;
}
}
)
);
Of course, you can't. A Boolean is not a Callable<Boolean>. So the solutions are limited to what you've already identified:
1) to use a lambda to create the Callable:
() -> Boolean.TRUE
() -> { return Boolean.TRUE; }
2) to create a method which does this for you. Such as method is likely to more verbose than option #1 so it doesn't gain you anything.
Sorry, there's no way other to automagically make this any better.
I am using Java 8.
The following code is working fine:
public void testMethod(List<String> prop1, EmailJson randomModel) {
prop1.stream().forEach(s -> randomModel.getSomeList()
.removeIf(model -> model.getSomeProp().equalsIgnoreCase(s)));
}
Is it possible to log a message if the condition is true?
I'm looking for something similar to:
public void testMethod(List<String> prop1, EmailJson randomModel) {
prop1.stream().forEach(s -> randomModel.getSomeList()
.removeIf(model -> model.getSomeProp().equalsIgnoreCase(s))
- > if this is true then log some action);
}
You can always replace
removeIf(model -> model.getSomeProp().equalsIgnoreCase(s))
with
removeIf(model -> {
boolean ret = model.getSomeProp().equalsIgnoreCase(s);
if (ret) {
// add logging
}
return ret;
})
If this is a recurring problem, you may create a helper method generalizing the task of decorating a predicate with another action, e.g. logging:
static <T> Predicate<T> logging(Predicate<T> p, BiConsumer<T,Boolean> log, boolean all) {
return t -> {
final boolean result = p.test(t);
if(all || result) log.accept(t, result);
return result;
};
}
which you may use like
public void testMethod(List<String> prop1, EmailJson randomModel){
prop1.forEach(s -> randomModel.getSomeList()
.removeIf(logging(model -> model.getSomeProp().equalsIgnoreCase(s),
(model,b) -> LOGGER.info(() -> "matched: "+model.getSomeProp()), false)));
}
though, in this specific case, it might be unnecessary to decorate the predicate itself, as removeIf return a boolean telling whether there were matches to remove, and the match value is still in scope:
public void testMethod(List<String> prop1, EmailJson randomModel){
prop1.stream().forEach(s -> {
if(randomModel.getSomeList()
.removeIf(model -> model.getSomeProp().equalsIgnoreCase(s)))
LOGGER.info(() -> "there were matches of: "+s);
});
}
I have task to change this if:
if (userDecision.equalsIgnoreCase("D")) {
return DirectoriesActivity.DELETE;
} else if (userDecision.equalsIgnoreCase("R")) {
return DirectoriesActivity.REPLACE;
} else {
return DirectoriesActivity.ADD_NEW_CONTENTS;
}
On something what will return just enum without using if. I have to use some enum properties but I don't know which one :/ Here is my enum:
public enum DirectoriesActivity {
DELETE,
REPLACE,
ADD_NEW_CONTENTS;
}
I tried to do something like this:
public enum DirectoriesActivity {
DELETE ("D"),
REPLACE ("R"),
ADD_NEW_CONTENTS ("A");
private String directoriesActivityCode;
private DirectoriesActivity(String directoriesActivityCode) {
this.directoriesActivityCode = directoriesActivityCode;
}
public DirectoriesActivity getEnum(String x){
//no idea what to do here
}
}
Or maybe somebody have some other idea?
You can add a Map lookup.
static Map<String, DirectoriesActivity> lookup = new HashMap<>();
static {
// iterate over all the values and
// put the value we want to lookup as the key to the map.
for(DirectoriesActivity da: values())
lookup.put(da.directoriesActivitCode, da);
}
public static DirectoriesActivity lookup(String s) {
// lookup the map we built in the static block.
return s == null ? null : lookup.get(s.toUppercase());
}
This way you can add as many codes as you want without having to change the code.
How about this:
public enum DirectoriesActivity {
DELETE ("D"),
REPLACE ("R"),
ADD_NEW_CONTENTS ("A");
private String directoriesActivityCode;
private DirectoriesActivity(String directoriesActivityCode) {
this.directoriesActivityCode = directoriesActivityCode;
}
public DirectoriesActivity getEnum(String x){
for (DirectoriesActivity directoriesActivity : values()) {
if (directoriesActivity.directoriesActivityCode.equals(x)) {
return directoriesActivity;
}
}
throw new IllegalArgumentException("Unknown value " + x);
}
}
Or in case you are using Java 8
return Arrays.stream(DirectoriesActivity.values())
.filter(directoriesActivity -> directoriesActivity.directoriesActivityCode.equals(userDecision))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unknown value " + userDecision));
Important side note here is that this solution is performing a lot worse than the solution provided by Peter. But as long as performance is not an issue, I'd prefer a solution like this.
If you can change enum names to D, R, A then you can use built-in feature:
public enum DirectoriesActivity {D,R,A}
DirectoriesActivity activity = DirectoriesActivity.valueOf("D");
valueOf throws IllegalArgumentException if string is not match.
I was reading an article linked from a slashdot story, and came across this little tidbit:
Take the latest version of Java, which
tries to make null-pointer checking
easier by offering shorthand syntax
for the endless pointer testing. Just
adding a question mark to each method
invocation automatically includes a
test for null pointers, replacing a
rat's nest of if-then statements, such
as:
public String getPostcode(Person person) {
String ans= null;
if (person != null) {
Name nm= person.getName();
if (nm!= null) {
ans= nm.getPostcode();
}
}
return ans
}
With this:
public String getFirstName(Person person) {
return person?.getName()?.getGivenName();
}
I've scoured the internet (okay, I spent at least 15 minutes googling variations on "java question mark") and got nothing. So, my question: is there any official documentation on this? I found that C# has a similar operator (the "??" operator), but I'd like to get the documentation for the language I'm working in. Or, is this just a use of the ternary operator that I've never seen before.
Thanks!
EDIT: Link to the article: http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292
The original idea comes from groovy. It was proposed for Java 7 as part of Project Coin: https://wiki.openjdk.java.net/display/Coin/2009+Proposals+TOC (Elvis and Other Null-Safe Operators), but hasn't been accepted yet.
The related Elvis operator ?: was proposed to make x ?: y shorthand for x != null ? x : y, especially useful when x is a complex expression.
This syntax does not exist in Java, nor is it slated to be included in any of the upcoming versions that I know of.
[EDIT]
Upon further thought, I figured out that it is actually possible to achieve the same only using standard Java 8 classes:
public String getFirstName(Person person) {
return Optional.ofNullable(person)
.map(Person::getName)
.map(Name::getGivenName)
.orElse(null);
}
In this case, it is even possible to choose a default value (like "<no first name>") instead of null by passing it as parameter of orElse.
[Original Answer]
One way to workaround the lack of "?" operator using Java 8 without the overhead of try-catch (which could also hide a NullPointerException originated elsewhere, as mentioned) is to create a class to "pipe" methods in a Java-8-Stream style.
public class Pipe<T> {
private T object;
private Pipe(T t) {
object = t;
}
public static<T> Pipe<T> of(T t) {
return new Pipe<>(t);
}
public <S> Pipe<S> after(Function<? super T, ? extends S> plumber) {
return new Pipe<>(object == null ? null : plumber.apply(object));
}
public T get() {
return object;
}
public T orElse(T other) {
return object == null ? other : object;
}
}
Then, the given example would become:
public String getFirstName(Person person) {
return Pipe.of(person)
.after(Person::getName)
.after(Name::getGivenName)
.get();
}
Java does not have the exact syntax but as of JDK-8, we have the Optional API with various methods at our disposal. So, the C# version with the use of null conditional operator:
return person?.getName()?.getGivenName();
can be written as follows in Java with the Optional API:
return Optional.ofNullable(person)
.map(e -> e.getName())
.map(e -> e.getGivenName())
.orElse(null);
if any of person, getName or getGivenName is null then null is returned.
There was a proposal for it in Java 7, but it was rejected:
http://tech.puredanger.com/java7/#null
See: https://blogs.oracle.com/darcy/project-coin:-the-final-five-or-so (specifically "Elvis and other null safe operators").
The result is that this feature was considered for Java 7, but was not included.
That's actually Groovy's safe-dereference operator. You can't use it in pure Java (sadly), so that post is simply wrong (or more likely slightly misleading, if it's claiming Groovy to be the "latest version of Java").
As lot of answers mentioned Java language don't have this feature.
It is possible in few scenarios with this compiler plugin, with few limitations
In the example code you mentioned can be written as
public String getFirstName(Person person) {
#NullSafe
String retVal = person.getName().getGivenName();
return retVal;
}
PS: I am author of plugin
It is possible to define util methods which solves this in an almost pretty way with Java 8 lambda.
This is a variation of H-MANs solution but it uses overloaded methods with multiple arguments to handle multiple steps instead of catching NullPointerException.
Even if I think this solution is kind of cool I think I prefer Helder Pereira's seconds one since that doesn't require any util methods.
void example() {
Entry entry = new Entry();
// This is the same as H-MANs solution
Person person = getNullsafe(entry, e -> e.getPerson());
// Get object in several steps
String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
// Call void methods
doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());
}
/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
if (o1 != null) return f1.apply(o1);
return null;
}
public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
return getNullsafe(getNullsafe(o0, f1), f2);
}
public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
return getNullsafe(getNullsafe(o0, f1, f2), f3);
}
/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
if (o1 != null) f1.accept(o1);
}
public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
doNullsafe(getNullsafe(o0, f1), f2);
}
public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
doNullsafe(getNullsafe(o0, f1, f2), f3);
}
class Entry {
Person getPerson() { return null; }
}
class Person {
Name getName() { return null; }
}
class Name {
void nameIt() {}
String getGivenName() { return null; }
}
I'm not sure this would even work; if, say, the person reference was null, what would the runtime replace it with? A new Person? That would require the Person to have some default initialization that you'd expect in this case. You may avoid null reference exceptions but you'd still get unpredictable behavior if you didn't plan for these types of setups.
The ?? operator in C# might be best termed the "coalesce" operator; you can chain several expressions and it will return the first that isn't null. Unfortunately, Java doesn't have it. I think the best you could do is use the ternary operator to perform null checks and evaluate an alternative to the entire expression if any member in the chain is null:
return person == null ? ""
: person.getName() == null ? ""
: person.getName().getGivenName();
You could also use try-catch:
try
{
return person.getName().getGivenName();
}
catch(NullReferenceException)
{
return "";
}
There you have it, null-safe invocation in Java 8:
public void someMethod() {
String userName = nullIfAbsent(new Order(), t -> t.getAccount().getUser()
.getName());
}
static <T, R> R nullIfAbsent(T t, Function<T, R> funct) {
try {
return funct.apply(t);
} catch (NullPointerException e) {
return null;
}
}
If someone is looking for an alternative for old java versions, you can try this one I wrote:
/**
* Strong typed Lambda to return NULL or DEFAULT VALUES instead of runtime errors.
* if you override the defaultValue method, if the execution result was null it will be used in place
*
*
* Sample:
*
* It won't throw a NullPointerException but null.
* <pre>
* {#code
* new RuntimeExceptionHandlerLambda<String> () {
* #Override
* public String evaluate() {
* String x = null;
* return x.trim();
* }
* }.get();
* }
* <pre>
*
*
* #author Robson_Farias
*
*/
public abstract class RuntimeExceptionHandlerLambda<T> {
private T result;
private RuntimeException exception;
public abstract T evaluate();
public RuntimeException getException() {
return exception;
}
public boolean hasException() {
return exception != null;
}
public T defaultValue() {
return result;
}
public T get() {
try {
result = evaluate();
} catch (RuntimeException runtimeException) {
exception = runtimeException;
}
return result == null ? defaultValue() : result;
}
}
You can test the code which you have provided and it will give syntax error.So, it is not supported in Java.
Groovy does support it and it was proposed for Java 7 (but never got included).
However, you can use the Optional provided in Java 8. This might help you in achieving something on similar line.
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Example Code for Optional
STEP-1 : Use this generic method.
public static <T> Optional<T> optionalChaining(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
} catch (NullPointerException e) {
return Optional.empty();
}
}
STEP-2 one example of usage of this method is below
Optional<String> rs = optionalChaining(()-> user.getName("Talha").getLastName());
if(rs.isPresent()) {
}
Done !!
Since Android does not support Lambda Functions unless your installed OS is >= 24, we need to use reflection.
// Example using doIt function with sample classes
public void Test() {
testEntry(new Entry(null));
testEntry(new Entry(new Person(new Name("Bob"))));
}
static void testEntry(Entry entry) {
doIt(doIt(doIt(entry, "getPerson"), "getName"), "getName");
}
// Helper to safely execute function
public static <T,R> R doIt(T obj, String methodName) {
try {
if (obj != null)
return (R)obj.getClass().getDeclaredMethod(methodName).invoke(obj);
} catch (Exception ignore) {
}
return null;
}
// Sample test classes
static class Entry {
Person person;
Entry(Person person) { this.person = person; }
Person getPerson() { return person; }
}
static class Person {
Name name;
Person(Name name) { this.name = name; }
Name getName() { return name; }
}
static class Name {
String name;
Name(String name) { this.name = name; }
String getName() {
System.out.print(" Name:" + name + " ");
return name;
}
}
}
If this is not a performance issue for you, you can write
public String getFirstName(Person person) {
try {
return person.getName().getGivenName();
} catch (NullPointerException ignored) {
return null;
}
}