Best DRY if statement? - java

Let's say I want to compare a bunch of variables to one static variable, normally I would do it like this:
int w = 0;
int x = 1;
int y = 1;
int z = 2;
if(w == x || w == y || w == z){/*more code here*/}
But that can get extremely long and doesn't seem necessary, are there any ways to do something more like:
if(w == (x || y || z)){/*more code here*/}
I would like to think that there is a way to do it like this.

Instead of:
if(w == x || w == y || w == z)
you can do:
if(Arrays.asList(x, y, z).contains(w))

Though there is an answer accepted, I would want to share my ways too:
Method 1 is similar to the accepted answer. However, instead of using List, I use a Set. In such case, it may be even faster than doing == individually if there are lots of values to check against:
// make it a static final member if semantically possible
Set<Integer> ALL_VALUES = new HashSet<Integer>(Arrays.asList(a,b,c,d,e,f,g,h));
//.....
if (ALL_VALUES.contains(w)) {
//... do something
}
Method 2 is to write a little utility function, something like
public static <T> boolean sameAsAny(T value, T... possibleValues) {
for (T p : possibleValues) {
if (value == p) {
return true;
}
}
return false;
}
with such util you can do something like:
if (sameAsAny(w, x, y, z))

You might prefer to format it like this :
if(w == x ||
w == y ||
w == z)
I find it helps break up the conditions and makes it easier to read.

That is not allowed in Java. But you could look into some rules based engines e.g drools.

Related

How do I break out of this recursive call?

I am a newbie to recursion and I am still learning it, so please tolerate my poor logic if it is bad. I have this function which has 5 parameters a,b,c,x,y. so what I essentially want to do is take an element out of either of these variables and add it to the other to finally get x , y. I want to try out this by myself and I have nearly done it, only i wanted to ask if there's any way i could get out of this recursive call, once I get the answer as "YES".
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String in = sc.nextLine();
int[] input = new int[10];
for(int i=0; i < 10; i=i+2) {
input[i] = Integer.parseInt(String.valueOf(in.charAt(i)));
}
int A = input[0];
int B = input[2];
int C = input[4];
int X = input[6];
int Y = input[8];
persistent(A,B,C,X,Y);
}
private static void persistent(int a, int b, int c, int x, int y) {
if(a == 0 || b == 0 || c == 0) {
if((a == x && b == y) && (b == x && a == y)) {
System.out.println("YES");
}
else if((b == x && c == y) || (c == x && b == y)) {
System.out.println("YES");
}
else if((a == x && c == y) && (c == x && a == y)) {
System.out.println("YES");
}
else {
return;
}
}
persistent(a-1,b+1,c,x,y);
persistent(a-1,b,c+1,x,y);
persistent(a+1,b-1,c,x,y);
persistent(a,b-1,c+1,x,y);
persistent(a+1,b,c-1,x,y);
persistent(a,b+1,c-1,x,y);
}
Your code never does.
Recursive algorithms pretty much all boil down to this exact same style:
First, check if some edge case has been reached (generally, the very simplest case). In this case, return immediately - do not recurse. By tautology, if the answer is so easy you can just give it without needing to recurse, that defines 'edge case' / 'simple case'. There must be at least one such case, or a recursive algorithm cannot work.
Otherwise, provide your answer and feel free to employ as many recursive calls as you prefer, but every single last one of those calls must be simpler, defined by the idea that it is strictly closer to that simple case as mentioned in 1.
All state is conveyed via parameters. It is common to have a private helper method that does the actual work which has a bunch of extra parameters, and the public API that is a one-liner that calls the helper, providing initial values for those extra parameters. Only if you have no such state can you omit this one.
Your code isn't doing this. There is a simple case, which is if a or b or c is 0, but your 6 recursive calls are not clearly moving towards simplicity.
The fix is not obvious. Your algorithm cannot work as written and cannot be fixed without considerably rethinking it.
Hopefully the above will help you: Your recursive calls need to become simpler somehow, guaranteed. Right now it's not guaranteed: Yes, every call is moving one of the 3 numbers closer to the edge case (be 0), but there is no clear flow: If I call your code with, say, 3/4/5 as arguments, then it makes recurisve calls with 2/5/5, 2/4/6, etcetera. That first call (2/5/5) is not moving guaranteed closer to the edge case, because as part of its call stack, it'll be doing 3/4/5 again.

Trying to Convert C++ to Java

