Shortening if() with string.equals method - java

Is there any way to shorten this if() statement? To avoid repeating string.equals() somehow?
if (extension.equals("jpg") || extension.equals("JPG") || extension.equals("png") || extension.equals("PNG") || extension.equals("bmp") || extension.equals("BMP") || extension.equals("jpeg") || extension.equals("JPEG"))
{
tmp.setIcon(new ImageIcon(getClass().getResource("/menage/Resources/imageIco.png")));
}
To something looking similar to this :
if (extension.equals(("jpg")||("JPG")||("png")||("PNG")||("bmp")||("BMP")||("jpeg")||("JPEG")))
{
tmp.setIcon(new ImageIcon(getClass().getResource("/menage/Resources/imageIco.png"));)
}
I am aware that this question looks odd, however if() with such long conditions list is unclear and requires a lot of writing as well.

Start by changing equals(...) to equalsIgnoreCase(...).
Other options, create a HashSet of lower case Strings (or upper case if desired) with your image extensions and see if it contains your String of interest, changed to lower case:
if (imageExtSet.contains(myExtension.toLowerCase()) {
}

Here is short version with predefined image types:
Set<String> imgTypes = new HashSet<>() {{
add("jpg"); add("JPG");
add("png"); add("PNG");
add("bmp"); add("BMP");
add("jpeg"); add("JPEG");
}};
public boolean isImgType(String type) {
return imgTypes.contains(type);
}

You can keep all values in a list and then asks if contains. If it's only a one liner (you don't need to ask for this condition anywhere else), you can do:
if (Arrays.asList("jpg", "JPG", "png", "PNG", "bmp", "BMP", "jpeg", "JPEG").contains(extension))
You can of course save the list as an object and then anywhere you need to ask for this condition reference it.

Use HashSet
Like this
Set<String> extSet= new HashSet<String>();
// Add All in Lower case .. to save your efforts
extSet.add("jpg");
extSet.add("png");
//...etc etc
and just check if it is present in the Set
if(extSet.contains(extension==null?null:extension.toLowerCase()))
{
/// True
}
else
{
// False
}

One thing you can do to eliminate some checks, is to convert the string to lower case:
String ext = extension.toLowerCase();
Now you have shorten the statement to:
if (ext.equals("jpg") || ext.equals("png") || ext.equals("bmp") || ext.equals("jpeg"))

if (Arrays.asList("jpg", "jpeg", "png", "bmp").contains(extension.toLowerCase))

The other answers give lots of good low-level ideas, but the basic principle here is to prevent code reuse.
If you are doing this test more than once, create a method that does the test for you:
boolean isValidImageExtenstion(String extension) {
return (extension.equals("jpg") || extension.equals("JPG") ||
extension.equals("png") || extension.equals("PNG") ||
extension.equals("bmp") || extension.equals("BMP") ||
extension.equals("jpeg") || extension.equals("JPEG"));
}
Call the method whenever you need it. If you like you can use one of the approaches described in the other answers within the method, (and the 'ignore case' suggestion is certainly worth it) but the rest become less important now that you have prevented the code repetition. As a bonus, if you decide you want to support gif extensions you only have to make the change in one place.
The advantages of this approach over the others are that it is self-documenting. It's pretty obvious what the method does, and some of the other answers are pretty obscure.
If you are only doing this once, and don't intend to do it again, then you have already created working code, so don't waste your time modifying working code.

Add in some methods...
private static boolean isJpeg(String ext) {
return java.util.Arrays.asList("jpg", "jpeg").contains(ext.toLowerCase());
}
private static boolean isPng(String ext) {
return "png".equalsIgnoreCase(ext);
}
private static boolean isBmp(String ext) {
return "bmp".equalsIgnoreCase(ext);
}
And change it to...
else if (isJpeg(extension) || isPng(extension) || isBmp(extension))
{
tmp.setIcon(new ImageIcon(getClass().getResource("/menage/Resources/imageIco.png")));
}
The isJpeg will throw a NullPointerException if the extention is null, so ensure it's not null by adding extension != null || ... or something.
The above is slightly different for your specific case as it allows JpEg and all other mixed capitalizations to slip through. If you don't want that, use these. Plus, the below have the added benefit of never throwing NullPointerException if the extension is null.
private static boolean isJpeg(String ext) {
return java.util.Arrays.asList("jpg", "JPG", "jpeg", "JPEG").contains(ext);
}
private static boolean isPng(String ext) {
return java.util.Arrays.asList("png", "PNG").contains(ext);
}
private static boolean isBmp(String ext) {
return java.util.Arrays.asList("bmp", "BMP").contains(ext);
}

