Choosing non null attributes - java

I have an object with 3 attributes, where only one can be not null. I would like to call a methode with the argument that is not null but if possible without a large if else statement.
I thought of something like this, but it doesn't work.
myMethode(myObj.getAttr1() || myObj.getAttr2() || myObj.getAttr3());
What would be a good solution?

One option is to stream the attributes and filter the first (presumably, only) non-null one:
myMethod(Stream.of(myObj.getAttr1(), myObj.getAttr2(), myObj.getAttr3())
.filter(Objects::notNull)
.findFirst()
.orElse(null) // Or perhaps throw an exception?
);

|| is a logical or operator and can be used only between two boolean types, which is why your code doesn't work.
myMethode(myObj.getAttr1() != null ? myObj.getAttr1() :
myObj.getAttr2() != null ? myObj.getAttr2() :
myObj.getAttr3() != null ? myObj.getAttr3() : null);

if your object only 3 attributes , you can use reflection like below
final long notNullAttributeCount = Arrays.stream(myObj.getClass().getFields())
.map(f -> {
try {
f.setAccessible(true);
return f.get(myObj);
} catch (IllegalAccessException e) {
return null;
}
}).filter(Objects::nonNull).count();
if (notNullAttributeCount == 1) {
//do your staff
}

Related

Java 8 Optional: combine two possibly null object

I have to ensure if two values are non null. When the first and second have non null values, pass first as argument to second. If one of them are null value, then return false.
This can be done in the following piece of code:
String value1 = function_to_get_value1()
if (value1 == null) return false;
String value2 = function_to_get_value2(value1)
if (value2 == null) return false;
return true;
It can also be done in short form:
try {
return function_to_get_value2(function_to_get_value1()) != null;
} catch (NullPointerException e) {
return false;
}
I was wondering how to do this in fluent form with Optional.
You could try something like this:
return Optional.ofNullable(function_to_get_value1())
.map(v1 -> function_to_get_value2(v1))
.isPresent();
map() applies the lambda if value is present and returns a new Optional.ofNullable() or otherwise returns an empty Optional. So in the end you have an empty Optional if either value was null or a non-empty one.
If you have a look at the source code for those methods, it basically is equivalent to this:
//Optional.ofNullable(...)
Optional<UiObject> v1Opt = value1 == null ? Optional.empty() : Optional.of(value1);
//Optional.map(...)
Optional<UiObject> v2Opt;
if(v1Opt.isPresent()) {
//this is the lambda
UiObject value2 = function_to_get_value2(value1);
//Optional.ofNullable(...) called in map(...)
v2Opt = value2 == null ? Optional.empty() : Optional.of(value2);
} else {
v2Opt = Optional.empty();
}
//Optional.isPresent()
return v2Opt.value != null;

How to compare an Integer using least code?

