String toString method in BST (binary search tree) - java

Why the next method does not print nothing but when i change the String s to array , it works Properly?
not working:
public String toString(){
//In-Order - left,root,right.
String s ="";
toString(root,s);
return s;
}
public void toString(BSTNode root,String s){
if (root!=null){
toString(root.left,s);
s=s+","+ root.data;
toString(root.right,s);
}
}
working:
public String toString(){
//In-Order - left,root,right.
String[] s =new String[1];
s[0]="";
toString(root,s);
return s[0];
}
public void toString(BSTNode root,String[] s){
if (root!=null){
toString(root.left,s);
s[0]=s[0]+","+ root.data;
toString(root.right,s);
}

When you create an array of String and pass, basically it is creating String object (like we create using new operator). So it sues the same reference and modifies the String as you work on it. But in the former case, it treat them as two separate variable like the primitive type are handled in java.
public class StringTest {
public static void main(String[] args) {
String s[] = new String[1];
System.out.println("before: "+s[0]);
updateString(s);
System.out.println("after: " + s[0]);
}
private static void updateString(String s[]) {
s[0] = "New String";
}
}
output of the program is:
before: null
after: New String
Otherwise, it does not print anything.

The reason is, that String is not a normal Reference-Type. If you change a String a new String is generated and the modified one is returned (String is immutable). (See String.replace() for example)
If you change your method to look like this, it should probably work:
public String toString(){
//In-Order - left,root,right.
return toString(root,s);
}
public String toString(BSTNode root,String s){
if (root!=null){
return toString(root.right,toString(root.left,s)+","+root.data);
}
return "";
}

Strings in java are immutable, this means that every time you assign them a new value a new object is actually created and the reference changes.

Related

Trying to loop through an array within an array

I am trying to print each part of my noteArray (eg: 19, and then "D" as separate parts) But by using a For loop I get an a mumble up print message for each line. The "processNotes(noteArray)" method is how I want my output to look.
Any help would be much appreciated!
public class question2 {
public static void main(String[] args) {
Note[] noteArray = new Note[5];
noteArray[0] = new Note(19, "D");
noteArray[1] = new Note(10, "C");
noteArray[2] = new Note(23, "F");
noteArray[3] = new Note(20, "B");
noteArray[4] = new Note(32, "C");
processNotes(noteArray);
for(Note i : noteArray){
System.out.println(i);
}
}
private static void playNote() {
int numberDuration = Note.getduration();
String letterPitch = Note.getpitch();
System.out.println("The note "+ letterPitch +" is played for "+
numberDuration +" seconds.");
return;
}
public static void processNotes(Note[] notes) {
playNote();
}
}
class Note
{
private static String pitch;
private static int duration;
public Note(int duration, String pitch) {
this.pitch = "C";
this.duration = 10;
}
public static int getduration() {
return duration;
}
public void setduration(int duration) {
Note.duration = duration;
}
public static String getpitch() {
return pitch;
}
public void setpitch(String pitch) {
Note.pitch = pitch;
}
}
EDIT:
Output I would like:
The note C is played for 10 seconds.
Output of arrays I get:
Note#6d06d69c
Note#7852e922
Note#4e25154f
Note#70dea4e
Note#5c647e05
You have two possibility.
First, override your toString() method so that it prints your notes as you want when you System.out.println().
Second, you can in your loop, instead of printing the note :
for(Note i : noteArray){
System.out.println(i.getPitch());
System.out.println(i.getDuration());
}
Add the following to your Note class:
public String toString() {
return "Duration = " + duration + ", pitch = " + pitch;
}
Demo
From object.toString:
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all
subclasses override this method.
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character `#', and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
You can override this method for a more meaningful output.
Suggested further read: The connection between 'System.out.println()' and 'toString()' in Java
You can just override toString method of the Note class, as sysout implicitly call toString.

Java String not behaving like an object? [duplicate]

This question already has answers here:
String is immutable. What exactly is the meaning? [duplicate]
(19 answers)
Closed 6 years ago.
As far as I know a String in Java is not a primitive but an object. Java also has some shortcuts to make working with Strings easier, so that we don't have to use new String() or joining two Strings with the + operator.
So I wrote the following little test:
package programming.project.test;
public class JavaStringTests {
public static void main(String[] args) {
String test1 = new String("uno dos ");
MyString test2 = new MyString("uno dos ");
System.out.println(test1);
System.out.println(test2);
extendMe(test1);
extendMe(test2);
//primitive-like behavior?
System.out.println("(String) -> " + test1);
//expected if String is not a primitive
System.out.println("(MyString) -> " + test2);
}
private static void extendMe(MyString blubb) {
blubb.add("tres ");
}
private static void extendMe(String blubb) {
blubb = blubb + "tres ";
}
}
The MyString class:
public class MyString {
String str;
public MyString(String str) {
this.str = str;
}
public String toString() {
return str;
}
public void add(String addme) {
str += addme;
}
}
Produces the following output:
uno dos
uno dos
(String) -> uno dos
(MyString) -> uno dos tres
If String is an object, why does it automatically create a new instance of it when passed as an argument? Is String some sort of primitive-like object, something in between primitive and object?
extendMe doesn't do what you think it does. Strings are immutable, they can't be changed. String.concat() doesn't change the string, it returns a new instance, which you discard in your code.
private static void extendMe(String blubb) {
blubb.concat("tres ");
}
Here String.concat returns a new String with concated value.
Where as
private static void extendMe(MyString blubb) {
blubb.concat("tres ");
}
Here you are adding the concated value to your internal str state.

how to make more than condition in toString method

I want to list all names that end with "Reda" and ignore case sensitivity, I have tried the condition in the toString method at the bottom, but it would not print any thing.
public class Customer {
public static void main(String[] args) throws IOException {
File a = new File("customer.txt");
FileWriter v = new FileWriter(a);
BufferedWriter b = new BufferedWriter(v);
PrintWriter p = new PrintWriter(b);
human Iman = new human("Iman", 5000);
human Nour = new human("Nour", 3500);
human Redah = new human("Redah", 0);
human iman = new human("iman", 200);
human MohamedREDA = new human("MohamedREDA", 3000);
human Mohamed_Redah = new human("Mohamed Redah", 2000);
human[] h = new human[6];
h[0] = Iman;
h[1] = Nour;
h[2] = Redah;
h[3] = iman;
h[4] = MohamedREDA;
h[5] = Mohamed_Redah;
p.println(Iman);
p.println(Nour);
p.println(Redah);
p.println(iman);
p.println(MohamedREDA);
p.println(Mohamed_Redah);
p.flush();
}
}
class human {
public String name;
public double balance;
public human(String n, double b) {
this.balance = b;
this.name = n;
}
#Override
public String toString() {
if (name.equalsIgnoreCase("Reda") && (name.equalsIgnoreCase("Reda"))) {
return name + " " + balance;
} else
return " ";
}
}
Please avoid putting condition in toString method. Remove the condition there
public String toString() {
return name + " " + balance;
}
and change your logic in Customer class
human[] h = new human[6];
h[0] = Iman;
h[1] = Nour;
h[2] = Redah;
h[3] = iman;
h[4] = MohamedREDA;
h[5] = Mohamed_Redah;
for (int i = 0; i < h.length; i++) {
if (h[i].name.toLowerCase().endsWith("reda")) { // condition here
p.println(h[i]);
}
}
And make use of loops do not duplicate the lines of code.Every where you are manually writing the lines.
Check Java String class and use required methods to add condition.
String redahname = ("Redah").toLowerCase(); //put your h[0] instead of ("Redah")
if(name.endsWith("redah")){ //IMPORTANT TO BE IN LOWER CASE, (it is case insenitive this way)
//your code here if it ends with redag
System.out.println(redahname);
} //if it does not end with "redah" it wont out print it!
You can use this, but can you please explain your question more? What exactly do you need?
try this
#Override
public String toString() {
if (name.toLowerCase().endsWith("reda"))) {
return name + " " + balance;
} else
return " ";
}
String.equals() is not what you want as you're looking for strings which ends with "Reda" instead of those equal to "Reda". Using String.match or String.endsWith together with String.toLowerCase will do this for you. The following is the example of String.match:
public class Reda {
public static void main(String[] args) {
String[] names = {"Iman", "MohamedREDA", "Mohamed Redah", "reda"};
for (String name : names) {
// the input to matches is a regular expression.
// . stands for any character, * stands for may repeating any times
// [Rr] stands for either R or r.
if (name.matches(".*[Rr][Ee][Dd][Aa]")) {
System.out.println(name);
}
}
}
}
and its output:
MohamedREDA
reda
and here is the solution using endsWith and toLowerCase:
public class Reda {
public static void main(String[] args) {
String[] names = {"Iman", "MohamedREDA", "Mohamed Redah", "reda"};
for (String name : names) {
if (name.toLowerCase().endsWith("reda")) {
System.out.println(name);
}
}
}
}
and its output:
MohamedREDA
reda
You shouldn't put such condition in toString() method cause, it's not properly put business application logic in this method.
toString() is the string representation of an object.
What you can do, is putting the condition before calling the toString() , or making a helper method for this.
private boolean endsWithIgnoringCase(String other){
return this.name.toLowerCase().endsWith(other.toLowerCase());
}
None of your humans are called, ignoring case, Reda, so your observation of no names printed is the manifestation of properly working logic.
Your condition is redundant: you perform the same test twice:
name.equalsIgnoreCase("Reda") && (name.equalsIgnoreCase("Reda"))
If you need to match only the string ending, you should employ a regular expression:
name.matches("(?i).*reda")
toString is a general-purpose method defined for all objects. Using it the way you do, baking in the business logic for just one special use case, cannot be correct. You must rewrite the code so that toString uniformly returns a string representation of the object.

Behavior of return statement in catch and finally

public class J {
public Integer method(Integer x)
{
Integer val = x;
try
{
return val;
}
finally
{
val = x + x;
}
}
public static void main(String[] args)
{
J littleFuzzy = new J();
System.out.println(littleFuzzy.method(new Integer(10)));
}
}
It will return "10".
Now I just replace Return type Integer to StringBuilder and Output was changed.
public class I {
public StringBuilder method(StringBuilder x)
{
StringBuilder val = x;
try
{
return val;
}
finally
{
val = x.append("aaa");
}
}
public static void main(String[] args)
{
I littleFuzzy = new I();
System.out.println(littleFuzzy.method(new StringBuilder("abc")));
}
}
OutPut is "abcaaa"
So, Anybody can explain me in detail.?
what are the differences.?
Just because integer in immutable so after method returns even if value is changed in method it does not reflect, and does reflect in StringBuilder Object
EDIT:
public class J {
public String method(String x) {
String val = x;
try {
return val;
} finally {
val = x + x;
}
}
public static void main(String[] args) {
J littleFuzzy = new J();
System.out.println(littleFuzzy.method("abc"));
}
}
The principal operations on a StringBuilder are the append and insert methods, which are overloaded so as to accept data of any type. Each effectively converts a given datum to a string and then appends or inserts the characters of that string to the string builder. The append method always adds these characters at the end of the builder; the insert method adds the characters at a specified point.
For example, if z refers to a string builder object whose current contents are "start", then the method call z.append("le") would cause the string builder to contain "startle", whereas z.insert(4, "le") would alter the string builder to contain "starlet".
In general, if sb refers to an instance of a StringBuilder, then sb.append(x) has the same effect as sb.insert(sb.length(), x). Every string builder has a capacity. As long as the length of the character sequence contained in the string builder does not exceed the capacity, it is not necessary to allocate a new internal buffer. If the internal buffer overflows, it is automatically made larger.
Instances of StringBuilder are not safe for use by multiple threads. If such synchronization is required then it is recommended that StringBuffer be used.
In above method, finally block is calling everytime.
When an object is passed, the copy of its reference gets passed and you can change the contents if it is mutable.

I have to test Java

I was told in my class that I have to write and test my code in the main method, I wrote it, but I dont know how to test it. How I am supposed to test my methods? I am supposed to take user input, and then get the get the first letter, last letter, etc.
import java.util.Scanner;
public class Word
{
public static void main(String[] args)
{
}
public String word;
public void Word()
{
String word = "";
}
public void Word(String word1)
{
String word = word1;
}
public String getWord()
{
return word;
}
public void setWord(String newWord)
{
String word = newWord;
}
public void getFirstLetter()
{
String firstLetter = word.substring(0, 1);
}
public void getLastLetter()
{
String lastLetter = word.substring(word.length() - 1, word.length());
}
public void removeFirstLetter()
{
String noFirstLetter = word.substring(1, word.length());
}
public void removeLastLetter()
{
String noLastLetter = word.substring(0, word.length() - 1);
}
public int findLetter (String parameter)
{
word.indexOf(parameter);
return 1;
}
}
You test your methods by calling them with some defined input and compare the results with your expected output.
Example:
Suppose you have a method like this:
public static int add(int a, int b) {
return a + b;
}
You'd test it like this:
int result = add( 3, 5);
if( result != 8 ) {
//method is wrong
}
So basically you define a "contract" of what input the method gets and what the result should be (in terms of return value or other changed state). Then you check whether you get that result for your input and if so you can assume the method works correctly.
In order to be quite sure (you often can't be perfectly sure) you'd test the method several times with different types of input (as many as reasonable, to test different cases, e.g. short words, long words).
You often also test how your method handles wrong input, e.g. by passing null or empty strings.
You should have a look at tools like junit.
You can create a simple Test class and test your class and its behavior.
imports ...;
public class MyTest{
#Test
public void testMyClass(){
Word w= new Word();
w.setWord("test");
Assert.assertEquals(w.getFirstLetter(), "t");
}
}
With tools like Eclipse you could nicely run such a test.
Just a hint: you're very close you need an instance of Word, than you can call your methods
public static void main(String[] args) {
Word test = new Word();
test.setWord("something");
// here you might read javadoc of the String class on how to compare strings
}
EDIT:
I overlooked this:
public void setWord(String newWord)
{
String word = newWord;
}
The code you've written creates a variable word and newWord is assigned to it and then disappears.
If you (obviously) want to set a member of a class you should use this wich references the instance (you created in main()).
public void setWord(String newWord) {
this.word = newWord;
}
Since I would say this is homework, I will try not to explicitly give the answer. In the main method, you should set your word, then call each method and print the output to verify it is correct.
Agree with Jason. If you wanna test something, simply System.out.println() it. In your methods though, your return type is not a String but a void, so you could change that, and print it out on the main program run.
If not, just put the System.out.println() in your void methods. Shouldn't have much of a problem!

Categories