String trim() method - java

In Java I have written below code for string trim() method.
if(" String ".trim() == "String")
System.out.println("Equal");
else
System.out.println("Not Equal");
It gives output Not Equals which I understood because " String ".trim() had returned new String object reference .
But when I trim and compare without white spaces it gives output Equals.
if("String".trim() == "String")
System.out.println("Equal");
else
System.out.println("Not Equal");
If String is not having white spaces what trim() method returns?
I know equals() I can use but in my exam I got this question.

Did you look at the API? This is clearly stated in documentation of trim() method:
Returns: A copy of this string with leading and trailing white space
removed, or this string if it has no leading or trailing white space.
You could have also gone through the source code. The trim() method returns this, if there are no whitespaces removed at either ends:
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
So, if both st > 0 and len < value.length are false, which would be case for strings that don't have whitespaces at either ends, it returns this.
Now, why "String" == "String" is true is by the virtue of String interning. You can get lot more information about this through google.

If the trim() method would do nothing (because the string is already trimmed), the same string object (ie this) is returned.
String interning means that the string constant "String" is the exact same object used throughout the code wherever "String" is used.
These two facts together is why == is true for the comparison of "String".trim() == "String".

The == operator checks if it is the same object.
To compare equality of the object, use .equals() method.
In your second case, the String which doesnt have whitespaces will no do anything to the Object. Hence it is equal, since the object is the same.

Related

how to check if there is no text in the textfield so that error message can b displayed

if(namefield.getText().compareTo("")==0)
Is this code above correct to check that no input is there in the textfield so that a error message can be generated?
provided have to use compareTo func only
to be more accurate
String data = nameField.getText()
if(data==null || data.length()==0)
{
//show error message here
}
It depends on how the namefield.getText() method is implemented in your platform. Since you didn't method which platform you are using. I suggest you can check the documentation.
Generally, when the namefield is not set, namefield.getText() will return a empty String which is "". So we don't need to check if it's null.
So we can check using following code:
if(namefield.getText().isEmpty()){}
which is same as following:
if(namefield.getText().length()==0){}
Because String.isEmpty() method is implemented as following:
public boolean isEmpty() {
return value.length == 0;
}
On the other hand, when the namefield.getText() can return null. You need to check null to avoid NPE.
String name = namefield.getText();
if(name==null || name.isEmpty()){}
Finally, if you want to check if the input string is whitespace, you can simply use String.trim() to remove the whitespace.
if(namefield.getText().trim().isEmpty()){}
or
String name = namefield.getText();
if(name==null || name.trim().isEmpty()){}
Even though we can use name.equals(""), I don't think it's the best way. Since in String.equals method, it firstly check if the objects are the same and then use the length to check if they're equal. However, when we get a text from a Textfield, the object will not be the same with the constant string "".
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
The method compareTo() is used for comparing two strings lexicographically. Each character of both the strings is converted into a Unicode value for comparison. If both the strings are equal then this method returns 0 else it returns positive or negative value. The result is positive if the first string is lexicographically greater than the second string else the result would be negative.
Instead use equals()
if(namefield.getText().equals(null) || namefield.getText().equals(""))
{
//do this
}
I would use
if((namefield.getText()== null) || (namefield.getText().length() == 0)){
show error message
}

StringIndexOutOfBounds when removing adjacent duplicate letters

