Doing some beginner problems for Java:
Given two strings, append them together (known as "concatenation") and return the result.
However, if the concatenation creates a double-char, then omit one of the chars, so "abc" and "cat" yields "abcat".
My code:
public static String conCat(String a, String b) {
//abc (c) == cat (c)
if (a.substring(a.length()-1,a.length()) == b.substring(0,1)) {
//return (ab) + (cat)
return a.substring(0,a.length()-2) + b;
//cat (c) == abc (c)
} else if(b.substring(0,1) == a.substring(a.length()-1,a.length())) {
//return (abc) + (at)
return a + b.substring(2,b.length());
} else if (a.equals("") || b.equals("")) {
return a + b;
}
}
I don't understand why Eclipse can't recognise the String returns.
First of all, you are comparing Strings with ==, which compares them by reference. This means that equal Strings might not return true. To avoid this problem, always use .equals() to compare Strings.
Second, keep in mind that your if statements are checked in the order specified. Since you want to check for empty strings first, you should put that one on top.
Third, you have to return something on all codepaths. If all of the if statements are false, you don't return anything. If you add else return a + b; you should get the desired behavior.
Furthermore, I suggest using a slightly different approach:
public static String conCat(String a, String b) {
//If either String is empty, we want to return the other.
if (a.isEmpty()) return b;
else if (b.isEmpty()) return a;
else {
//If the last character of a is the same as the first character of b:
//Since chars are primitives, you can (only) compare them with ==
if (a.charAt(a.length()-1) == b.charAt(0))
return a + b.subString(1);
//Otherwise, just concatenate them.
else
return a + b;
}
}
Note that you can omit the else blocks, since return will end the execution of the method there, so this will also work:
public static String conCat(String a, String b) {
if (a.isEmpty()) return b;
if (b.isEmpty()) return a;
if (a.charAt(a.length()-1) == b.charAt(0)) return a + b.subString(1);
return a + b;
}
actually, it can. but all your return statements are depending on a condition, so there 'll be cases for which you haven't provided a return statement.
in those cases, the method won't return anything, even while it should return a String.
add:
return "";
or
return null;
to the end of your method and try again.
Related
I am more interested about why does not the return function work. Not about the optimization or my method of thinking.
I have tried a simple program to check recursively if a String is palindrome or not.
package palindrom;
public class PalindromString {
public static boolean isPalindrom(String myText) {
char f = myText.charAt(0);
char l = myText.charAt(myText.length() - 1);
if (f != l) {
return false;
}
else {
if (myText.length() > 1) {
isPalindrom(myText.substring(1, myText.length() - 1));
} else {
return true;
}
}
return true;
}
public static void main(String[] args) {
String text = "cococbc";
System.out.println(isPalindrom(text));
}
}
For the first step , the program takes that first "c" char and the last one and it compares them, then the function is called again , this time with the "ococb" String.
The function takes the "o" char and "b" , it compares them , it sees that they are not equal , it goes to the "return false;" statement , and yet it returns true ?
Can you help me with this ? I really want to understand why it behaves this way :|.
it sees that they are not equal , it goes to the "return false;" statement , and yet it returns true ?
Yes, isPalindrom("ococb") returns false, but when that recursive call returns, you ignore its return value, and therefore isPalindrom("cococbc") returns true. You need to return isPalindrom(myText.substring(1, myText.length() - 1)) in order to fix that.
Besides that issue, you should also change the condition to require myText.length() is at least 3, otherwise you may pass an emptyString` to the recursive call, since you are removing the first and last characters.
if (myText.length() >= 3) {
return isPalindrom(myText.substring(1, myText.length() - 1));
} else {
return true;
}
After you make that change you should remove the final return true;, which will no longer be reachable.
You might also consider adding a check for a null or empty String at the beginning, in order for your method not to throw an exception when called for a null or empty String.
I need some help with 2 methods that I'm using.
My first method looks at each character after the first (0th) in the string s and checks if they're digits but I cannot get it to fully work.
/**
* Forms the latter 5 characters of the accountNum String into a substring
which is checked to
* see if all characters are positive integers
*/
public Boolean hasValidDigits(String s)
{
for(int i=1; i<s.length(); i++)
if (Character.isDigit(s.charAt(i))) {
return true;
}
}
The issue with the method is it's asking for a return statement for the 'for' and I'm not sure why.
My second method calls methods from other parts of the class to check a string s.
/**
* Checks the following three criteria:
* - Is a string of length 6
* - Starts with a capital Letter
* - Subsequent characters are positive integers
*/
public Boolean isValidAccountNum(String s)
{
if (s.isValidLength() s.isValidStart() s.hasValidDigits()) {
return true;
} else {
return false;
}
}
The issue with this method is it's saying "Cannot find symbol - method isValidLength()
I'm guessing it would have same error with the other methods.
The methods I want to call are all made public. I'll include the isValidLength() below.
/**
* Checks if the variable accountNum has a length of 6 characters
*/
public Boolean isValidLength(String s)
{
if (s.length()==6) {
return true;
} else {
return false;
}
}
Your first method might not return anything if your if condition is not true so you need to return something at last line of function.
Your second method does not have passed any parameters and syntactically incorrect as well.
Please check out your language syntax first and practice some basic examples for your understanding of java
Your methods accept a String as a parameter, they are not part of the String class. So you have to do this isValidLength(s) rather than s.isValidLength().
Further, you cant have multiple method calls inside the parenthesis of an if statement, without a logical operator in between (&& for and, || for or).
Also, your hasValidDigits does not do what you think, it will return true if one of the character is a digit, rather than all of them. Also, the first part of the javadoc comment on this method is nowhere near true. It also lacks a return when the if statement never evaluates to true.
So what you want is something like this:
public Boolean isValidLength(String s) {
return s.length == 6;
}
//this checks all characters of the string though,
//your javadoc said something about checking the last 5 characters..
public Boolean hasValidDigits(String s) {
for(int i=1; i<s.length(); i++)
if (!Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
}
public Boolean isValidAccountNum(String s) {
return isValidLength(s) && isValidStart(s) && hasValidDigits(s);
}
The first method might performs a loop but will return at the first iteration if it is a digit it does not check the whole string and there is no false returned e.g.:
public Boolean hasValidDigits(String s) {
for (int i = 1; i < s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
}
the isValidAccountNum method can just return the statement as it is already a boolean expression
return s.isValidLength() && s.isValidStart() && s.hasValidDigits();
same for the isValidLength method for the same reason:
return s.length()==6;
My enum declaration:
public enum Note { A, A_SHARP, B, C, C_SHARP, D, D_SHARP,
E, F, F_SHARP, G, G_SHARP;
public String toString(Note note) {
if (note == Note.A)
return "A";
else if (note == Note.A_SHARP)
return "A#";
else if (note == Note.B)
return "B";
else if (note == Note.C)
return "C";
else if (note == Note.C_SHARP)
return "C#";
else if (note == Note.D)
return "D";
else if (note == Note.D_SHARP)
return "D#";
else if (note == Note.E)
return "E";
else if (note == Note.F)
return "F";
else if (note == Note.F_SHARP)
return "F#";
else if (note == Note.G)
return "G";
else if (note == Note.G_SHARP)
return "G#";
else
return "";
}
public Note getNext() {
int index = ordinal();
index++;
if (index > values().length)
return values()[0];
else
return values()[index];
}
}
Whenever I call either of these two methods, my app crashes. Here is where I call them:
public void ChangeSound(View v) {
note = note.getNext();
tvSounds.setText(note.toString(note));
}
ChangeSound() is an onClick method for a button. If I remove both lines in ChangeSound(), the code works as it should, but if either of the two lines are in there, the app crashes on the button click. Any ideas why? Thanks in advance!!
EDIT**
note is a variable of type Note
Thank you everyone! It was returning null (look at Jason C's answers (my comment)). All of this was helpful for me!
You should use >= since probably you're getting some OutOfBoundsException
if (index >= values().length)
return values()[0];
else
return values()[index];
}
Also instead of switch you could sth like that:
public enum Note { A("A"), A_SHARP("A#"), B("B");
private String s;
public Note (String s) {
this.s = s;
}
public String toString() {
return s;
}
Change this:
if (index > values().length)
to this:
if (index >= values().length)
It's unclear what you mean by "crashes", and you also do not show enough context (what is 'note'?) but the most likely cause based on the fact that you stated either of those two lines crash seems to be that 'note' is null. If 'note' is null then ChangeSound will throw a NullPointerException. You need to make sure that if ChangeSound is assuming 'note' is not null, that that is actually the case.
Also you should make toString(Note) a static method, and define a non-static toString() override. This will give Note.toString(Note) the ability to handle nulls correctly:
public static String toString (Note n) {
return n == null ? "" : n.toString();
}
Edit: As noted in other answers, you should use >= instead of > (even == would be sufficient), that is also a potential problem.
The issue has already been spotted by the other answers. Note however that you could simplify your code in two ways:
by associating the String representation of the notes with the enum constants directly
by using a modulus instead of your if/else in getNext
It could look like:
public enum Note { A("A"), A_SHARP("A#"), B("B"), C("C"), C_SHARP("C#"), D("D"),
D_SHARP("D#"), E("E"), F("F"), F_SHARP("F#"), G("G"), G_SHARP("G#");
private final String noteName;
Note(String noteName) {
this.noteName = noteName;
}
#Override
public String toString() {
return noteName;
}
public Note getNext() {
int nextIndex = (ordinal() + 1) % values().length;
return values()[nextIndex];
}
}
And in your main code:
note = note.getNext();
tvSounds.setText(note.toString());
I was trying this code writing exercise and I am so lost!
The exercise is:
Complete the method which takes two Strings and one boolean as input. If the boolean is true, this method compares the first two Strings, ignoring case considerations (uppercase/lowercase). Two Strings are considered equal ignoring case if they are of the same length, and corresponding characters in the two Strings are equal ignoring case.
If the boolean is false, this method should compare two Strings and return true if the first String represents the same sequence of characters as the second String, otherwise false.
Note: compareTwoStrings("HELLO", "", false) should return false.
And here is my attempt:
public boolean compareTwoStrings (String a, String b, boolean isIgnoreCase)
{
if (a.equalsIgnoreCase(b)) {
return (isIgnoreCase==true);
}
else if (a.equals(b)) {
return (isIgnoreCase==false);
}
}
It doesn't even compile, but even if it did, I'm sure it wouldn't work.
You're doing it backwards. The subject says: if the boolean is true, then do this, else, then do that. So you should program it the same way:
if (isIgnoreCase) {
return ...
}
else {
return ...
}
The rest is left as an exercise. You should be able to figure it out by yourself.
I think the requested solution is the following method:
public boolean compareTwoStrings(String a, String b, boolean isIgnoreCase)
{
if (isIgnoreCase)
{
return a.equalsIgnoreCase(b);
}
return a.equals(b);
}
Your method das not compile because the Java compiler supposes that unter some circumstances both if conditions evalutes to false. Because of that the compiler can not ensure that at least one return statement is reachable.
This could be the solution for your problem:
public boolean compareTwoStrings (String a, String b, boolean isIgnoreCase){
if (isIgnoreCase)
return (a.toLowerCase()).equals(b.toLowerCase());
else
return a.equals(b);
}
I think this is what you are looking for.
public static void myMethod(String str, String str2, boolean bool) {
if (bool) {
str = str.toLowerCase();
str2 = str2.toLowerCase();
if (str.equals(str2))
System.out.println("strings equal");
}
else {
System.out.println("false condition");
}
}
I created a Java program to compare two strings:
String str = "Hello";
if (str.equals("hello")) {
System.out.println("match");
} else {
System.out.println("no match");
}
It's case-sensitive. How can I change it so that it's not?
The best way is to use str.equalsIgnoreCase("foo"). It's optimized specifically for this purpose.
You can also convert both strings to upper- or lowercase before comparing them with equals. This is a trick that's useful to remember for other languages which might not have an equivalent of equalsIgnoreCase.
str.toUpperCase().equals(str2.toUpperCase())
If you are using a non-Roman alphabet, take note of this part of the JavaDoc of equalsIgnoreCase which says
Note that this method does not take locale into account, and will
result in unsatisfactory results for certain locales. The Collator
class provides locale-sensitive comparison.
Use String.equalsIgnoreCase().
Use the Java API reference to find answers like these:
https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#equalsIgnoreCase(java.lang.String)
https://docs.oracle.com/javase/1.5.0/docs/api/
String.equalsIgnoreCase is the most practical choice for naive case-insensitive string comparison.
However, it is good to be aware that this method does neither do full case folding nor decomposition and so cannot perform caseless matching as specified in the Unicode standard. In fact, the JDK APIs do not provide access to information about case folding character data, so this job is best delegated to a tried and tested third-party library.
That library is ICU, and here is how one could implement a utility for case-insensitive string comparison:
import com.ibm.icu.text.Normalizer2;
// ...
public static boolean equalsIgnoreCase(CharSequence s, CharSequence t) {
Normalizer2 normalizer = Normalizer2.getNFKCCasefoldInstance();
return normalizer.normalize(s).equals(normalizer.normalize(t));
}
String brook = "flu\u0308ßchen";
String BROOK = "FLÜSSCHEN";
assert equalsIgnoreCase(brook, BROOK);
Naive comparison with String.equalsIgnoreCase, or String.equals on upper- or lowercased strings will fail even this simple test.
(Do note though that the predefined case folding flavour getNFKCCasefoldInstance is locale-independent; for Turkish locales a little more work involving UCharacter.foldCase may be necessary.)
You have to use the compareToIgnoreCase method of the String object.
int compareValue = str1.compareToIgnoreCase(str2);
if (compareValue == 0) it means str1 equals str2.
import java.lang.String; //contains equalsIgnoreCase()
/*
*
*/
String s1 = "Hello";
String s2 = "hello";
if (s1.equalsIgnoreCase(s2)) {
System.out.println("hai");
} else {
System.out.println("welcome");
}
Now it will output : hai
In the default Java API you have:
String.CASE_INSENSITIVE_ORDER
So you do not need to rewrite a comparator if you were to use strings with Sorted data structures.
String s = "some text here";
s.equalsIgnoreCase("Some text here");
Is what you want for pure equality checks in your own code.
Just to further informations about anything pertaining to equality of Strings in Java. The hashCode() function of the java.lang.String class "is case sensitive":
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
So if you want to use an Hashtable/HashMap with Strings as keys, and have keys like "SomeKey", "SOMEKEY" and "somekey" be seen as equal, then you will have to wrap your string in another class (you cannot extend String since it is a final class). For example :
private static class HashWrap {
private final String value;
private final int hash;
public String get() {
return value;
}
private HashWrap(String value) {
this.value = value;
String lc = value.toLowerCase();
this.hash = lc.hashCode();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof HashWrap) {
HashWrap that = (HashWrap) o;
return value.equalsIgnoreCase(that.value);
} else {
return false;
}
}
#Override
public int hashCode() {
return this.hash;
}
}
and then use it as such:
HashMap<HashWrap, Object> map = new HashMap<HashWrap, Object>();
Note that you may want to do null checks on them as well prior to doing your .equals or .equalsIgnoreCase.
A null String object can not call an equals method.
ie:
public boolean areStringsSame(String str1, String str2)
{
if (str1 == null && str2 == null)
return true;
if (str1 == null || str2 == null)
return false;
return str1.equalsIgnoreCase(str2);
}
Use s1.equalsIgnoreCase(s2): https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#equalsIgnoreCase(java.lang.String).
You can use equalsIgnoreCase
More about string can be found in String Class and String Tutorials
To be nullsafe, you can use
org.apache.commons.lang.StringUtils.equalsIgnoreCase(String, String)
or
org.apache.commons.lang3.StringUtils.equalsIgnoreCase(CharSequence, CharSequence)
public boolean newEquals(String str1, String str2)
{
int len = str1.length();
int len1 = str2.length();
if(len==len1)
{
for(int i=0,j=0;i<str1.length();i++,j++)
{
if(str1.charAt(i)!=str2.charAt(j))
return false;
}`enter code here`
}
return true;
}