why if comparison doesn't work in java - java

I am making a Hash Table in java.
In searching function, I am doing some comparison in IF statement. but it is not doing any comparison.
here's is some part of my code.
while (table[pos]!=null) {
if (table[pos]==key) {
System.out.println("SEARCH "+key+" at INDEX "+home);
return;
}
else {pos=h(home+p(i));
i++;
}
}
System.out.println("Failed to find "+key+".");
return;
}
It doesn't work even when table[pos] and key are the same!
but I add very simple assigning variable to another one. It work! I don't know why it works. I wanna know it xD
while (table[pos]!=null) {
int x = table[pos];
if (x==key) {
System.out.println("SEARCH "+key+" at INDEX "+home);
return;
}
else {pos=h(home+p(i));
i++;
}
}
System.out.println("Failed to find "+key+".");
return;
}

Well, if table[pos] and key are both Integer (and table[pos] must be a reference type, since you are comparing it to null in the while statement), they should be compared with equals, not with ==, since two different Integer objects may have the same int value.
When you assign table[pos] to the int variable x, it is un-boxed to a primitive value.
Now, when you compare the int x to the Integer key, the key is also un-boxed to an int, and int comparison works with ==.
This can be demonstrated by the following short example:
Integer i1 = 300;
Integer i2 = 300;
System.out.println (i1 == i2);
int i3 = i1;
System.out.println (i3 == i2);
which outputs:
false
true
The code code would be:
while (table[pos] != null) {
if (table[pos].equals(key)) {
System.out.println("SEARCH "+key+" at INDEX "+home);
return;
} else {
pos = h(home + p(i));
i++;
}
}
System.out.println("Failed to find "+key+".");

When comparing two objects with ==, you check if both of these references point to the same place in the memory, while using == with primitives simply checks if values are the same. To correctly check equation of values inside two Integers you should use equals() method.
In your second example you used unboxing from Integer to int so it checked values as you expected it to do. In the first one you compared if both values point to the same place in memory.