Here is my code:
public static String removeAdjDuplicates(String s) {
if(s == "" || s == null || s.isEmpty())
return s;
if(s.length() < 2)
return s;
if(s.charAt(0) != s.charAt(1))
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
if(s.charAt(0) == s.charAt(1)) //line 37
return removeAdjDuplicates(s.substring(2));
return s;
}
With the input string "ull", I get the following error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.charAt(String.java:658)
at GFG.removeAdjDuplicates(File.java:37)
at GFG.main(File.java:16)
I read and tried answers given to similar questions, but I'm not sure what is wrong.
Judging from the exception that you get, removeAdjDuplicates returns an empty string, invalidating all indexes past zero.
Although your code performs length checking at the top, it also performs this assignment when the two initial characters are different:
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
This means that s can become a one-character string if removeAdjDuplicates returns an empty string.
As you Try to pass this string "ull" to the method the last letter in the String should be the letter "u" because you use this
if(s.charAt(0) != s.charAt(1))
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
as you dont return the String back like the other conditions in the method it will continue to the next condition at line 37
and u have only one letter while the condition checking the first and the second characters ... there is no second letter so you get this error .. so the solution is to return s like this
if(s.charAt(0) != s.charAt(1)){
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
return s;
}
I think the source of the error is sufficiently explained by #dasblinkenlight's answer.
Although not clearly stated in the question, it looks like you're trying to remove adjacent duplicate letters recursively (one of your comments mentions that you would expect output s for input geegs).
Here's an alternative way to do it:
while(!s.equals(s = s.replaceAll("(.)\\1", "")));
It uses a regular expression to match and remove duplicate characters, and the while loop keeps executing this until the string is no longer being modified by the operation.
You should simplify your code:
public static String removeAdjDuplicates(String s) {
if (s == null || s.length() < 2)
return s;
if (s.charAt(0) != s.charAt(1))
return s.charAt(0) + removeAdjDuplicates(s.substring(1));
return removeAdjDuplicates(s.substring(2));
}
Changes
The first two if statements do the same thing (return s;) and can be combined into one. Some of the conditions are redundant and can be eliminated.
The third if statement should immediately return instead of continuing into the fourth if statement (or you can instead change the fourth if statement into an else), because removedAdjDuplicates can return an empty String making s a length-one String when the fourth if is expecting at least a length-two String.
The fourth if can be eliminated because if (s.charAt(0) != s.charAt(1)) failed in the third if, then the only alternative is that (s.charAt(0) == s.charAt(1)), so the check for that isn't necessary.

Checking Character in a String using .equals() not working

