for loop has "dead code" at i++ - java

public String toString() {
for(int i = 0; i<items.length; i++) { //i++ is considered "dead code"
return "Name: " + items[i].getName() + ", Is carn? " + items[i].getVeg() + ", Pop: " + items[i].getPop();
}
return null;
}
This method should go through an array and return the name, veg and pop. Works for items[0] but not further.

Your for loop is the same as:
int i = 0:
while (i < items.length) {
return "Name: " /* etc */;
i++; // Update.
}
If you enter the loop, you start to execute the body, and then return, so you never execute the update.
If you don't enter the loop, you don't execute the update.
So you don't execute the update, hence the update is dead code.

i++ is supposed to run after first and subsequent iterations, since code is returning without any condition in the first iteration itself i++ will never be reached.

This is considered "dead code" as the return statement will end the function so instead having the for loop just print the lines and then the function ceasing it's execution following the loop.
Or if you want to use the lines being made here for something, make an array of strings out of them and return that

Right, you're probably confused about what the return statement does. I think you're trying to do the following:
public String toString() {
final StringBuilder result = new StringBuilder();
for(int i = 0; i<items.length; i++) {
result.append("Name: ").append(items[i].getName())
.append(", Is carn? ").append(items[i].getVeg())
.append(", Pop: ").append(items[i].getPop())
.append("\n");
}
return result.toString();
}
The return statement does exactly that: it returns immediately from a method and returns a result (or nothing, in case of a void method). It doesn't somehow magically append to your expected result; you'll have to do that yourself.

return an Array or a List. Also it is better to make a method toString (or print if you already have toString) in your Item class. I would do it like this.
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Demo {
private Item[] items;
class Item {
private String name;
private boolean veg;
private String pop;
/* Constructor, getters and setters */
#Override
public String toString() {
return "Name: " + name + ", Is carn? " + veg + ", Pop: " + pop;
}
}
public List<String> listItemsString() {
return Stream.of(items).map(Item::toString).collect(Collectors.toList());
}
public String[] arrayItemsString() {
return Stream.of(items).map(Item::toString).toArray(String[]::new);
}
}

Related

I am able to enter ten entries for my TreeSet, but only the last entry prints out

The assignment asks for entry of 10 patient records, to include patientId, patientFirstName, patientLastName, patientIllness, and notes; this is to be put into a TreeSet with a Comparator that will abc by last name.
This is the section of code that I am struggling with:
public void patientRecord() {
int i = 0;
int patientRecords = 10;
Set<Patient> patientHashSet;
System.out.println("This program will create ten patient records.");
System.out.println();
do {
getPatientId();
getPatientFirstName();
getPatientLastName();
getPatientIllness();
getNotes();
patientHashSet = new TreeSet<>(new PatientComparator());
patientHashSet.add(new Patient(patientId, patientFirstName, patientLastName, patientIllness, notes));
i++;
} while (i < patientRecords);
for (Patient record : patientHashSet) {
System.out.println(record.patientId + " " + record.patientLastName + ", " + record.patientFirstName + " "
+ record.patientIllness + " " + record.notes);
System.out.println("##########################################################################");
}
}
And this is the Comparator code:
import java.util.Comparator;
public class PatientComparator implements Comparator<Patient> {
#Override
public int compare(Patient o1, Patient o2) {
return o1.patientLastName.compareTo(o2.patientLastName);
}
}
I'm not really sure what it is that I'm doing wrong. I have also tried placing the "add" into an array, but that produces the same results--only the last patient's information prints out, along with the line of "####".
Put this line above the loop
patientHashSet = new TreeSet<>(new PatientComparator());
In your code, it is written inside the loop, so it is creating a new set on every iteration.
Check the correction.

How do I separate strings with a comma and a space without having them being put before it?

Beginner programmer here.
I have to append strings of file names together and have come up with the following methods:
class ConsLoItem implements ILoItem {
Item first;
ILoItem rest;
ConsLoItem(Item first, ILoItem rest) {
this.first = first;
this.rest = rest;
}
public String images() {
if (this.rest.equals(new MtLoItem()))
{
return this.first.images();
}
else
return this.first.images() + ", " + this.rest.images();
}
}
and keep getting the same results, with:
", jesse.jpeg, " when I expect "jesse.jpeg".
Any ideas on how to remove the ", " from the beginning and end of the file name?
You can change your images method, like so
public String images() {
if (this.rest.equals(new MtLoItem())) {
return this.first.images();
} else { // missed a brace here.
if (this.first.images().length() > 0) {
return this.first.images() + ", " + this.rest.images();
}
return this.rest.images();
}
}

In Java, would all these methods be considered pure functions?