There is an Integer property called foo in a model. Now I need to know whether it equals 1 or 2. Usually I use:
if (null != model) {
Integer foo = model.getFoo();
if (foo != null) {
if (foo == 1) {
// do something...
}
if (foo == 2) {
// do something...
}
}
}
Is there any handier code to avoid the NullPointerException?
You can use Optional:
Optional.ofNullable(model)
.map(Model::getFoo)
.ifPresent(foo -> {
switch (foo) { // or if-else-if, the important thing is you skip the null check
case 1:
...
break;
case 2:
...
break;
...
}
});
You can use the null-safe java.util.Object.equals:
if(null != model) {
Integer foo = model.getFoo();
if(Objects.equals(foo, 1){
//do something
}
if(Objects.equals(foo, 2){
//do something
}
}
The method has this description:
Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.
If you didn't return null sentinels values, and instead used Optionals, you could do:
Optional<Model> model = getModel();
Optional<Integer> foo = model.flatMap(Model::getFoo);
foo.filter(Integer.valueOf(1)::equals).ifPresent(this::doSomething);
foo.filter(Integer.valueOf(2)::equals).ifPresent(this::doSomethingElse);
You could do Integer.of(1).equals(foo), but this is a bit silly. Why save the one line? I'd just put it inside the same if/else-if chain (and if that gets long, conside a switch/case (which also is not null-safe, though).
if (foo == null)
else if (foo == 1)
else if (foo == 2)
Also note that comparing objects with == is a bit tricky because of how auto-boxing works (or does not work). I think that it works in this case, but I do not want to have to think about it too hard, so in my code I usually drop down to int (after the null check) to be on the safe side.
Assuming possible value is only 1 or 2
Of course the model the should be guarded with null check
Use ternary operator
Model theModel = model.getFoo() ;
if(model!=null && model.getFoo()!=null){
model.getFoo() == 1 ? callOne() : call2();
}
Edit the code to like this:
if (null != model) {
Integer foo = model.getFoo();
if (Integer.valueOf(1).equals(foo)) {
// do something...
}
if (Integer.valueOf(2).equals(foo)) {
// do something...
}
}
I hope to help you.

How to prevent the error: null > 0 java

I currently have an enumlist. The enumlist gets filled at random, so there is a possibility that one has the value null. That is logical because it doesn't get filled.
The problem is further in my code I have:
if (player.Enumlist().get(CART_BLACK) > 0) {
}
Java throws a NullPointerException. Is there something I could add to the if-statement to prevent this error?
If get(CART_BLACK) may return null:
Get the value before the condition and replace it with a negative value if it's null:
Integer cartBlack = player.Enumlist().get(CART_BLACK);
if (cartBlack == null) cartBlack = -1;
if (cartBlack > 0) {
If player.Enumlist() may return null
Similar, but not quite identical:
final Enumlist list = player.Enumlist();
final int cartBlack = list == null ? -1 : list.get(CART_BLACK);
if (cartBlack > 0) {
You'll need to guard against nullity:
if(player.Enumlist().get(CART_BLACK) != null &&
player.Enumlist().get(CART_BLACK) > 0) {...}
or a more efficient version:
Integer temp = player.Enumlist().get(CART_BLACK);
if (temp != null && temp > 0){...}
if( player.Enumlist().get(CART_BLACK) != null && player.Enumlist().get(CART_BLACK) > 0) {
}
This will work because ifs are checked from left to right, and if one condition fails the rest won't be evaluated and you won't get the NPE.
Correcting the issue at the end makes the trick but it is not fine because it means that it may occur in other invocations. Besides, as a consequence, you may finish by overusing not null guards as you will never know if the null is a normal case.
So you should favor the use of Optional (Java 8 or Guava) as return rather than null to make your API clearer (it may return an empty thing so convey that) and more robust (the contained object has to be specifically unwrapped).
For example :
Optional<Integer> optValue = player.Enumlist().get(CART_BLACK);
optValue.filter(v -> v > 0)
.ifPresent( v -> ...);
You need to do Null Checking:
if (player == null || player.Enumlist () == null) {
throw new Exception("Player or Enumlist cannot be null");
}
You should also check that the Integer value is not null, but I guess that would be pretty weird if you wrote the code.
You are using get which could give you an IndexOutOfBoundsException eventually. You could check that using the size method or using streams.
If (player.Enumlist().size() > CART_BLACK && player.Enumlist().get(CART_BLACK) != null && player.Enumlist().get(CART_BLACK) > 0) {
//...
}
You may check for Null also handle the exception using try..catch block
try
{
if( player.Enumlist().get(CART_BLACK)!=null && player.Enumlist().get(CART_BLACK) > 0)
{
}
}
catch(NullPointerException)
{
//handle exception here
}

A more elegant approach to multiple checks performed in java class?

I have the below conditions to check which I will be checking based on the value that I will be recieving on parameter incomingProduct, So, I have below multiple conditions but they look odd as every time multiple checks wil be performed please advise how can i customise the below checks with else if I can acheive the same thing.
String incomingProduct = wokerchoice.getProduct();
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("CD") ) {
wokerchoice.setFourceSystem
((String)configuration.getConfiguration().get("CD"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("MODITY") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("MODITY"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("WQEQD") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("WEREQD"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("QRTFI") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("WERFI"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("URES") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("V"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("FXQWNM") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("FXQWNM"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("IERTRD") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("IERTRD"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("UHVMM") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get(UHV"MM"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("OPT") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("OPT"));
}
if (incomingProduct!= null && incomingProduct.equalsIgnoreCase("RECE") ) {
wokerchoice.setFourceSystem((String)configuration.getConfiguration().get("RECS"));
}
Since yours aren't the same, the usual thing to do is to put the incoming and outgoing mappings on a map:
Map<String, String> ht = new HashMap<String, String>(){ { put("ONE","ONE");
put("OTHER","TWO");} };
String cfg = ht.get(incomingProduct.toUpperCase());
if (cfg != null)
wokerchoice.setFourceSystem((String)configuration
.getConfiguration().get(cfg));
Sadly java doesn't yet give us the ability to declare literal maps so I used the ugly anonymous class hack you see above to get a one liner.
If you could get the incoming and outgoing mappings the same (which I recommend, though it might not be possible), you could use a list or array of strings instead.
String[] mapping = {"ONE", "TWO"};
String incoming = incomingProduct.toUpperCase();
if(Arrays.asList(mapping).contains(incoming)){
wokerchoice.setFourceSystem((String)configuration
.getConfiguration().get(incoming));
}
But really; assuming getConfiguration().get() returns a null if there is no value (and you can get rid if the mapping step), the best answer looks something like so:
String incoming = incomingProduct.toUpperCase();
Object cfg= configuration.getConfiguration().get(incoming);
If (cfg != null)
wokerchoice.setFourceSystem((String)cfg);

java find the smallest of two numbers coming from two different object types when one can be null

I'm trying to figure out the best way of grabbing the smallest of two numbers when the numbers are attributes inside of two different objects. Each, but not both, of the objects can be null, which can lead to null pointer exceptions. Each object has their own getValue() method, which will return a Long value. There's the basic if/else that I'd prefer not to do:
if (obj1 != null && obj2 != null) { // neither object is null
minValue = obj1.getValue() <= obj2.getValue() ? obj1.getValue() : obj2.getValue();
} else if (obj1 == null && obj2 != null) { // only obj1 is null
minValue = obj2.getValue();
} else { // only obj2 is null (they can't both be null, so we don't need an if for the situation where they're both null)
minValue = obj1.getValue();
}
I've tried some other things:
// can throw null pointer exception
Collections.min(Arrays.asList(obj1.getValue(), obj2.getValue()));
// while both objects have a getValue() method, they are of different types, so mapping doesn't work
Collections.min(Arrays.asList(obj1, obj2)
.filter(obj -> obj != null)
.map(obj -> obj.getValue()) // this line will fail since the methods correspond to different objects
.collect(Collectors.toList()));
I feel like this should be a fairly easy problem, but my brain's not allowing it to work. There's due to be some min function where you can bipass a situation where the object can be null?
long minValue = Math.min(obj1 == null ? Long.MAX_VALUE : obj1.getValue(),
obj2 == null ? Long.MAX_VALUE : obj2.getValue());
I am not sure I fully understand your question, but if I do, something like this could work:
if(obj1 == null)
minValue = obj2.getValue();
else if(obj2 == null)
minValue = obj1.getValue();
else minValue = obj1.getValue() < obj2.getValue() ? obj1.getValue() : obj2.getValue();
You could have a method that takes in your ObjType, does a null check and returns Long.MAX_VALUE, or the value if it's null.
public Long getVal(ObjType val)
{
if(val != null)
{
return val.getValue();
}
return Long.MAX_VALUE;
}
then do
Math.min(obj1, obj2);

Categories

Resources