Related

Java 8 Replace two null check with Optional

Below is my code which is working as expected. But I need to replace it with Optional.ofNullable
if (getFirstData != null && getSecondData !=null {
... doing my work here
} else {
... doing my else work here
}
How can I use Optionals.ofNullable(..) to replace two AND null checks?
It may be a bit overkill, but if there's need to check multiple values for nulls, it may be done like this using Optional:
static boolean allNonNullsOptional(Object ... items) {
return Stream.of(items).map(Optional::ofNullable).allMatch(Optional::isPresent);
}
But the same may be achieved with much shorter Object::nonNull:
static boolean allNonNulls(Object ... items) {
return Stream.of(items).allMatch(Objects::nonNull);
}
Just technically what you want can be achieved the following way
if (Optional.ofNullable(getFirstData).isPresent() && Optional.ofNullable(getSecondData).isPresent() ) {
... doing my work here
} else {
... doing my else work here
}
But as other commenters have already pointed out, it does not seem wise to do so.

What is the most elegant way of doing null checks in Java

Giving an example, lets say we have a code like the one below:
String phone = currentCustomer.getMainAddress().getContactInformation().getLandline()
As we know there is no elvis operator in Java and catching NPE like this:
String phone = null;
try {
phone = currentCustomer.getMainAddress().getContactInformation().getLandline()
} catch (NullPointerException npe) {}
Is not something anyone would advise. Using Java 8 Optional is one solution but the code is far from clear to read -> something along these lines:
String phone = Optional.ofNullable(currentCustomer).flatMap(Customer::getMainAddress)
.flatMap(Address::getContactInformation)
.map(ContactInfo::getLandline)
.orElse(null);
So, is there any other robust solution that does not sacrifice readability?
Edit: There were some good ideas already below, but let's assume the model is either auto generated (not convenient to alter each time) or inside a third party jar that would need to be rebuild from source to be modified.
The "heart" of the problem
This pattern currentCustomer.getMainAddress().getContactInformation().getLandline() is called TrainWreck and should be avoided. Had you done that - not only you'd have better encapsulation and less coupled code, as a "side-effect" you wouldn't have to deal with this problem you're currently facing.
How to do it?
Simple, the class of currentCustomer should expose a new method: getPhoneNumber() this way the user can call: currentCustomer.getPhoneNumber() without worrying about the implementation details (which are exposed by the train-wreck).
Does it completely solve my problem?
No. But now you can use Java 8 optional to tweak the last step. Unlike the example in the question, Optionals are used to return from a method when the returned value might be null, lets see how it can be implemented (inside class Customer):
Optional<String> getPhoneNumber() {
Optional<String> phone = Optional.empty();
try {
phone = Optional.of(mainAddress.getContactInformation().getLandline());
} catch (NullPointerException npe) {
// you might want to do something here:
// print to log, report error metric etc
}
return phone;
}
Per Nick's comment below, ideally, the method getLandline() would return an Optional<String>, this way we can skip the bad practice of swallowing up exceptions (and also raising them when we can avoid it), this would also make our code cleaner as well as more concise:
Optional<String> getPhoneNumber() {
Optional<String> phone = mainAddress.getContactInformation().getLandline();
return phone;
}
String s = null;
System.out.println(s == null);
or
String s = null;
if(s == null)System.out.println("Bad Input, please try again");
If your question was with the object being null, you should have made that clear in your question...
PhoneObject po = null;
if(po==null) System.out.println("This object is null");
If your problem is with checking whether all the parts of the line are null, then you should have also made that clear...
if(phone == null) return -1;
Customer c = phone.currentCustomer();
if(c == null)return -1;
MainAddress ma = c.getMainAddress();
if(ma == null) return -1;
ContactInfo ci = ma.getContactInformation();
if(ci == null)return -1;
LandLine ll = ci.getLandline();
if(ll == null)return -1;
else return ll.toNumber()//or whatever method
Honestly, code that's well written shouldn't have this many opportunities to return null.

How to make complex conditions look nice and save the number of statements?

In my java application I have a huge set of conditions which decides just one action. My question is how to make it look nice (I use NetBeans so I'd prefer solution that will not be broken by its code formatting function). I'd also like to have there as low amount of if/else statements as possible, because I think it will make it faster.
My original code was a mess, so I made an action diagram:. Take a copy if you want to play with it. Please keep in mind that the diagram is not perfect as to UML syntax, partly because I made it using google docs.
This is the code:
if (!config.get("checkForSpecials") || event.isNotSpecial()) {
if (config.get("filterMode").equals("blacklist")) {
if (!itemFilter.contains(event.getItem().getName())) {
item.process();
}
} else if (config.get("filterMode").equals("whitelist")) {
if (itemFilter.contains(event.getItem().getName())) {
item.process();
}
} else {
item.process();
}
}
There are two things I don't like about it - the conditions are not too clear (especially when I unfold full method names and config strings), and the fact that the process method call is there three times.
Factoring booleans out and caching return values from method calls can help clarify code.
In addition, plotting all the outcomes on a logic table can help. I use this tool to help.
With the linked tool:
A: config.get("filterMode").equals("blacklist")
B: config.get("filterMode").equals("whitelist")
C: filterContainsName (see below)
The tool churns out:
(!A && !B) || (!A && C) || (A && !C)
Which leads to the code below (with a small tweak that replaces (!A && C) with (B && C)):
boolean filterContainsName = itemFilter.contains(event.getItem().getName());
boolean useBlacklist = config.get("filterMode").equals("blacklist");
boolean useWhitelist = config.get("filterMode").equals("whitelist");
if (!config.get("safeMode") || event.isSafe()) {
if((!useBlackList && !useWhiteList) ||
( useWhiteList && filterContainsName) ||
( useBlackList && !filterContainsName)) {
item.process();
}
}
Use maps. The key of the map is the condition/case, the value is a single method class/anonymouse interface that contains the logic for that condition. Whenever you encounter a certain condition/case, you simply do a lookup in the map and execute the related function. This way you can even split up your logic-by-condition into seperate classes (if needed for sake of code beauty). As an added bonus you'll probably gain a performance bonus when the # of conditions > 10.
Looks good as it is to me. Perhaps you can isolate the valid conditions for calling item.process() to a method to make it more easier to understand.
if (!config.get("safeMode") || event.isSafe()) {
if (isItemValidForProcess(config, itemFilter, event)) {
item.process();
}
}
boolean isItemValidForProcess(config, itemFilter, event) {
String filterMode = config.get("filterMode");
if (filterMode.equals("whitelist")) {
return itemFilter.contains(event.getItem().getName());
}
if (filterMode.equals("blacklist")) {
return !itemFilter.contains(event.getItem().getName());
}
return true;
}
Believe it or not, the diagram is not that complex:)
There is no loop, and it is rather linear.
Here's a pseudo code that implements it
void action()
if <sort out specials>
if <is it special>
return;
if <check for unsafe items>
if not <safe items list contains item>
return;
if <filter status = on>
if < filter mode = whitelist>
if not <item is on filter>
return;
else // black list
if not <item is on filter>
return;
// finally!
[process item]
For really complex diagram, the answer is ... goto ...

Chaining order in Guava

I'm a bit new to Guava and it's style. I'm definitely digging it, but one thing I keep tripping over is the order of chained methods. Where I seem to have this problem the most is when using compound Orderings. I have to keep asking myself questions like:
Where does the natural go?
Where does the nullFirst (or last) go?
Which nullsFirst does what? (In the example below, one for host, one for last name, one for first name?)
Here's an example of one that I was just working on. It looks cumbersome, and I'm just not sure if I put it all together right. I have some JUnits to test it, and it seems okay, but there are always those quirky boundary cases.
Ordering<Host> lastNameThenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
public String apply(Host host) {
return host.getLastName();
}}).compound(Ordering.natural().nullsFirst().onResultOf(new Function<Host, String>() {
public String apply(Host host) {
return host.getFirstName();
}})).nullsFirst();
As for an actual question: Is there a well-defined rule for how these things get executed? It seems to be last-to-first, but I'm having trouble telling that.
edit: Just wanted to point out the large, ugly code I was trying to replace:
Ordering<Host> ordering2 = new Ordering<Host>() {
public int compare(Host host1, Host host2) {
if (host1 == null || host2 == null) {
return host1 == host2 ? 0 : ((host1 == null) ? -1 : 1);
}
if(host1.getLastName() != null || host2.getLastName() != null){
if (host1.getLastName() == null) {
return -1;
} else if (host2.getLastName() == null) {
return 1;
}
if (host1.getLastName().compareTo(host2.getLastName()) != 0) {
return host1.getLastName().compareTo(host2.getLastName());
}
}
if (host1.getFirstName() == null) {
return -1;
} else if (host2.getFirstName() == null) {
return 1;
}
return host1.getFirstName().compareTo(host2.getFirstName());
}};
I think what you do is correct, but awfully ugly. Try this for readability:
Use an Enum
Move the functions to an enum that implements Function<Host, String>. Each of the enum items can provide it's own implementation.
enum HostFunctions implements Function<Host, String>{
GETFIRSTNAME{
#Override
public String apply(final Host host){
return host.getFirstName();
}
},
GETLASTNAME{
#Override
public String apply(final Host host){
return host.getLastName();
}
}
}
Indent your Code
Now reference those enum functions and indent your code properly. This is what it will look like:
final Ordering<Host> orderingByLastAndFirstName =
Ordering
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETLASTNAME)
.compound(
Ordering
.natural()
.nullsFirst()
.onResultOf(HostFunctions.GETFIRSTNAME))
.nullsFirst();
I'd say that makes everything much more understandable.
IDE Configuration
Regarding proper indentation (at least if you use Eclipse), see this question:
How to indent the fluent interface
pattern “correctly” with eclipse?
Enums as Functions
Regarding the enum: this is called the enum singleton pattern. The Guava guys use it all over their code base. Read about it on wikipedia or in Effective Java, Item 3. Although those sources both talk about single-item enums, the approach is almost the same here.
Each chaining call is "wrapping" the previous ordering into a new one, so you're right, the execution order can be thought of as "backwards".
I wrote and reviewed the Ordering class and I still regularly have to stop and scratch my head over the correct interleaving of nullsFirst(), and onResultOf() and reverse()!
The following would be my preference for doing this, assuming you must be able to handle null hosts, first names and last names. To me, it seems like a non-null first name and last name ought to be a requirement of the Host class. And you should generally try to avoid allowing collections to contain null objects.
Ordering<Host> lastNameFirstNameOrdering = new Ordering<Host>() {
#Override public int compare(Host left, Host right) {
return ComparisonChain.start()
.compare(left.getLastName(), right.getLastName(), Ordering.natural().nullsFirst())
.compare(left.getFirstName(), right.getFirstName(), Ordering.natural().nullsFirst())
.result();
}
}.nullsFirst();
Alternatively, I'd take an approach similar to Sean's but break things down for readability.
Ordering<Host> lastNameOrder = Ordering.natural().nullsFirst()
.onResultOf(Host.LAST_NAME);
Ordering<Host> firstNameOrder = Ordering.natural().nullsFirst()
.onResultOf(Host.FIRST_NAME);
Ordering<Host> orderingByLastAndFirstName =
lastNameOrder.compound(firstNameOrder).nullsFirst();
Keep in mind that you could also make these individual orderings static final fields of the class, allowing you to easily use them anywhere when sorting like Host.LAST_NAME_ORDER.