This program determines whether the string the user has input is a palindrome or not.
import acm.program.ConsoleProgram;
public class PurePalindrome extends ConsoleProgram {
public void run() {
String originalString;
String reversedString;
boolean isPalindrome;
originalString = readLine("? ");
reversedString = reverseString(originalString);
isPalindrome = checkPalindrome(originalString, reversedString);
println("The word you entered " + determineWord(isPalindrome)
+ " a palindrome. " + originalString + " reversed is: "
+ reversedString + ".");
}
private boolean checkPalindrome(String word, String revWord) {
if (revWord.equals(word)) {
return true;
} else {
return false;
}
}
private String reverseString(String wordToReverse) {
String reversedWord = "";
for (int i = 0; i < wordToReverse.length(); i++) {
reversedWord = wordToReverse.charAt(i) + reversedWord;
}
return reversedWord;
}
private String determineWord(boolean palindrome) {
if (palindrome) {
return "is";
} else {
return "is not";
}
}
}
Would all these methods be considered pure functions? If not, why not? I'm having a bit of trouble determining whether a method is a pure function or not.
A method is a pure function if its returned value depends exclusively on its arguments, and not on anything else, and if it doesn't have any side effect.
So the last three methods are pure functions, whereas the first one is not: it doesn't return anything, depends on the user input, and has the side effect of printing on the screen.
Side note:
if (revWord.equals(word)) {
return true;
} else {
return false;
}
should be replaced by
return revWord.equals(word);

Chat Bot, last part

