I don't really do Java. But this looks like infrequently executed code that you should be optimizing for readability vs. trying to minimize the number of comparisons.
Imagine being in the position of someone maintaining the code after a directive like "we've decided not to support versions prior to 4." Is it completely clear which part they can delete?
So how do you convey the intention of this code (essentially, a version-sensitive decision on whether or not to add an entry to arrayData based on a type?) You want to distinguish between versions prior to 4, version 4, and version 5 and above. Imagine breaking it down so each branch is clearly separated:
boolean shouldAdd = false;
WhateverType subType = entry.getSubType();
boolean isTypeA = (subType == null) ? false : subType.equals("typeA");
boolean isTypeB = (subType == null) ? false : subType.equals("typeB");
if (!isTypeA && !isTypeB)
shouldAdd = true;
if (version >= 4) {
if (isTypeA)
shouldAdd = true;
}
if (version >= 5) {
if (isTypeB)
shouldAdd = true;
}
if (shouldAdd)
arrayData.add(entry);
This approach tips toward being verbose just to float the idea of leaning away from thinking you have to collapse everything into a single if
statement. You can have complex per-version logic that sets a variable, and that variable can trigger the ultimate decision. (In this case your per-version logic is pretty simple, so it's overkill.)
If you cache the result of the type check in a boolean, it will be cheap and avoids potential mistyping of the string constant. (And if you're referring to these frequently, you should probably create a global constant... it's easy to miss and get "tpyeA"
and have no compiler checking to catch the mistake!)