I am new to java and trying to learn a better way of coding.Please let me know if I can replace the multiple OR conditions in the below ELSE IF statement with any other way to execute based on the username passed in the calling method :
public void verifyPermissions(String user, String level2, String Folder) {
if (user.equalsIgnoreCase("ABC_Username")) {
verifyXYZPermission(Folder);
verifyNoPermissionToDelete();
}
else if (user.equalsIgnoreCase("DEF_Username") || user.equalsIgnoreCase("GHI_Username")
|| user.equalsIgnoreCase("JKL_Username") || user.equalsIgnoreCase("MNO_Username")
|| user.equalsIgnoreCase("PQR_Username") || user.equalsIgnoreCase("STU_Username")
|| user.equalsIgnoreCase("VWX_Username")) {
if (user.equalsIgnoreCase("GHI_Username")) {
verifyNoPermissionToCreate(user, Folder, level2);
verifyNoPermissionToUpdate(Folder);
} else {
verifyCreatePermission(level2);
verifyPermisssionToUpdate(Folder);
}
}
}
Here's one way: define a Set<String> with the possible username values before the if block, and check against it. Notice how all the strings were lower-cased to avoid trouble:
Set<String> userNames = new HashSet<>();
userNames.add("def_username");
userNames.add("ghi_username");
userNames.add("jkl_username");
userNames.add("mno_username");
userNames.add("pqr_username");
userNames.add("stu_username");
userNames.add("vwx_username");
// assuming `user` is non-null
user = user.trim().toLowerCase();
if (user.equals("abc_username")) {
verifyXYZPermission(Folder);
verifyNoPermissionToDelete();
} else if (userNames.contains(user)) {
if (user.equals("ghi_username")) {
verifyNoPermissionToCreate(user, Folder, level2);
verifyNoPermissionToUpdate(Folder);
} else {
verifyCreatePermission(level2);
verifyPermisssionToUpdate(Folder);
}
}
Use a switch-case statement.
In the case blocks for each user you can then execute the appropriate permissions.
https://www.w3schools.com/java/java_switch.asp
user_lc=user.toLowerCase();
switch (user_lc){
case "abc_user":
//execute code
break;
case "def_user":
//execute code
break;
}
It's highly opinionated I guess. Here are various approaches I can think of:
OR as you have done, or
regex to reduce lines of code, or
switch-case, or
Using a Collection such as List or Set.
It's all based on author's choice.
Related
boolean isRoleOld,isRoleNew;
for (Relations relation : listOfRelations)
{
if (Constants.ROLE_OLD.equalsIgnoreCase(relation.getRole()))
{
isRoleOld = true;
}
if (Constants.ROLE_NEW.equalsIgnoreCase(relation.getRole()))
{
isRoleNew = true;
}
}
if (isRoleOld && isRoleNew)
{
“Success”
}else{
throw Exception();
}
What i have done yet is
if (listOfRelations.stream()
.anyMatch(relation -> Constants.ROLE_OLD.equalsIgnoreCase(relation.getRole()))
&&
listOfRelations.stream()
.anyMatch(relation -> Constants.ROLE_NEW.equalsIgnoreCase(relation.getRole())))
{
System.out.println("Success");
}
How to use streams from Java8 to optimize this code. Using a anymatch twice is not the point.
Any help will be appreciated.
You could use a stream to map to each Role, and filter to identify old/new role match, then count the distinct matches.
long count = listOfRelations.stream().map(Relations::getRole)
.filter(role -> Constants.ROLE_OLD.equalsIgnoreCase(role)
|| Constants.ROLE_NEW.equalsIgnoreCase(role))
.map(String::toLowerCase)
.distinct().count();
if (count != 2) {
throw new Exception();
}
System.out.println("Success");
However although this does only one pass through the stream it does not exit early once matched both roles so won't be ideal for large data-sets.
Actually, the solution with two .anyMatch checks is better because of short-circuiting when the required value is matched and therefore these checks may usually complete "sooner" than a full single run over the entire stream. In case ROLE_OLD value is missing, && short-circuiting occurs and no check for ROLE_NEW is executed. The worst case is when ROLE_OLD is located at the end of the input listOfRelations, and no ROLE_NEW is there.
Similar loop-based solution would use break as soon as both ROLE_OLD and ROLE_NEW have been detected; in the worst case, the collection is fully iterated one time.
I am struggling right now to check all my InputFields wether they == "".
I found many solutions here but somehow it doesnt work.
I have a RegistrationModal and a RegistrationController.
In the modal I tryed to check the fields like that:
public boolean RegisterUser(String user, String vorname, String nachname) throws SQLException {
PreparedStatement preparedStatement = null;
if (user == "" || vorname == "" || nachname == "") {
System.out.println("Fill in all fields");
return false;
}
// Here follows the SQL query the prepared statement and exequte
}
But it it never uses this if statement, I have no idea why?
I also tryed to catch the empty element in the controller:
public void Absenden(ActionEvent event) {
try {
if (registerModel.RegisterUser(txt_user.getText(), txt_vorname.getText(),
txt_nachname.getText())) {
if (registerModel.RegisterUser(txt_user.getText().trim().isEmpty(), txt_vorname.getText().trim().isEmpty(),
txt_nachname.getText().trim().isEmpty())) {
System.out.println("False! Do something?");
}
// Here opens the new window with a notification Registration was successfull
((Node) event.getSource()).getScene().getWindow().hide();
}
Here I had errors so thats why two if statement which already seems weird, I had to autogenerate a new method in model to make this work with booleans, but still it never used this if statement.
I tryed to give only relevant code, otherwise it would be much more.
Maybe someone has an idea.
Thanks
Your condition will fail if it has one or more spaces as inputs.
You should always trim() and then check if the length is 0
i.e
user.trim().length==0
also If you want to check contents always use equals instead of ==
You should have try like this
if(use.trim.length<0)
{
// todo code !!
}
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);
}
I wanted to know if there was a way to shorten this if statement with the ".equals" so that I can test things in one line, instead of multiple if statements.
This is an excerpt my current long winded code. (This is what I want to shorten)
if (queryArray[1].equals("+")) {
System.out.println("Got +");
} else if (queryArray[1].equals("-")) {
System.out.println("Got -");
} else if (queryArray[1].equals("*")) {
System.out.println("Got *");
}
I tried doing this (Does not work) to reduce the number of lines needed.
if (queryArray[1].equals("+","-","*")) {
System.out.println("Got +");
}
And even (Does not work):
if (queryArray[1].equals("+" || "-" || "*")) {
System.out.println("Got +");
}
Also, I know about the or syntax "||" within if statements, however I'm looking to shorten it within the ".equals()" method.
Is there any way to shorten this code? Thank you.
Since you're only doing single-character comparisons, you can do a switch on queryArray[1].charAt(0).
switch (queryArray[1].charAt(0)) {
case '+':
// plus thing
break;
case '-':
// minus thing
break
// ... and so on
}
Or if you're using Java 7, you can switch directly on the string.
With Java 7, you can do a switch on strings:
switch(queryArray[1]) {
case "+":
case "*":
case "-":
System.out.println("Got " + queryArray[1]);
break;
default:
// do nothing
}
you can even do it in this way
List<String> list = Arrays.asList("+","-","*");
if(list.contains(queryArray[1]))
System.out.println("Got "+queryArray[1]);
First off your alternative syntax inside the .equals() isn't valid Java.
Unless you have way more than a few tests and each one of them has lots of cyclomatic complexity in each condition, there isn't any compelling reason to do what you are asking.
That said, you need to flip the problem on its head and do something like the following:
interface Handler { public void handle(); }
final Map<String, Handler> symbols = new HashMap<String, Handler>();
symbols.put("+", new Handler() {
public void handle() { System.out.println("Got +"); }
};
symbols.put("-", new Handler() {
public void handle() { System.out.println("Got -"); }
};
symbols.put("*", new Handler() {
public void handle() { System.out.println("Got *"); }
};
Then the logic tests are reduced to:
symbols.get(queryArray[1]).handle();
This won't be any faster than the individual if/elseif/else construct, but it does something like you are looking for to reduce the lines of code.
This is a common Object Oriented Design pattern, it is a variation on the Chain of Responsibility Pattern.
It is very useful when there are many alternatives in an if/elseif/else construct and the logic in each alternative is complicated.
It makes adding alternatives simple as implementing the interface and adding the alternative to the Map.
It also makes maintenance a very easy as well. Because it promotes Encapsulation of the rules and Cohesion of the logic. Something that is gets completely lost in very large if/elseif/else blocks.
You don't have to use Anonymous Inner Classes as in my example, they can be regular classes that are in their own files or regular Inner Classes.
Try this
Map<String,String> resultMap = new HashMap<String,String>();
resultMap.put("+","Got +");
resultMap.put("-","Got -");
resultMap.put("*","Got *");
System.out.println(resultMap.get(queryArray[1]));
The code block you provided is the most effecient and more readable. and if considered scalabilty and maintenance, it shouldn't be refactore if logic doesn't change.
if (queryArray[1].equals("+"))
{
System.out.println("Got +");
}
else if (queryArray[1].equals("-"))
{
System.out.println("Got -");
}
else if (queryArray[1].equals("*"))
{
System.out.println("Got *");
}
However Borealid has given switch-case construct but a little bit of logic change will initiate a lot of changes and probably bugs-crawling also.
Well, I'm too providing a solution on same lines, but it's also not better than the code you provided:
System.out.println(queryArray[1].equals("+")?"Got +"
:queryArray[1].equals("-")?"Got -"
:queryArray[1].equals("*")?"Got *"
:"");
if your problem is that method size is increasing, try creating a separate method which returns a string (to be printed), so the equals-comparison method can be moved to a separate block.
And, one more thing to say, the || and && operators should be used with boolean operands. and, before calling an API check it's javadoc: equals
On a single line ...
if (Arrays.asList("+", "-", "*").contains(queryArray[1])) {
System.out.println("BINGO!");
}
This works because asList has a varargs parameter.
However, this code involves creating and initializing a new String[], wrapping it in a new List and then iterating over the list. So don't do it if performance is likely to be a concern.
Something even more obscure:
char a = queryArray[1].charAt(0);
if ((a - '*') * (a - '+') * (a - '-') == 0) {
/* process here. */
}
Rather useless if you want to compare more than one character, though.
The shortest Java-solution I can think of is:
System.out.println (Arrays.asList ("+", "-", "*").contains ("-"));
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.