I am trying to convert source code from C++ to Java and i have done all of it except from one method that seems to be returning the wrong type and im not sure how i should format it correctly...
this is the C++ code i want to convert
int find( int x )
{
return f[x]==x ? x : f[x]=find(f[x]);
}
and this is what i thought it would be in Java but it wont work as it says cannot convert int to boolean but how would i correctly convert?
public static int find(int x)
{
return f[x] == x != 0 ? x : f[x] = find(f[x]);
}
f[x] == x != 0 ? x : f[x] = find(f[x]) means compare f[x] with x != 0 ? x : f[x] = find(f[x]), then this produces a boolean while the return type is int.
You don't have to change the original expression, let it as is, it will work correctly: f[x] == x ? x : (f[x] = find(f[x]))
The result of f[x] == x is already a boolean. All you need do is
public static int find(int x) {
return f[x] == x ? x : (f[x] = find(f[x]));
}
You need an extra () around the assignment as it has lower precedence.

Java boolean method needs extra return statement?

I am starting with java and while I was writing a way to identify whether a number was prime I wrote a method like this
public static boolean checkPrime(int n){
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !Prime;
}
else if(((n % x) == 0) && (n > x)){
return Prime;
}
else {
return Prime;
}
}
What I couldn't figure out was the necessity of the last else statement. If I do not put it, I get an error message. However I don't think it is necessary since all possibilities are covered by the previous loops, with their respecting return statements. Or am I missing something?
You don't need the else. What you are being told by the compiler is the method must return SOMETHING. Your last else block could replaced by this:
return PrimeOrNot;
In fact, your method could look like this:
public static boolean checkPrime(int n){
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !(PrimeOrNot);
}
return (PrimeOrNot);
}
In any case your very last statement block cannot be an else if.
The method has a return type of boolean.
The compiler is scared by the possibility in which none of the 'if' cases are met. In this situation, the method know what to return. This method needs to return something, so just give it a 'return true' before the method ends. It won't ever be read, but it will make the compiler happy.
The conditional expressions within the if/else-if are only evaluated at runtime. Normally, the compiler wouldn't know what the result would be, because they are not evaluated at compile-time. Only, situation when the compiler can figure what the result of the expression would be is when it's some compile-time constant (like if(true) {).
public static boolean checkPrime(int n){
boolean PrimeOrNot = false;
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !(PrimeOrNot);
}
else if(((n % x) == 0) && (n > x)){
return (PrimeOrNot);
}
return PrimeOrNot;
}
A method which returns a value will be compilable if it returns a value in all its possible code paths.
Imagine for a moment that you're the compiler. You see this code:
int myMethod()
{
if (cond)
return anInt;
}
While you may know that cond is in fact always true, the compiler will not know that. It can only be sure about the result of a boolean expression if it is an expression which can be evaluated at compile time only.
Note that the vast majority of "code optimization" in Java is in fact done at run time (JIT: Just In Time).
The compiler only checks to see if there are valid return paths from your method. The compiler isn't "smart" enough to inspect the conditional statements and determine whether the conditions can be logically met -- the compiler simply checks to make sure that some value is returned to respect the contract of the method declaration.
Some would argue that the following is a cleaner structure for the method (but I think it is just a matter of taste):
public static boolean checkPrime(int n){
int x = 2;
while (((n % x) != 0) && (n > x)){
x = x + 1;
}
if(((n % x) == 0) && (n == x)){
return !(PrimeOrNot);
}
return (PrimeOrNot);
}

If statement return loop