I'm trying to check if a letter submitted by user is contained in a string, but it always return false. From what I read the .equals() function should work. I was expecting that if a user inputs the letter "a" it would return "pass" if the string was "america".
for (int i = 0; i < outputTest.length(); i++){
if (userInput.equals(outputTest.charAt(i))){
System.out.println("Pass");
}else {
System.out.println("Fail");
}
}
Based on outputTest.length() and outputTest.charAt() I am assuming that outputTest is String.
Based on userInput.equals I am assuming it is not primitive type like char (since primitive types don't have methods). It is also not Character, otherwise you would see Pass few times. So it most likely is also String.
outputTest.charAt(i) returns char, but you are comparing it with String which equals method looks like:
964 public boolean equals(Object anObject) {965 if (this == anObject) {966 return true;967 }968 if (anObject instanceof String) {969 String anotherString = (String)anObject;970 int n = value.length;971 if (n == anotherString.value.length) {972 char v1[] = value;973 char v2[] = anotherString.value;974 int i = 0;975 while (n-- != 0) {976 if (v1[i] != v2[i])977 return false;978 i++;979 }980 return true;981 }982 }983 return false;984 }
So since equals expects Object, char (returned from outputTest.charAt(i)) will be automatically boxed to Character, but since Character doesn't extend String test
if (anObject instanceof String)
will fail and you will immediately move to return false;.
You may want to use contains method if you want to check if one String contains another
outputTest.contains(userInput)
To find a string in another string, just do:
return text.contains(string);
To find a char in a string, do
return text.indexOf(ch) > -1;
What is the data type of your object userInput? You seem to be comparing a String object with a character which is returned by the charAt() method. That will always return false.
When you are learning to use methods, a good habit to develop is to look at what kind of data type the methods apply or return. For instance, you cannot code this: char scanner.nextLine() // nextLine() is to read String, not char. Therefore, in your code outputTest.charAt(i) // I am a char, and this userInput.equals() // I am a String, you are comparing different things. You cannot compare an apple with a desk because they are two different objects. The compiler will always tell you false.
I assume: String inputTest = scanner.nextLine(); for user input a letter, and you can consider "a" as a String with a length 1. (or any other letters inside)
if (outputTest.contains(userInput)) // now you are comparing String and String
System.out.println("Pass");
else
System.out.println("Fail");

the sequence of one-line code of Reverse Words in a string on leetcode

I have a small question about one answer of this problem.
the problem is like
Given an input string, reverse the string word by word.
For example,
Given s = "the sky is blue",
return "blue is sky the".
The answer is
public class Solution {
public String reverseWords(String s) {
s = s.trim();
return helper(s,0).toString();}
private StringBuilder helper(String s, int index){
if(index>=s.length())
return new StringBuilder();
StringBuilder cur = new StringBuilder();
int lastIndex = index;
while(index < s.length() && s.charAt(index)!=' ')
{
cur.append(s.charAt(index++));
}
while(index < s.length() && s.charAt(index)==' ')
index++;
if(lastIndex == 0)
return helper(s,index).append(cur);
return helper(s,index).append(cur).append(' ');}
I got a question about the last line of this code. why append(cur) is before append(' ')? shouldn't it be after?
Consider this part of the code :
if(lastIndex == 0)
return helper(s,index).append(cur);
return helper(s,index).append(cur).append(' ');
The condition (lastIndex == 0) is true in the first call to helper, in which case cur contains the first word, and helper(s,index) returns the remaining words in reverse order.
Since you append, in this case, the first word to the rest of the reversed StringBuilder without adding a space, this means that helper(s,index) must append a space after the reversed sub-string.
For example, suppose you have a String :
One Two Three
helper(s,index) must return "Three Two ", to which you append "One" to get the reversed String.
The next call to helper would return "Three ", to which you append "Two" and then a space.
The next call returns an empty StringBuilder, to which you append "Three" and then a space.
You could replace the 3 lines above with this single line :
return helper(s,index).append(' ').append(cur);
However, in this case the output will have an extra space in the beginning, since the last call to helper returns an empty StringBuilder, so if you append a space after it, that space would be the first character of the output.
You can add a different condition to eliminate that extra space :
StringBuilder sub = helper(s,index);
if (sub.length() > 0)
sub.append(' '); // append a space only if it's not the
// first char of the output
return sub.append(cur);

StringBuffer Append Space (" ") Appends "null" Instead

Basically what I'm trying to do is take a String, and replace each letter in the alphabet inside, but preserving any spaces and not converting them to a "null" string, which is the main reason I am opening this question.
If I use the function below and pass the string "a b", instead of getting "ALPHA BETA" I get "ALPHAnullBETA".
I've tried all possible ways of checking if the individual char that is currently iterated through is a space, but nothing seems to work. All these scenarios give false as if it's a regular character.
public String charConvert(String s) {
Map<String, String> t = new HashMap<String, String>(); // Associative array
t.put("a", "ALPHA");
t.put("b", "BETA");
t.put("c", "GAMA");
// So on...
StringBuffer sb = new StringBuffer(0);
s = s.toLowerCase(); // This is my full string
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
String st = String.valueOf(c);
if (st.compareTo(" ") == 1) {
// This is the problematic condition
// The script should just append a space in this case, but nothing seems to invoke this scenario
} else {
sb.append(st);
}
}
s = sb.toString();
return s;
}
compareTo() will return 0 if the strings are equal. It returns a positive number of the first string is "greater than" the second.
But really there's no need to be comparing Strings. You can do something like this instead:
char c = s.charAt(i);
if(c == ' ') {
// do something
} else {
sb.append(c);
}
Or even better for your use case:
String st = s.substring(i,i+1);
if(t.contains(st)) {
sb.append(t.get(st));
} else {
sb.append(st);
}
To get even cleaner code, your Map should from Character to String instead of <String,String>.
String.compareTo() returns 0 if the strings are equal, not 1. Read about it here
Note that for this case you don't need to convert the char to a string, you could do
if(c == ' ')
use
Character.isWhitespace(c)
that solves the issue. Best practice.
First, of all, what is s in this example? It's hard to follow the code. Then, your compareTo seems off:
if (st.compareTo(" ") == 1)
Should be
if (st.compareTo(" ") == 0)
since 0 means "equal" (read up on compareTo)
From the compareTo documentation: The result is a negative integer if this String object lexicographically precedes the argument string. The result is a positive integer if this String object lexicographically follows the argument string. The result is zero if the strings are equal;
You have the wrong condition in if (st.compareTo(" ") == 1) {
The compareTo method of a String returns -1 if the source string precedes the test string, 0 for equality, and 1 if the source string follows. Your code checks for 1, and it should be checking for 0.

Categories