Merge this if statement with the enclosing one - java

I'm running my code on sonarqube, but it shows there's an issue with my code, saying"Merge this if statement with the enclosing one." I tried it, but still have no idea how to solve it.
if (splitStrings.length == 2) {
if (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1) {
throw new IllegalArgumentException("Invalid Input");
}
}

You could do three things:
Either you need to chain the conditions as below:
if (splitStrings.length == 2
&& (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
You could declare local variable for Integer.parseInt(splitStrings[1]) inside the first if after adding the matches condition in it.
if (splitStrings.length == 2 && splitStrings[1].matches("\\d{1,3}")) {
int val = Integer.parseInt(splitStrings[1]);
if (val > 100 || val < 1)) {
throw new IllegalArgumentException("Invalid Input");
}
}
Even though i won't recommend it, you could also suppress the warning using //NOSONAR in the line in which warning is displayed or add #SuppressWarnings("squid:S1066") at the method level.

Try this.
if (splitStrings.length == 2
&& (!splitStrings[1].matches("\\d{1,3}")
|| Integer.parseInt(splitStrings[1]) > 100
|| Integer.parseInt(splitStrings[1]) < 1)) {
throw new IllegalArgumentException("Invalid Input");
}

You should merge them by && between them and wrap the second with brackets, like:
if(splitStrings.length == 2 && (!splitStrings[1].matches("\\d{1,3}") || Integer.parseInt(splitStrings[1]) > 100 || Integer.parseInt(splitStrings[1]) < 1)){
//code here
}

Integer.parseInt may be skipped altogether if a better regexp is provided to check for the digits in the range [1..100], thus the conditions could be simplified:
if (splitStrings.length == 2 && !splitStrings[1].matches("(?!0)\\d{1,2}|100")) {
throw new IllegalArgumentException("Invalid Input");
}
Online demo of the regexp: (?!0)\d{1,2}|100 validating positive cases 0 < x <= 100
(?!0)\d{1,2} - 1 or 2 digit numbers except 0 excluded with negative lookahead (?!0): 1 - 99
|100 - OR 100

In my opinion the assertion that combining if statements makes code more readable is flawed. Often it makes sense to ask a series of questions in sequence, especially when each part is asking an essentially independent question.
This can (in direct opposition of the SonarQube assertion) make each part more readable. It also allows for correct placement of useful comments in cases where the meaning is not stupidly obvious.
Another valid reason for nested if statements would be to follow certain easily recognized coding patterns. An example would be in ASP.Net applications where Page_Load methods may often have an if (!PostBack) block, which can then contain additional logic that may include additional nested conditions. If there is only one nested condition and it is combined, later changes may need to undo that merge. (There may be a case at that point for refactoring the logic into a separate method at that point, but that is a different subject.)
The question of whether or not to combine nested if statements should be left to the discretion and good judgement of the author (and code reviewer) based on which form is more readable and/or maintainable.
In your particular case, your logic is asking two questions: (1) "Does the input have two parts?" and (2) "Is the second part valid"?
So yes, your nested if statements can be combined into a single (but logically more complex) statement, but this is not necessarily better.

Related

Java; Checking if 3 numbers are the same, and run code if they are

case "119":
PotionsUpgrade();
if(potionAttack & potionDefence & potionStrength==20){
System.out.println("You have reached the max amount of upgrades");} else{
cost=potionsUpgrade;
gold=gold-cost;}
Store(); //this is running the Store method
break;
okay this is one of my cases in my game that i am building in java. I want to figure out how to check if all three of the numbers equal 20 then to tell the player that he has reached the max amount of upgrades on the potion. Else to keep buying the upgrade.
This isn't doing what you think:
if (potionAttack & potionDefence & potionStrength==20) {
You have to be pretty specific with code, it's not going to interpret something that may intuitively sound logical. It has to be specifically logical. In this case you have three distinct logical cases you want to check. Each one individually looks like:
potionAttack == 20
So to put all three together, each one would still look like that individually:
if (potionAttack == 20 && potionDefence == 20 && potionStrength == 20) {
(Note also the use of && instead of &. Different problem in the code, but not the primary one being addressed here.)
`if(potionAttack == 20 & potionDefence == 20 & potionStrength == 20)`
The oher is the same ,but you can format it better like this
`if(potionAttack == 20 & potionDefence == 20 & potionStrength == 20){
System.out.println("You have reached the max amount of upgrades");
}
else{
cost = potionsUpgrade;
gold = gold - cost;
}`
You are using & instead of the logical and operator, &&.

Beginner Boolean compiling error

I am very new to Java (doing a beginners university module) so sorry for the probably silly question. I am trying to verify whether a ragged array is a 'tridiagonal matrix'.
It is valid if it is of length 3 at the first level and of length n − 1, n, and n − 1 at the second level. I intended to come up with a code to firstly verify the length is 3, then find the longest length array within it for n, then finally verify each length.
For whatever reason my code won't compile but I'm not seeing an error message, just a red exclamation mark on the class. I assume this means there are multiple errors. If anyone could point them out it would be a massive help.
static boolean isValidTridiagonal ( double [][] m)
{
if (double [][]=new double [3][])
{
int n = 0;
for(int i = 0; i < m.length; i++)
{
if(m[i].length > n)
{
n = m[i].length;
if( (m[0].length = n-1) && (m[1].length = n) &&(m[2].length=n-1))
{
return true
}
else
{
return false
}
}
else
{
return false
}
}
Thanks very much!
I agree with Foolish in the comments that it's helpful to use an IDE that can highlight syntax errors and other problems with the code, it really makes a huge difference. Apart from that, another general strategy is to always code in "baby steps": do only the minimal thing to test if the code works, compile and test often. And if you still have troubles, you can always comment out chunks of your code when searching for the offending bits.
Having said that, the errors that I see in your code are:
if (double [][]=new double[3][])
If you want to test the length of the input, you can do if (m.length == 3)
In
if( (m[0].length = n-1) && (m[1].length = n) &&(m[2].length=n-1))
you're not testing for equality, but rather trying to put the values n-1 etc into m[0].length, which is not going to work. What you probably meant was
if( (m[0].length == n-1) && (m[1].length == n) &&(m[2].length==n-1))
In
return true
you're missing a semicolon. The compiler is whiny about things like that and unless you use an IDE or learn to interpret the compiler error messages, it can be really painful to find such errors.
Finally, of course, the answer by vasste provides a much simpler solution to your actual task, so it's worth looking into that :).
Why do you need all that loops? If all arrays cannot be null, than
static boolean isValidTridiagonal(double[][] m) {
return m.length == 3 && m[0].length == m[1].length - 1 && m[2].length == m[0].length;
}
You're missing a few braces at the end but, judging from your indentation, you just forgot to copy them.
You're missing semicolons from the end of the return lines.
The condition within this if statement if (double [][] = new double [3][]) is not a valid expression. You simply want to evaluate the length, which you can do like if (m.length == 3). You did the same thing later on.
The line including (m[0].length = n-1) && (m[1].length = n) && (m[2].length=n-1) is not valid because you are performing assignment (=) in all three cases. An equality check is the double equals operator ==.
You do not return a value in every case. You can fix this by adding return false; after the closing brace of your first if statement, i.e. the last line of the function.
This is enough to get your code to compile. As mentioned in another answer though, your logic is confusing and without actually tracing it through I would speculate that it will not work as you would expect.
If I have understood your requirements correctly, you can rewrite the entire function as:
static boolean isValidTridiagonal ( double [][] m)
{
return m.length == 3 &&
m[0].length + 1 == m[1].length &&
m[2].length + 1 == m[1].length;
}
A proper IDE - Netbeans, Eclipse, etc. - will give you fairly descriptive error messages to show you where you've gone wrong.
This is basically completely stylistic but I wish someone had pointed this out to me earlier. If you ever find yourself writing code in this form:
if( (m[0].length == n-1) && (m[1].length == n) && (m[2].length == n-1))
{
return true;
}
else
{
return false;
}
know that you can save yourself so many lines without losing any readability by instead writing:
return (m[0].length == n-1) && (m[1].length == n) && (m[2].length == n-1);

java Do While confusion

I have looked at other do while issues on StackOverflow, but I could not find the solution to my issue. I have variables initialized outside the do{ and they are being use within, but when the variables reach a certain value, the while method does not jump out.
Here is what I have:
int aiShotHit = 0;
int shotHit = 0;
do{
showBoard(board);
bAi.showAi(ai);
shoot(shoot,ships);
bAi.aiHit(aiShoot);
attempts++;
if(hit(shoot,ships)){
hint(shoot,ships,aiShips,attempts);
shotHit++;
System.out.println("\nShips Left on the Board: " + shotHit);
}
else
hint(shoot,ships,aiShips,attempts);
changeboard(shoot,ships,board);
if(bAi.aiHit(aiShoot,aiShips)){
hint(shoot,ships,aiShips,attempts);
aiShotHit++;
}
else
System.out.print("");
bAi.changeAi(aiShoot,aiShips,ai);
}while(shotHit !=3 || aiShotHit !=3);
if (shotHit == 3){
System.out.println("\n\n\nBattleship Java game finished! You Beat the Computer");
}
System.out.print("You lost! The Ai beat you");
You probably started out by saying, I want this to loop until shotHit is 3 or until aiHShotHit is 3.
That would be
while (!(shotHit == 3 || aiShotHit == 3));
which is "loop while it is not the case that either shotHit or aiShotHit contains the value 3", but it's kind of ugly so you wanted to apply the negation operator to each subexpression and get rid of some parens. The mistake was thinking you can move the negation operator without changing anything else to get
while (shotHit != 3 || aiShotHit != 3);
This exits the loop only in the event that shotHit is 3 at the same time that aiShotHit is 3. Not what you want.
The correct transformation is
while (shotHit != 3 && aiShotHit != 3);
This much was covered in the comments. The guidelines for how to safely transform this kind of expression are De Morgan's rules, which describe how to transform conjunctions and disjunctions in terms of each other. Following those rules lets you can move the negation operator and change the parenthesization without changing the meaning of the expression:
"not (A or B)" is the same as "(not A) and (not B)"
"not (A and B)" is the same as "(not A) or (not B)"
Needing to reorganize an expression to make it more readable comes up a lot in programming and this is a tool you need in order to do it safely. If you want to know more about De Morgan's rules you might want to read this answer.

Best way to format multiple 'or' conditions in an if statement

I have an if statement with many conditions (have to check for 10 or 15 constants to see if any of them are present.)
Instead of writing something like:
if (x == 12 || x == 16 || x == 19 || ...)
is there any way to format it like
if x is [12, 16, 19]?
Just wondering if there is an easier way to code this, any help appreciated.
The answers have been very helpful, but I was asked to add more detail by a few people, so I will do that to satiate their curiosity. I was making a date validation class that needed to make sure days were not > 30 in the months that have only 30 days (of which there are 4, I think) and I was writing an if statement to check things like this:
if (day > 30 && (month == 4 || month == 6 || month == 9 || month == 11))
I was just wondering if there was a faster way to code things like that - many of the answers below have helped.
I use this kind of pattern often. It's very compact:
Define a constant in your class:
private static final Set<Integer> VALUES = Set.of(12, 16, 19);
// Pre Java 9 use: VALUES = new HashSet<Integer>(Arrays.asList(12, 16, 19));
In your method:
if (VALUES.contains(x)) {
...
}
Set.of() returns a HashSet, which performs very well even for very large sets.
If performance is not important, you can code the gist of it into one line for less code footprint:
if (Set.of(12, 16, 19).contains(x))
but know that it will create a new Set every time it executes.
Do you want to switch to this??
switch(x) {
case 12:
case 16:
case 19:
//Do something
break;
default:
//Do nothing or something else..
break;
}
If the set of possibilities is "compact" (i.e. largest-value - smallest-value is, say, less than 200) you might consider a lookup table. This would be especially useful if you had a structure like
if (x == 12 || x == 16 || x == 19 || ...)
else if (x==34 || x == 55 || ...)
else if (...)
Set up an array with values identifying the branch to be taken (1, 2, 3 in the example above) and then your tests become
switch(dispatchTable[x])
{
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
}
Whether or not this is appropriate depends on the semantics of the problem.
If an array isn't appropriate, you could use a Map<Integer,Integer>, or if you just want to test membership for a single statement, a Set<Integer> would do. That's a lot of firepower for a simple if statement, however, so without more context it's kind of hard to guide you in the right direction.
Use a collection of some sort - this will make the code more readable and hide away all those constants. A simple way would be with a list:
// Declared with constants
private static List<Integer> myConstants = new ArrayList<Integer>(){{
add(12);
add(16);
add(19);
}};
// Wherever you are checking for presence of the constant
if(myConstants.contains(x)){
// ETC
}
As Bohemian points out the list of constants can be static so it's accessible in more than one place.
For anyone interested, the list in my example is using double brace initialization. Since I ran into it recently I've found it nice for writing quick & dirty list initializations.
You could look for the presence of a map key or see if it's in a set.
Depending on what you're actually doing, though, you might be trying to solve the problem wrong :)
No you cannot do that in Java. you can however write a method as follows:
boolean isContains(int i, int ... numbers) {
// code to check if i is one of the numbers
for (int n : numbers) {
if (i == n) return true;
}
return false;
}
With Java 8, you could use a primitive stream:
if (IntStream.of(12, 16, 19).anyMatch(i -> i == x))
but this may have a slight overhead (or not), depending on the number of comparisons.
Here is another answer based on a comment above, but simpler:
List numbers= Arrays.asList(1,2,3,4,5);
if(numbers.contains(x)){
//
}

if loop processing efficiency

Which of the 2 is better from a processing or optimizing point of view?
I feel Option 1 is more readable, but I've been told Option 2 is more efficient. Is that so?
if (value != null) {
if (value.equalsIgnoreCase(ApplicationConstants.A)) {
} else if (value.equalsIgnoreCase(ApplicationConstants.B)) {
}
}
Option 2:
if ((value != null) && (value.equalsIgnoreCase(ApplicationConstants.A))) {
} else if ((value != null) && (value.equalsIgnoreCase(ApplicationConstants.B))) {
}
There's nothing here to care about performance wise, write your code so it's as readable as you can make it.
When performance testing later highlights areas that need to be optimized then and only then optimize only the places that need it.
To make it more readable you can invert your tests to get rid of the null check:
if (ApplicationConstants.A.equalsIgnoreCase(value)) {
} else if (ApplicationConstants.B.equalsIgnoreCase(value)) {
}
Option 1 is efficient since there is no redundant null check.
I'd expect the first to be slightly more efficient, because && is short-circuit, so it gives multiple conditional branches anyway. But if you want to be certain, time them.
I would go with option 1 as in option 2, more no of comparisons are made.
The first option is better as with one condition check you can decide.
so if value != null then only it will enter else it will not even enter the conditional block.
But in 2nd option it will check if condition , and if false also it wd check else condition (for value == null).

Categories