Extract Method with continue

We're refactoring a long method; it contains a long for loop with many continue statements. I'd like to just use the Extract Method refactoring, but Eclipse's automated one doesn't know how to handle the conditional branching. I don't, either.
Our current strategy is to introduce a keepGoing flag (an instance variable since we're going to want to extract method), set it to false at the top of the loop, and replace every continue with setting the flag to true, then wrapping all the following stuff (at different nesting levels) inside an if (keepGoing) clause. Then perform the various extractions, then replace the keepGoing assignments with early returns from the extracted methods, then get rid of the flag.
Is there a better way?
Update: In response to comments - I can't share the code, but here's an anonymized excerpt:
private static void foo(C1 a, C2 b, C3 c, List<C2> list, boolean flag1) throws Exception {
for (int i = 0; i < 1; i++) {
C4 d = null;
Integer e = null;
boolean flag2 = false;
boolean flag3 = findFlag3(a, c);
blahblahblah();
if (e == null) {
if (flag1) {
if (test1(c)) {
if (test2(a, c)) {
Integer f = getF1(b, c);
if (f != null)
e = getE1(a, f);
if (e == null) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
} else {
Integer f = getF2(b, c);
if (f != null)
e = getE2(a, f);
if (e == null) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
flag2 = true;
}
} else {
if (test3(a, c)) {
Integer f = getF2(b, c);
if (f != null)
e = getE2(a, f);
if (e == null) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
flag2 = true;
} else {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
flag2 = true;
}
}
}
if (!flag1) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
}
if (e == null) {
list.add(b);
continue;
}
List<C2> list2 = blahblahblah(b, list, flag1);
if (list2.size() != 0 && flag1) {
blahblahblah();
if (!otherTest()) {
if (yetAnotherTest()) {
list.add(b);
continue;
}
blahblahblah();
}
}
}
}
This is one of those fun ones where no single pattern will get you there.
I would work at it iteratively.
First I'd try to see if I couldn't use an early continue to remove one of those levels of ifs. It's much clearer code to check for a condition and return early (or in your case continue) than to have deeply nested ifs.
Next I think I'd take some of the inner chunks and see if they couldn't be extracted into a separate method. It looks like the first two big blocks (within the "if (test2(a, c)) {" and its else statement) are very similar. There is cut and paste logic that should be the same.
Finally after that stuff is cleared up, you can start looking at your actual problem--you need more classes. This entire statement is probably a three line polymorphic method in 3-5 sibling classes.
It's very close to throw-away and rewrite code, once you identify your actual classes, this entire method will vanish and be replaced with something so simple it hurts. Just the fact that it's a static utility method should be telling you something--you don't want one of those in this type of code.
Edit (After looking a little more):
There is so much here it would be really fun to go through. Remember that when you are done you want no code duplication--and I'm pretty sure this entire thing could be written without a single if--I think all your ifs are cases that could/should easily be handled by polymorphism.
Oh, and as an answer to your question of eclipse not wanting to do it--don't even TRY automatic refactoring with this one, just do it by hand. The stuff inside that first if() needs to be pulled out into a method because it's virtually identical to the clause in its else()!
When I do something like this, I usually create a new method, move the code from the if into the new method (leaving just a call to the new method inside the if), then run a test and make sure you didn't break anything.
then go line by line and check to ensure there is no difference between the if and its else code. If there is, compensate for it by passing the difference as a new variable to the method. After you're sure everything is identical, replace the else clause with a call. Test again. Chances are at this point a few additional optimizations will become obvious, you'll most likely lose the entire if by combining it's logic with the variable you passed to differentiate the two calls.
Just keep doing stuff like that and iterating. The trick with refactoring is to use Very Small Steps and test between each step to ensure nothing changed.
continue is basically an analogue of an early return, right?
for (...) {
doSomething(...);
}
private void doSomething(...) {
...
if (...)
return; // was "continue;"
...
if (!doSomethingElse(...))
return;
...
}
private boolean doSomethingElse(...) {
...
if (...)
return false; // was a continue from a nested operation
...
return true;
}
Now I must admit that I didn't quite follow your current strategy, so I might have just repeated what you said. If so, then my answer is that I can't think of a better way.
If I were faced with your situation I would look at using other refactoring techniques such as "replace conditional with polymorphism". That said you should always do one thing at a time, so if you first want to extract method you have two options:
Add the "keepGoing" flag
Throw an exception from the method
Of these two options, I think the keepGoing flag is better. I wouldn't stop refactoring after you extract the method. I am sure once you have a smaller method you will find a way to remove this flag and have cleaner logic.
I'm going to summarize the answers here, while accepting Bill K's answer as the most complete. But everyone had something good to offer, and I might use any of these approaches next time I'm faced with this sort of situation.
mmyers: Cut out the loop body, paste it into a new method and replace all the continues with returns. This worked very nicely, although it would have trouble if there were other control flow statements, like break and return, inside the loop.
Bill K: Tease it apart iteratively; look for duplication and eliminate it. Take advantage of polymorphic classes to replace the conditional behavior. Use Very Small Steps. Yes; this is all good advice, with broader applicability than just this specific case.
Aaron: Either use the keepGoing flag to replace the continue or throw an Exception. I didn't try this, but I think the Exception option is a very nice alternative, and one I hadn't considered.

Categories

Resources