Just one last part remaining in the ChatBot. I need to figure out a way to modify the chatbot class so
that it occasionally (say, 30% of the time) returns a randomly-­‐generated standard reply to user input one of at least five possible replies, like “LOL”, “OMG”, “You don’t say”, “Really?”, or “I see”.
Edit: Applied recommended changes:
import java.util.Random;
import java.util.Scanner;
public class ChatBot
{
private int responseCount = 0;
public String getResponse(String value)
{
String X = longestWord(value);
this.responseCount++;
if (responseCount == 10)
{
return "Sorry, but our time is up. I can't talk with you any longer.";
}
if (value.contains("you"))
{
return "I'm not important. Let's talk about you instead.";
}
else if (X.length() <= 3)
{
return "Maybe we should move on. Is there anything else you would like to talk about?";
}
else if (X.length() == 4)
{
return "Tell me more about " + X;
}
else if (X.length() == 5)
{
return "Why do you think " + X + " is important?";
}
else if (X.length() <=9)
{
return "Now we are getting somewhere. How does " + X + " affect you the most?";
}
return getRandomResponse();
}
public String longestWord(String value){
Scanner input = new Scanner (value);
String longest = new String();
longest = "";
while (input.hasNext())
{
String temp = input.next();
if(temp.length() > longest.length())
{
longest = temp;
}
}
return longest;
}
private String getRandomResponse()
{
String [] responses = {"OMG", "LOL", "You don't say", "Really?", "I See"};
return responses [(int)(Math.random() * responses.length)];
}
}
The problem is, it keeps returning the same response, instead of one of the five responses given. Any help would me much appreciated, thank you!
Edit:It's now giving only the random responses, and overriding every other response in the getResponse() method.
Given your logic, your getRandomResponse method should always return "OMG". This is because on the first run of the loop in that method, counter = 1. Thus the first if statement will run and will return "OMG" exitting the method. A nicer equivalent might putting all teh responses into an array and returning a random value from it, rather than doing somehting strange with iteration:
String[] responses = {"OMG", "LOL", "You don't say", "Really?", "I See"};
return responses[(int)(Math.random() * responses.length)];
In getRandomResponse, you make a random number generator using Random(), but you never use it. Then in your for loop, you execute your decision-making tree but use a variable counter that always begins at 0. Then on the first time through your loop, the first if statement will execute because 0 < 5, so "OMG" is returned.
Edit: I just noticed something else that is not going to work in your code:
Random randomNumber = new Random();
for (int counter =0; counter<10; counter++)
{
counter = randomNumber.nextInt();
You're trying to use counter to do two different things: you are trying to run this loop 10 times, but you're also using it to store random values.

Java: How to get the caller function name

To fix a test case I need to identify whether the function is called from a particular caller function. I can't afford to add a boolean parameter because it would break the interfaces defined. How to go about this?
This is what I want to achieve. Here I can't change the parameters of operation() as it is an interface implementation.
operation()
{
if not called from performancetest() method
do expensive bookkeeping operation
...
}
You could try
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
String methodName = e.getMethodName();
Here is code that is more modern (available in Java 9+) and better performing.
private static String getCallerMethodName()
{
return StackWalker.
getInstance().
walk(stream -> stream.skip(1).findFirst().get()).
getMethodName();
}
Change skip(1) to a larger number as needed to go higher on the stack.
This performs better than Thread.currentThread().getStackTrace() because it does not walk the entire stack and allocate all of the stack frames. It only walks two frames on the stack.
This method can be adapted to return StackWalker.StackFrame that has a lot of information about the method.
Here's a function I wrote to Log the function name of the function that calls it. It runs up the stack trace until it finds a function named logIt, then displays the next name. It's a dirty hack, so don't do it unless you're using it to debug.
private static void logIt() {
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
boolean logged = false;
boolean foundMe = false;
for(int i=0; i<stacktrace.length; i++) {
StackTraceElement e = stacktrace[i];
String methodName = e.getMethodName();
if (foundMe) {
if (!methodName.startsWith("access$")) {
Log.i(TAG, String.format(Locale.US, "%s.%s", e.getClassName(), methodName));
logged = true;
break;
}
} else {
if (methodName.equals("logIt")) {
foundMe = true;
}
}
}
if (!logged)
Log.e(TAG, "unlogged call");
}
I tweaked the code that is being discussed here and customized it to get the invoking method. What the code does here is to iterate over the stack trace elements and as soon as it finds the name of the method being invoked, it gets the name of the previous method, which in turn will be the method that is invoking this method.
private String method() {
String methodName=null;
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
for (int i = 0; i < stacktrace.length; i++) {
if(stacktrace[i].getMethodName().equals("method")) {
methodName = stacktrace[i+1].getMethodName();
break;
}
}
return methodName;
}
Another sample for android usage:
//package your.package.name;
import android.util.Log;
/*
File name: MyDebugLog.java
*/
public class MyDebugLog {
private static final int index = 4; // <== Index in call stack array
private static final String methodName = "Log"; // <== Name of method for public call
private static String getCallerName() {
String caller = "NONE";
final StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
for (int i = 0; i < stacktrace.length; i++) {
Log.e("Method ", "[" + i + "]" + stacktrace[i].getMethodName());
}
if (stacktrace.length >= index){
caller = stacktrace[index].getMethodName();
}
return caller;
}
private static String getTag() {
String tag = "NONE";
final StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
for (int i = 0; i < stacktrace.length; i++) {
Log.e("Method ", "[" + i + "]" + stacktrace[i].getMethodName());
if (stacktrace[i].getMethodName().equals(methodName)) {
tag = "("+stacktrace[i + 1].getFileName() + ":" + stacktrace[i + 1].getLineNumber()+")";
return tag;
}
}
return tag;
}
public static void Log(String message){
Log.v(getTag(), getCallerName() + " " + message);
}
}
Usage:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_main);
MyDebugLog.Log("XXXXX");
}
Output:
V/(MainActivity.java:117): onCreate XXXXX
Sample of arrays:
getTag Sample of stacktace array:
Method: [0]getThreadStackTrace
Method: [1]getStackTrace
Method: [2]getTag
Method: [3]Log <== Method for external call
...
getName Sample of stacktace array:
Method: [0]getThreadStackTrace
Method: [1]getStackTrace
Method: [2]getCallerName
Method: [3]Log
Method: [4]onCreate <== Our external method
Method: [5]performCreate
...
I sometimes want to make some outputs to the logcat. So I wrote a tiny class with some testing-methods:
public class Common {
// can be used as test-flag anywhere in the app (set to false, when release the app)
public static boolean b_TEST_MODE = true;
public static void echo(String message) {
if (b_TEST_MODE) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
// subtring(25) is to cut off app-name from output
System.out.println(">>> " + stackTraceElements[3].toString().substring(25) + ": " + message);
}
}
}
now you can call it from anywhere in the app to get some infos:
String sSQLQuery = "SELECT * FROM database WHERE id=23";
Common.echo(sSQLQuery);
The logcat prints out:
>>> MainActivity.onCreate(MainActivity.java:46): SELECT * FROM dateabase WHERE id=23
I have no idea why but in my shop the develop system differs from the test and production environments shifting position in the stack. I was forced to loop through the stack to find and get the calling method from the next element in the stack trace. A little clunkier but so far has been consistently returning the desired method. I use this as part of my error handling to identify where an exception was caught.
List<String> list = new ArrayList<String>();
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (int i = 0; i < Thread.currentThread().getStackTrace().length; i++) {
System.out.println("Stack: "
+ i
+ " Class: "
+ elements[i].getClassName()
+ " Method: "
+ elements[i].getMethodName());
if (elements[i].getMethodName().equals("<init>")) {
list.add(elements[i + 1].getClassName());
list.add(elements[i + 1].getMethodName());
break;
} // if
} // for

Categories