Why is string comparison failing in my code? - java

I have an array in containing numbers that represent cable sizes (1, 1.5, 2.5, etc), stored as strings.
In my program, the array is loaded into a spinner, which is working fine.
However, when the item is selected and stored in a variable, I want to check what string was selected, and set another numerical variable to 2.5 so I can do a calculation later in the program.
I tried the following:
if (conductorSize = "1" ) {conCsa = 1;}
else if (conductorSize = "1.5") {conCsa = 1.5;}
conductorSize being the variable holding the selected string, and conCsa being the variable
set to a numerical variable for calculation.
The compiler says that I cannot convert a string to boolean. What's happening?

If you are doing string comparisons, use .equals()
Example taken from here:
String s = "something", t = "maybe something else";
if (s == t) // Legal, but usually WRONG.
if (s.equals(t)) // RIGHT <<<<<<<<<<<<< Use this.
if (s > t) // ILLEGAL
if (s.compareTo(t) > 0) // CORRECT>

As Ed S. points out you are using the assignment operator. However since you are comparing a String you need to use the equals method.
if ("1".equals(conductorSize)) {conCsa = 1;}
else if ("1.5".equals(conductorSize)) {conCsa = 1.5;}
Alternatively, you could just create a new float from your String:
float conCsa;
try {
conCsa = Float.parseFloat(conductorSize);
}catch(NumberFormatException e){
conCsa = 0.0f; //set to a default value
}

It looks like what you're trying to do might better be expressed in this way:
conCsa = Double.parseDouble(conductorSize);

In general you need to use the .equals() method.
If performance is extremely important and you are comparing against string literals, take a look at String.intern(). It'll allow you to do super-fast == comparisons and avoid a full character-by-character scan as in .equals().
Performance would have to be really, really important though, to justify such a non-standard approach.

When you have cable sizes which are constants, you need to use Enums , which will help you in reducing no of if condition comparisons.

Related

Splitting a string by delimiter without any variables?