Actually the correct way is to use both just like HashMap does for example, this way we will always be sure. This is for example how HashMap does it internally:
if(((k = first.key) == key || (key != null && key.equals(k)))) ...
So in your case it would be:
if ((table[pos] == key) || (key != null && (table[pos].equals(key)))) {

Related

Removing a substring from a string, repeatedly

Problem:
Remove the substring t from a string s, repeatedly and print the number of steps involved to do the same.
Explanation/Working:
For Example: t = ab, s = aabb. In the first step, we check if t is
contained within s. Here, t is contained in the middle i.e. a(ab)b.
So, we will remove it and the resultant will be ab and increment the
count value by 1. We again check if t is contained within s. Now, t is
equal to s i.e. (ab). So, we remove that from s and increment the
count. So, since t is no more contained in s, we stop and print the
count value, which is 2 in this case.
So, here's what I have tried:
Code 1:
static int maxMoves(String s, String t) {
int count = 0,i;
while(true)
{
if(s.contains(t))
{
i = s.indexOf(t);
s = s.substring(0,i) + s.substring(i + t.length());
}
else break;
++count;
}
return count;
}
I am just able to pass 9/14 test cases on Hackerrank, due to some reason (I am getting "Wrong Answer" for rest of the cases). After a while, I found out that there is something called replace() method in Java. So, I tried using that by replacing the if condition and came up with a second version of code.
Code 2:
static int maxMoves(String s, String t) {
int count = 0,i;
while(true)
{
if(s.contains(t))
s.replace(t,""); //Marked Statement
else break;
++count;
}
return count;
}
But for some reason (I don't know why), the "Marked Statement" in the above code gets executed infinitely (this I noticed when I replaced the "Marked Statement" with System.out.println(s.replace(t,""));). I don't the reason for the same.
Since, I am passing only 9/14 test cases, there must be some logical error that is leading to a "Wrong Answer". How do I overcome that if I use Code 1? And if I use Code 2, how do I avoid infinite execution of the "Marked Statement"? Or is there anyone who would like to suggest me a Code 3?
Thank you in advance :)
Try saving the new (returned) string instead of ignoring it.
s = s.replace(t,"");
replace returns a new string; you seemed to think that it alters the given string in-place.
Try adding some simple parameter checks of the strings. The strings shouldn't be equal to null and they should have a length greater than 0 to allow for counts greater than 0.
static int maxMoves(String s, String t) {
int count = 0,i;
if(s == null || s.length() == 0 || t == null || t.length() == 0)
return 0;
while(true)
{
if(s.contains(t) && !s.equals(""))
s = s.replace(t,""); //Marked Statement
else break;
++count;
}
return count;
}
You might be missing on the edge cases in the code 1.
In code 2, you are not storing the new string formed after the replace function.
The replace function replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.
Try this out:
public static int findCount(String s, String t){
if( null == s || "" == s || null == t || "" == t)
return 0;
int count =0;
while(true){
if(s.contains(t)){
count++;
int i = s.indexOf(t);
s = s.substring(0, i)+s.substring(i+t.length(), s.length());
// s = s.replace(t,"");
}
else
break;
}
return count;
}
String r1="ramraviraravivimravi";
String r2="ravi";
int count=0,i;
while(r1.contains(r2))
{
count++;
i=r1.indexOf(r2);
StringBuilder s1=new StringBuilder(r1);
s1.delete(i,i+r2.length());
System.out.println(s1.toString());
r1=s1.toString();
}
System.out.println(count);
First of all no logical difference in both the codes.
All the mentioned answers are to rectify the error of code 2 but none told how to pass all (14/14) cases.
Here I am mentioning a test case where your code will fail.
s = "abcabcabab";
t = "abcab"
Your answer 1
Expected answer 2
According to your code:
In 1st step, removig t from index 0 of s,
s will reduce to "cabab", so the count will be 1 only.
But actual answer should be 2
I first step, remove t from index 3 of s,
s will reduced to "abcab", count = 1.
In 2nd step removing t from index 0,
s will reduced to "", count = 2.
So answer would be 2.
If anyone know how to handle such cases, please let me know.

Idiomatic way to ensure many values are equal

Say I have a list of many primitive variables:
final int a = 3;
final int b = 4;
final int c = 4;
final int d = 4;
final int e = 4;
What's an idiomatic way to make sure they all hold the same value? The obvious way is simply
if (a == b && a == c && a == d && a == e) // ...
But I think this is error prone and hard to read, especially when the variables have proper names, unlike my example.
if ( numCategories == numTypes && numCategories == numColours
&& numCategories == numStyles && numCategories == numPrices) // ...
It would be nice if we could do the comparison like this:
if (a == b == c == d == e)
but obviously a == b resolves to a boolean so we can't compare that to c.
Is there a library function in the JDK or another utility library with maybe a signature somewhat like this?
static boolean areEqual(int... numbers)
then we could use it like so:
if (areEqual(a, b, c, d, e)) //...
I could easily write a function like this myself, but why reinvent the wheel if you don't have to?
Maybe there's another idiomatic way to accomplish this that I'm missing.
Using Streams, you can take advantage of some convenient methods to achieve your goal.
You can use Stream's or IntStream's distinct() combined with count() to find the number of unique elements:
For int variables:
if (IntStream.of(a,b,c,d,e).distinct().count() == 1) {
}
For reference type variables:
if (Stream.of(a,b,c,d,e).distinct().count() == 1) {
}
Another way, which is probably less efficient (but I'll keep it here since it's the first thing I thought about) is creating a Stream of all the elements you want to compare and then collecting them into a Set and checking the size of the Set is 1 (since Set doesn't allow duplicates) :
if (IntStream.of(a,b,c,d,e).boxed().collect(Collectors.toSet()).size() == 1) {
}
or
if (Stream.of(a,b,c,d,e).collect(Collectors.toSet()).size() == 1) {
}
for general Objects.
A naive option is to build methods that receives all the variables as varargs and compare them one after other. If one of them is different you will get false
public static boolean areEqual(int...nums)
{
for (int i = 0 ; i < nums.length - 1 ; ++i) {
if (nums[i] != nums[i + 1]) {
return false;
}
}
return true;
}
Uses
if (areEqual(a, b, c, d, e))
I like this approach. There's no auto-boxing and no magic numbers.
As per the documentation, it's also short-circuiting so therefore potentially more efficient than other methods. More importantly, it's very easy to read.
IntStream.of(a, b, c, d).allMatch(x -> x == e);
Credit to saka1029.

java recursion test if arraylist are equal

I have some code that I would like to make more efficient by recursion. Trouble is I don't know where to start. The code compares two arraylists a and b to see if they are equal. Assume the sizes of both arrays are equal.
The code is
public boolean isEqual(A B) {
boolean answer = false;
if (lessThanOrEqualTo(B) == true);
for (int i = 0; i < DList.size(); i++) {
if (DList.get(i) == B.DList.get(i)) answer = true;
else answer = false;
}
return answer;
}
I have currently written
public boolean isEqualRecursion(A B) {
if DList.size() == 0;
return false();
} else {
}
I know the stopping case is 0 as when size is 0 nothing happens. I have no idea what to write next
Any help will be appreciated
Thanks
I have some code that I would like to make more efficient by recursion.
It is unlikely that you can make it more efficient by recursion. The chances are that it will be less efficient, and also fragile. This is because standard Java compilers don't implement tail-call optimization. The fragility occurs because a recursive comparison algorithm is liable to trigger a stack overflow if the input arrays are large enough.
However, if you want to continue with this as "an exercise", then my HINT is to add an index argument to the isEqualRecursion signature ...
I think that this is a pretty good start for you. This looks through all your elements, assuming they are an array, and then checks if they are equal in size.
public boolean isEqual(ArrayList<?> a, ArrayList<?> b) {
if (a.size() != b.size())
return false;
for (int i = 0; i < a.size(); i++) {
if (!isEqual((ArrayList<?>)a.get(i), (ArrayList<?>)b.get(i))) {
return false;
}
}
return true;
}
Now a couple of things to consider:
This assumes that the content of a(and b) must be an ArrayList at line (ArrayList<?>)a.get(i) what if our ArrayList actually contains something else, like an Integer?
What if our array lists contain null as an item?
What if we pass in two null ArrayLists? (or even just one?)
I'm not sure the point of your function lessThanOrEqualTo(B) is this part of the question or did you write this down wrong?
Also what is a DList?
This is a typical recursion question. You might want to try something like this:
int x = 0;
if(Dlist.get(x) != B.Dlist.get(x)) {
return false;
} else {
x+1;
}
if( x!= dList.size()) {
recursion;
}
return true;

check Equal and Not Equal conditons for double values

I am facing difficulty in comparing two double values using == and !=.
I have created 6 double variables and trying to compare in If condition.
double a,b,c,d,e,f;
if((a==b||c==d||e==f))
{
//My code here in case of true condition
}
else if ((a!=b||c!=d||e!=f))
{
//My code here in case false condition
}
Though my condition is a and b are equal control is going to else if part
So I have tried a.equals(b) for equal condition, Which is working fine for me.
My query here is how can I check a not equal b. I have searched the web but I found only to use != but somehow this is not working for me.
If you're using a double (the primitive type) then a and b must not be equal.
double a = 1.0;
double b = 1.0;
System.out.println(a == b);
If .equals() works you're probably using the object wrapper type Double. Also, the equivalent of != with .equals() is
!a.equals(b)
Edit
Also,
else if ((a!=b||c!=d||e!=f))
{
//My code here in case false condition
}
(Unless I'm missing something) should just be
else
{
//My code here in case false condition
}
if you really want invert your test conditions and test again,
else if (!(a==b||c==d||e==f))
Or use De Morgan's Laws
else if (a != b && c != d && e != f)
You can use
!a.equals(b) || !c.equals(d) || !e.equals(f)
Well with double data type you can use
==,!= (you should try to use these first.. )

how can i get true logic condition to true in java

That's my while loop, and the question is, how can i get a true condition?
s and t are Integer variables
while (s<=t && s>=t && s!=t )
EDIT
tl;dr the original question stated:
s and t are int variables (and OP commented they are not Integer variables)
Never!
s and t are int variables, so when s == t the third operand will fail, when s != t one of the first two operands will fail.
Possible, but unlikely, if they are declared as volatile int s, t; in a multi-threaded application.
EDIT
Question has been modified. Now s and t are Integer variables, which makes the answers referring to Integer objects more relevant.
By boxing the primitive value in an object:
Integer s = new Integer(5);
Integer t = new Integer(5);
boolean rslt = (s <= t && s >= t && s != t);
System.out.println("Result = " + rslt);
The rslt boolean here will indeed evaluate to true.
However, the following would return false:
s <= t && s >= t && !s.equals(t)
it is because in Java, for objects, == means that it is indeed the same instance, while equals is left up to be implemented by every class and typically means that the core values of the compared objects are the same -- while not necessarily being the same class instance (AKA object). The > and < for boxed primitives are evaluated agaist the primitive value, however == is checking the object identity.
It actually is possible:
public class EqualsTest
{
public static void main(String[] args)
{
Integer x = new Integer(Integer.parseInt(args[0]));
Integer y = new Integer(Integer.parseInt(args[1]));
if(x <= y && y <= x && y !=x)
{
System.out.println("equal");
}
else
{
System.out.println("not equal");
}
}
}
Compiling this and running it with two equal integer arguments produces:
$ java EqualsTest 5 5
equal
The reason that this works is due to autoboxing and the fact that, for objects, == only checks whether or not the references are the same (which, in the case above, they are not).
Never man, no way.
s<=t && s>=t returns true if s == t, and s == t && s != t returns false forever.
You cant the only way first two conditions result true is when s is equal to t and the third conditions negates this fact.
Hence i dont think its possible
If the two values are accessible by multiple threads (either static, or members variables of an object shared between multiple threads), you could do this:
Thread 1:
s = 1; // 1
t = 1; // 2
t = 2; // 5
Thread 2:
This is equivalent to your expression but easier to label.
boolean result = s <= t; // 3
if(result) {
result = s >= t; // 4
}
if(result) {
result = s != t; // 6
}
Assuming everything happens in the order given by the commented numbers, then at the end of thread 2's code, result will be true.
So, thread 1 sets s and t to be equal, then thread 2 checks that they're equal, then thread 1 sets them to be not equal, then thread 2 checks that they're not equal.
There are more complicated situations where this could be true, but this is the simplest one I could think of.

Categories

Resources