Just a declaimer:i am a beginner in java.
Write a method named numUnique that takes three integers as parameters and that returns the number of unique integers among the three. For example, the call numUnique(18, 3, 4) should return 3 because the parameters have 3 different values. By contrast, the call numUnique(6, 7, 6) would return 2 because there are only 2 unique numbers among the three parameters: 6 and 7.
public int numUnique(int x,int y,int z){
    if(x==y||y==z){
}
return 1;
else if(x!=y||y!=z){
}
return 2;
    
}
I am very confused about the relationship of if and return.I always put return inside if statement.But i dont understand why does it generate me an error message.if something is fulfil,i return in the loop.Why is it wrong.But on the other hand,the println statement can be put inside for loops.
Another issue,because this question,i tried to attempt using if else too.But my first condition is if and i return it.So after that i placed else if after the first return,it gives me error again.
I will appreciate someone will explain to me and i will alter the codes on my own.Please dont give me the full codes.Thank you.
Edited*
By the way,i read through all the comments and i finally understand it.This is my codes that i work out on my own(:
public static int numUnique(int x, int y, int z) {
if(x==y && y==z){
return 1;
}else if(x==y && y!=z || y==z && z!=x || x==z && y!=z ){
return 2;
}
return 3;
}
The return statements should be placed within the curly bracets.
To give you a clear understanding of "return" statements, i will say there can be only one return statement in one block of code i.e {...}.
"return" statement is used to return to the caller, and it has to be last statement of the block.
As suggested by you i am not providing you complete code, rather making you aware of usage of "return" statement.
In your code you are writing two "return" statements in one block.
i think you need to write return statements inside if-else blocks otherwise it will always return 1
The syntax for a what you want looks like this:
public static int numUnique(int x,int y,int z){
if(x==y||y==z){
return 1;
}else if(x!=y||y!=z){
return 2;
}
return 3;
}
Maybee this code ist better understandable:
public static int numUnique(int x, int y, int z) {
if (x == y && x == z && y == z) {
return 3;
} else if (x != y && x != z && y != z) {
return 1;
}
return 2;
}
Pseudocode If
if( condition ){
// do something if condition is true
}
Pseudocode If then else
if( condition){
// do something
}else{
// do something if condition is false
}
Pseudocode elseif
if( condition ){
// do something
}else if(condition2){
// do something, only if condition2 is true, if condition 1 is true, you never will be here
}else{
// do something, your only here if the two conditions above were false
}
A return statement, immidiently brakes execution ( there are some exception, exmaple: the finally block)
First, your return are outside the if statements, they should be inside. Because if you write:
if(Something) {
}
return 1;
Then 1 will be always returned because your if is empty. If you want to return 1 only if(Something) then write it inside the if body:
if(Something) {
return 1;
}
Second, your logic is not good. You need to check:
if x == y == z then they're all equal.
if x == y and x != z then you should return 2.
if x != y != z then you should return 0.
....
You need to cover all situations.
since if is a conditional flow, i may or may not run (depending on the condition),
but if your method has return type it should return in every cases. But in the later case, (if condition is false), it wont find any return.
so if you write
public int value(boolean flag){
if(flag){
return 0; //only reachable if flag is true, else value can not return from here
}
}
it is wrong, since if flag is false method wont return anything. so you must provide a return in else or after if block ends
using the fact that Sets store values only once...
public int numUnique(int x,int y,int z){
Set<Integer> number = new HashSet<Integer>();
number.add(x);
number.add(y);
number.add(z);
return numbers.size();
}
You have to put the return statement in the block from if and else:
public int numUnique(int x,int y,int z){
if(x==y||y==z){
return 1;
}
else if(x!=y||y!=z){
return 2;
}
}
it fails because the compiler think, that you have not a return statement for the function in every path.
Your code is ill-formed:
And if-else statement is as following:
if { code }
else { code }
So, if and else blocks make a pair. But you have:
if (condition) { code }
code
else { code }
code
So, the code just above the word else breaks this pair, and else remains isolated, and thus your program is syntactically incorrect.
You "want" to do:
if (x==y || y == z) {
return 1;
}
else if (x != y || y != z) {
return 2;
}
Moreover, if a if (or else) block has only one line, you can erase the brackets:
if (x==y || y == z)
return 1;
else if (x != y || y != z)
return 2;
Even more, you algorithms isn't a solution to your problem, ¿how about 3 unique values?. You should check more situations (all diferents, all equals, or only one different).

Java - Double Comparison

How can I do something like:
int a=5;
if(4<=a<=6){
}
in Java?
Make it two conditions:
int a=5;
if(4<=a && a<=6){
}
Apart from the obvious solution stated by others (if(4<=a && a<=6)), you can use commons-lang's IntRange:
Range range = new IntRange(4,6)
if (range.containsInteger(5)) {..}
It looks like a bit of an overkill, but depending on the situation (if it isn't as trivial) it can be very useful.
if(4 <= a && a <= 6) {
// do something
}
Of course, you could always write a function like this in some Util class:
class Util {
public static boolean inclusiveBetween(int num, int a, int b) {
return num >= a && num <= b;
}
}
and then you can do something like
if(Util.inclusiveBetween(someResourceIntensiveOpReturningInt(), 4, 6)) {
// do things
}
You can't, I don't think. What's wrong with
int a = 5;
if(a >= 4 && a <= 6) {
}
? If you need to compare many different variables, put them in an array and sort the array, then compare the arrays.
You can do this. Its ugly, but can be very slightly faster.
int a = 5;
if(a - Integer.MIN_VALUE - 4 <= 2 - Integer.MIN_VALUE) {
}
This exploits the use of underflow to turn two comparisons into one. This can save about 1-2 nano-seconds. However, in some usecases it can cost the same amount, so only try it if you are trying to micro-tune a loop.

Categories

Resources