Can you split a string in Java without storing what has been split into variables? (Assignment requirement :()
I have tried things which worked on other programming languages however nothing I try seems to work:
(Attempting to see if the second item in a space delimited string (x) is +)
if ((x.split.(" ")).(1) = "+") {
// Do something
}
if ((x.split.(1).(" ")) = "+") {
// Do something
}
Well, what is returned is of type String[]. So if you know that there will be two items, you can reference it as an array..
if(x.split(" ")[1].equals("+"))
Extra Reading
You should look at String Comparison.
String.split returns an array, so this is how it could be done. Note the use of '.equals()'. In Java the == operator checks if the pointer value is the same.
if (x.split.(" ")[1].equals("+")) {
// Do something
}
(And of course this could throw an out of bounds exception if the split wouldn't make an array of size >= 2)

Java grammar questions

I am learning Android and taking the MOOC offered by Maryland University.
In one of the lectures I noticed the following line of code:
String output = (val == answer) ? "42" : "We may never know";
My guess is that this is equivalent to:
if(val == answer){
String output = "42";
}else{
String output = "We may never know";
}
Is my assumption correct?
PS: Is there anywhere besides coursera where I can take certified android classes online?
You are almost correct, it's actually like this:
String output;
if(val == answer){
output = "42";
}else{
output = "We may never know";
}
BR Erik
Your assumption is almost correct. The ternary expression would be more accurately represented as:
String output;
if (val == answer) {
output = "42";
}
else {
output = "We may never know";
}
In your original version, output is only available within the scope of the if/else blocks, since you declare it inside them. Declaring it outside the scope means you'll be able to use the value later. However, as Hariharan pointed out, using == for string comparison is a no-no in Java; you're comparing the raw objects, not the string contents. You'll want to replace your val == answer with val.equals(answer) to get a proper result.
Edit: If val and answer aren't strings, disregard the portion about using .equals(). I (and apparently everyone else who answered this question) made the bad assumption that they were, since everything else was strings. .equals() should be used for strings and any other complex object, == can be safely used for primitives.
Yes, you are correct (almost). It's called ternary operator. Your logic is good but you must take care that the variable is initialized outside of the if-else statement.
String output;
if (val == answer) {
output = "42";
} else {
output = "We may never know";
}
If the variable would be defined inside if and else blocks you would not be able to use it after the } sign because it would fall out of the scope.
Yes, you are totally right. It's so called ternary operator. take a look here and here
And a small note: it's weird to declare the same variable twice inside conditional blocks. Declare it somewhere outside .

Why does java require a double equals sign?

Why does java require a double equals sign (==) when comparing Integers in a if statement?
For example
if(x = 3.141)
System.out.println("x is equal to pi.");
is incorrect, it should be
if(x == 3.141)
System.out.println("x is equal to pi.");
I know that "==" is used to compare integers and "=" is used to set an integer value, but why in a if statement does this remain true?
Is it even allowed to assign a variable a value in an if statement (or initiate a new variable)?
Is there any reason anyone would ever want to assign a variable a new value inside an if statement (if so please provide an example)?
This seems like a question that should already have an answer, but I was unable to find one on here or using google, if this is a duplicate question please tell me and I will remove it immediately.
Wouldn't it be confusing if = sometimes did assignment, and sometimes comparison, depending in which context you used it?
That sounds like a bad idea, and would introduce errors.
Plus, the current syntax is compatible with C and C++, so a lot of people are familiar with it.
Is there any reason anyone would ever want to assine a variable a new value inside of an if statement (if so please provide an example)?
It's quite common in while loops:
int b;
while ((b=in.read()) != -1){
=
is used for assignment.
==
is used for comparison.
Is it even allowed to assign a variable a value in an if statement (or initiate a new variable)?
yes it is allowed.
Note what error message you get for if (x = 3.141); it is a type error (cannot convert from double to boolean).
The assignment's type is the type of its both sides; if the type of the assignment is boolean (if (x = true), or even if (x = a.equals(b))), then it is legal to write.
So since it is legal to assign a value to a boolean in the condition, you'd have to use == for comparison.
Is it even allowed to assine a variable a value in an if statement (or initiate a new variable)?
Yes. A common idiom for doing this is:
String line = null;
while ( (line = in.readLine()) != null ) {
// do work
}
In the loop, line is assigned a value and then compared to null. I can't think of an example with ints; it certainly wouldn't be clear there.
History of programming languages 101:
Fortran uses = for both.
Algol introduced := for assignment and used = for comparison. This was required to resolve a grammar ambiguity.
Pascal followed suit.
PL/1 did not.
I can't speak for B or BCPL but by the time we got C it was = for assignment and == for comparison, again to resolve a grammar ambiguity
C++ followed C
Java followed C++ in many respects including this one.
The grammar ambiguity arises because of allowing assignments in expressions. Contrary to your assertion, if (x = true) is legal in Java if x is of type boolean.
== is the identity comparator, which works for both objects and primitives. It answers the question "are the two things the same thing".
= is the assignment operator. It sets the value of the left side to the right side.
Things can turn buggy when using your example with booleans:
boolean b;
if (b = true) // This compiles, but is a bug, because it sets b, not tests it
While other types won't compile with this syntax, boolean and Boolean do, so that's why the following pattern is advised:
if (b)
you can absolutely assign a variable in an if statement. also, that's just the way it works: = always is assignment, and == is always comparison.
So..
= is assignment, and == is comparison, and it is always like this, no matter where they are used.
And assignment is different with "declaration". An assignment statement has its return value, while a declaration doesn't. So you can't write boolean a = false in the () of if statement, but you can write a = false when a has been declared before.
Not all assignments are legal. For example:
int index;
if (index = str.indexOf("something")) {
...
}
It's not legal, because String.indexOf(String) returns an int, while if requires a boolean.
Also, there is a huge difference between "legal" and "making sense".
int index;
if ((index = str.indexOf("something")) != -1) {
...
}
It is legal, as != operation returns a boolean, and it makes sense, as I do want to check if the str contains a substring "something";
However,
int index;
boolean flag;
if ( flag = ((index = str.indexOf("something")) != -1) ) {
...
}
is also legal, as the statement as last returns a boolean; but it DOESN'T make sense, because the != statement already returns a boolean.

Alternative to substring

I have a strange problem when adding a value to a String array which is later involved in an array sort using a hash map. I have a filename XFR900a, and the XFR900 part is added to the array using the following code;
private ArrayList<String> Types = new ArrayList<String>();
...
Types.add(name.substring(0,(name.length() - 1));
System.out.println(name.substring(0,(name.length() - 1));
I even print the line which gives "XFR900", however the array sort later on behaves differently when I use the following code instead;
Types.add("XFR900");
System.out.println(name.substring(0,(name.length() - 1));
which is simply the substring part done manually, very confusing.
Are there any good alternatives to substring, as there must be some odd non ascii character in there?
Phil
UPDATE
Thanks for your comments everyone. Here is some of the code that later compares the string;
for (int i=0;i< matchedArray.size();i++){
//run through the arrays
if (last == matchedArray.get(i)) {
//add arrays to a data array
ArrayList data = new ArrayList();
data.add(matchedArray1.get(i));
data.add(matchedArray2.get(i));
data.add(matchedArray3.get(i));
data.add(matchedArray4.get(i));
data.add(matchedArray5.get(i));
//put into hash map
map.put(matchedArray.get(i), data);
}
else {
//TODO
System.out.println("DO NOT MATCH :" + last + "-" + matchedArray.get(i));
As you can see I have added a test System.out.println("DO NOT MATCH" ... and below is some the output;
DO NOT MATCH :FR99-XFR900
DO NOT MATCH :XFR900-XFR900
I only run the substring on the XFR900a filename. The problem is that for the test line to be printed last != matchedArray.get(i) however they are then the same when printed out to the display.
Phil
You should never use the == operator to compare the content of strings. == checks if it is the same object. Write last.equals(matchedArray.get(i)) instead. The equals() method checks if to object are equal, not if they are the same. In case of String it checks if the two strings consists of the same characters. This might eliminate your strange behaviour.
PS: The behaviour of == on string is a little unpredictable because the java virtual machine does some optimization. If two strings are equal it is possible that the jvm uses the same object for both. This is possible because String objects are immutable anyway. This would explain the difference in behaviour if you write down the substring manually. In the one case the jvm optimizes, in the other it doesn't.
Use .equals() rather than == because they are strings!
if (last.equals(matchedArray.get(i))) {}
Never use == operator if you wanted to check the value since operator will check the Object reference equality, use equals operator which check on the value not the reference i.e. for (int i=0;i< matchedArray.size();i++){
//run through the arrays
if (last.equals(matchedArray.get(i))) { // Line edited
//add arrays to a data array
ArrayList data = new ArrayList();
data.add(matchedArray1.get(i));
data.add(matchedArray2.get(i));
data.add(matchedArray3.get(i));
data.add(matchedArray4.get(i));
data.add(matchedArray5.get(i));
//put into hash map
map.put(matchedArray.get(i), data);
}
else {
//TODO
System.out.println("DO NOT MATCH :" + last + "-" + matchedArray.get(i));

Why my parsing doesn't work?

I was asked for my homework to make a program wherein the user inputs a Roman numerals between 1-10 and outputs the decimal equivalent. Since I'll be getting a string in the input and an integer in the output, I parsed it, but it won't work. Any ideas why?
import java.util.Scanner ;
class Romans {
static Scanner s = new Scanner(System.in) ;
static String val = null ;
public static void main (String [] args)
{
System.out.print ("Enter a roman numeral between I to X: ");
String val = s.nextLine();
int e = Integer.parseInt(val);
}
static int getRoman (int e)
{
if (val = "I"){
System.out.print ("1") ;
}else if (val = "II" ){
System.out.print ("2") ;
}else if (val = "III") {
System.out.print ("3") ;
} else if (val = "IV") {
System.out.print ("4") ;
} else if (val = "V"){
System.out.print ("5");
} else if (val = "VI") {
System.out.print ("6");
} else if (val = "VII") {
System.out.print ("7");
} else if (val = "VIII") {
System.out.print ("8");
} else if (val = "IX") {
System.out.print ("9");
} else if (val = "X") {
System.out.print ("10") ;
}
return val ;
}
}
Two points:
= is the assignment operator, not the equality-testing operator (==)
You shouldn't use == to test for string equality anyway, as it will only test for reference equality; use equals to test whether two string references refer to equal (but potentially distinct) string objects.
Additionally, you're trying to return a String variable as an int, and you're not even calling getRoman...
I think we can tell you that the correct way to compare Strings is using equals().
You're doing assignments, to compare primitive types you've to use ==, to compare String the equals method.
Example:
if (val.equals("I"))
But also val is not present in the method getRoman().
You are trying to parse val as an int, but its not, its a character.
For such a small sample of chars, its probably easiest to simply create a lookup table, index it on the char.
Are you getting any errors?
In your code, you never call the getRoman function. Also, you're using the assignment operator = instead of the comparison operator "I".equals(val) for example.
String comparsion should be done with equals(String str) method instead of == comparison.
PS. You have = instead of == anyway.
The following statement is an assignment:
val = "I"
That is definitely not what you want to do here.
A comparison is done with the double equals, but double equals (==) compares references but you do not want to do that here either.
You want to use the equals method.
if (val.equals("I")) ...
Make those change everywhere and see how it works for you.
ACtually your main trouble comes from string comparison. In java, = is meant to assign values to variables, == is meant to compare values of primitive types and equals is the way to compare objects, especially for strings.
An alternative to using equals can be to use the JDK internal pool of strings, in this case, you could use == as a comparator.
In your case of parsing roman language numbers, you could also consider using a hashmap to store and retrieve effectively the parsed values of numbers. If you have thousands of comparisons like this to make, then go for identityhashmap.
And last, if you want to do real parsing for all roman numbers, not only the first ones, then you should considering using an automata, i.e. a state machine to parse numbers in a somewhat recursive way, that would be the more efficient model to apply to your problem.
The last 2 remarks are more oriented towards software algorithms, the first two ones are more oriented towards java syntax. You should start to know the syntax before going higher level optimizations.
Regards,
Stéphane
Aside from what was said above about how your String comparison should use the equals( ... ) function - for example,
if ( val.equals("VII") )
you also need to provide a return value for your function called getRoman. This function was declared as a function that returns an integer value to the caller, but in the implementation that you have provided, there are no return values (only System.out.println( ... )).
Also, you aren't inputting the correct parameter type - from what it looks like, your function is checking a String to see if it is a certain Roman numeral. So the correct function header would look like this:
public static int getRoman(String val)
Also, make sure you are actually calling this function in your main() - from what it looks like right now, you aren't even using the getRoman() function.
Hope this helps!

Categories