I don't wish to leave a user stranded by returning nothing. Normally I can rectify this problem using a simple if else statement but since it's nested inside a for loop I don't get very good result. Below is my code for returning students attached to a module:
System.out.print("Search for a student: ");
scan = new Scanner(System.in);
String searchStudent = scan.nextLine().trim();
for (Student student : students) {
if (searchStudent.equalsIgnoreCase(student.getName())) {
Iterator it = modules.iterator();
Boolean found = false;
while (it.hasNext() && !found) {
Module module = (Module) it.next();
if (module.getStudents().contains(student)) {
System.out.printf("%s ", module.getName());
found = true;
}
}
} else {
System.out.println("Sorry. " + searchStudent + " does not exist in the database");
}
}
The output:
Search for a student: jane
UFCE3 UFCE1 Sorry. jane does not exist in the database
Sorry. jane does not exist in the database
Sorry. jane does not exist in the database
Sorry. jane does not exist in the database
Clearly in this example, Jane does exist in the database and she is enrolled on UFCE3 and UFCE1.
Since the if statement is nested inside the for loop I wouldn't expect anything less than getting an inaccurate output as the for loop will continue to loop until all elements in the student array have been passed. Any advice?
You can add a simple sentinel value (boolean flag) to your while statement. You start the value off as false, and then change it to true when a record is found.
Boolean found = false;
while (it.hasNext() && !found) {
Module module = (Module) it.next();
if (module.getStudents().contains(student)) {
System.out.printf("%s ", module.getName());
found = true;
}
Or you could use a "break" statement to terminate the loop.
while (it.hasNext() ) {
Module module = (Module) it.next();
if (module.getStudents().contains(student)) {
System.out.printf("%s ", module.getName());
break;
}
extract your for loop into a method, returning the modules you are interested in.
then call that method. check if you get any useful result and print it or print your excuse otherwise.
This is known as seperation of concerns. An entity should do exactly one thig. your for loop does at least three:
searching for students
searching for modules
printing results
Related
So I am trying to make this swing GUI that searches a list of books and then displays the book in a JTextArea. Here is my actionPerformed Method
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Search Books")){
String bookName = JOptionPane.showInputDialog(this, "Enter books to search"); // prompts user to enter book title
if (bookName == null){
sArea.append("Enter a Book");
}else{
for (Book b: ban.getListOfBooks()){ //going through list of books to find matching title
if (bookName.equals(b.getTitle())){ // appends string if it is equal to one of the book names
sArea.append(bookName);
}else{
sArea.append("Book not found");
}
}
}
}else{
...
So my problem is for the for each loop. Naturally it will print "Book not found" for every element in the list that is not equal. So if i have ten books, and i enter the name of the first one, it will print that and then "Book not found" nine times. How could i reformat this to only print out one thing?
You can use a boolean found flag and then check if the book was found at the end of the loop
}else{
boolean found = false;
for (Book b: ban.getListOfBooks()){ //going through list of books to find matching title
if (bookName.equals(b.getTitle())){ // appends string if it is equal to one of the book names
sArea.append(bookName);
found = true;
}else{
}
}
if (!found) sArea.append("Book not found");
}
If you want to still continue using foreach loop you can extract that part to a function, return the book name when it matches but if any book does not matche return "Not found" instead of appending every iterarion
Like this:
public String searchBook(List<Book> books, bookName ){
for (Book b: books)){ //going through list of books to find matching title
if (bookName.equals(b.getTitle())){
return b.getTitle();
}
}
return "Book not found"; }
So you just calling this function instead of your foreach loop like this:
sArea.append(this.searchBook(ban.getListOfBooks() , bookName))
It´s cleaner.
Finally I'm not sure if is correct to use append method If you just want to put the result everytime the user search.
Also if you have a List you can use indexOf or contains methods to know if a element exists in the list, it´s cleaner.
This can help you more : https://www.baeldung.com/find-list-element-java
I have been working on an exercise summarized as follows:
Write a program to store details of food items in a single array by using inheritance and polymorphism. Example, details of pizzas(item number, size, base), softdrinks(...)...
I have modeled everything, created my base class and derived classes.
Everything works fine except for one thing: when the user chooses to delete an item, I am supposed to output the string "Not found" if the item number is not found. My array list has each food item object (the subclasses) as elements. Here is my code for deleting an item from the array:
System.out.println("Enter the menu item number");
String num = input.next();
for(int j=0; j<menuItems.size();j++) //menuItems is my arraylist
{ if((menuItems.get(j).getItemNumber().equals(num))) //getItemNumber is a method in the derived class
menuItems.remove(j);
}
System.out.println("Done");
break; //for the switch statement
I am supposed to output "Not found" instead of "Done" if the item is not found in the array list. My initial attempt was as follows:
if(!menuItems.get(j).getItemNumber().contains(num))
System.out.println("Not found");
else
//the code above
This did not work because it is within the for-loop and the if-statement will check the array list even after the item has been removed. So, it will still evaluate to true.
Could someone please help me with this?
UPDATE:
I solved the problem as follows
int found=0; // element not found found =0 else 1
for(j=0; j<menuItems.size();j++)
{
if((menuItems.get(j).getItemNumber().equals(num)))
{
menuItems.remove(j);
System.out.println("Done");
found+=1;
}
}
if (found ==0)
{
System.out.println("Not found");
}
break; //for the switch statement
You could do it something like this
boolean found = false;
for(int j=0; j<menuItems.size();j++){
if((menuItems.get(j).getItemNumber().equals(num))){
menuItems.remove(j);
found = true;
break;
}
}
if(found){
System.out.println("Done");
} else {
System.out.println("Not found");
}
If you didn't manage to remove the item, then it wasn't there.
If you find and remove the element, break the switch (plates is just a random label):
plates: switch (smth) { //whatever you use here (not provided in the post)
...
for(int j=0; j<menuItems.size();j++) { //menuItems is my arraylist
if(menuItems.get(j).getItemNumber().equals(num)) { //getItemNumber is a method in the derived class
menuItems.remove(j);
System.out.println("Done!");
break plates; //for the switch statement
}
}
System.out.println("Not found!");
break; //for the switch statement (that you did not provide)
...
} //end of switch (if num is found, you continue from here)
I think maybe you can look at HashMap, then you can write your code like:
HashMap<String, Food> = new Hashmap<>();
String num = input.next();
final Food temp = MyMap.get(num)
if(temp == null)
{
//not found
}
else
{
//found
}
I keep getting those two errors and cannot seem to understand why. These errors suddenly appeared in other methods as well, further down the same class. I have tried to find double declarations but could not find any. Also, I have paid attention to to write a method within another method. Help will be much appreciated! :)
public void connectStudentToCourse(long studentID, String courseID)
{
if (studentID >= 0 && courseID != null)
{
boolean flag = false;
Course tempCourse = new Course(courseID);
tempCourse = sData.getCourses().get( sData.getCourses().indexOf(courseID) );
Student stu = new Student(studentID);
stu = sData.getStudents().get( sData.getStudents().indexOf(studentID) );
if (tempCourse != null && stu != null)
{
if (tempCourse.getPreCourses() != null)
for (Course c : tempCourse.getPreCourses())
{
for (Course passed : stu.getCompletedCourses())
{
if (passed.equals(c))
flag = true;
}
if (flag == false)
{
MyFileLogWriter.writeToLogFile("Failed to connect Student "+studentID+" to course "+courseID+"\n", false);
return;
}
else flag = false;
}
if (tempCourse.addStudent(stu))
{
if (stu.addCourse(tempCourse))
{
MyFileLogWriter.writeToLogFile("Student "+stu.getId()+" connected to course "+tempCourse.getCourseID()+" successfully\n", false);
return;
}
else //RollBack
tempCourse.removeStudent(stu);
}
}
}
MyFileLogWriter.writeToLogFile("Failed to connect Student "+studentID+" to course "+courseID+"\n", false);
}
I think you have to add opening bracket at 2nd if statement and close it, may it solve your problem...
Only when I cut all the problematic methods from the class, I noticed a missing "}" in the method above them. Eclipse did not show this missing brace, only until I removed all the rest of the code, so I could not tell where was it missing until the removal. I added the missing brace and re-pasted the rest of the problematic methods back into the class, and all errors have vanished! Solution was much more simple than I expected it to be. #PM77-1, #Jon Skeet and #Andreas - you are all LEGENDS!! Thank you so much!! :)
I am trying to search through a Java LinkedList that uses a custom object called Name. I need to search on first name (My compareTo method in Name already compares last names because I need to use it to sort by last name). Name has an observer method called getFirstName().
I am not having any success in accessing first name from my LinkedList. This is what I want to do but this (obviously) doesn't work.
if (iterator.next().getFirstName().equals(inputSearch))
Can someone point me in the right direction?
This is the full method I am currently trying to write:
// Creating a method to search for a first name
static void searchName()
{
Scanner inData = new Scanner(System.in);
// Label to request input from user
System.out.println("Enter the first name that you would like to search for:");
// Setting variable to capture input
String inputSearch = inData.next();
// Creating an iterator to search through the list
iterator = list.iterator();
// While loop to search each entry
while (iterator.hasNext())
{
if (iterator.next().getFirstName().equals(inputSearch))
{
System.out.println("MATCH FOUND: " + iterator.next());
}
}
}
You're calling iterator.next() twice. The second time will advance past the item you want. Instead, save the return value from the first call to iterator.next() and use that.
while (iterator.hasNext())
{
Name item = (Name) iterator.next();
if (item.getFirstName().equals(inputSearch))
{
System.out.println("MATCH FOUND: " + item);
}
}
or, more idiomatically
for (Name item : list)
{
if (item.getFirstName().equals...
}
while (iterator.hasNext()) {
if (iterator.next().getFirstName().equals(inputSearch)) { //iterator.next()
System.out.println("MATCH FOUND: " + iterator.next()); //iterator.next()
}
}
Since you are calling next() twice, while printing it would be next object.
try storing whatever iterator.next() returns in its corresponding type and use it to compare and print if succeed.
ex:
while(iterator.hasNext(){
Name name=iterator.next();
if(name.getFirstName().equals(inputSearch)){
System.out.println("Match Found"+name);
}
}
This is what I see wrong. Not aware of anything else.
I currently have 3 classes, a main class containing a GUI, in which i'm calling this method, a customer class containing the data, and a customerList class which gathers the data from the customer class, puts it into an array list, and also contains the search arraylist method.
I'm trying to implement a search method which can be called from my main class on an action event handler. I'm having a few problems though.
Whenever I run the method, the " System.out.println(customer.returnFamilyName());" line always displays the first familyname in my arraylist.
Don't hesitate to ask for more information, I'm not sure how well i've explained this.
Here is my method:
public void searchCustomer(String familyName) {
int index = 0;
boolean found = false;
customer customer;
while(index < CustomerList.size() && !found) {
customer = CustomerList.get(index);
if(customer.returnFamilyName().equalsIgnoreCase(familyName)) {
found = true;
break;
}
if(found == true) {
;
}
System.out.println(customer.returnFamilyName());
index++;
return;
}
}
It's not clear from your question what the intended behaivor actually is. Besides that, what is this ?
if (found == true);
Presumably you meant :
if (found) {
System.out.println...
}
But what if the same last name occurs twice in your list? Also why aren't using a Map instead of a List? Lookup will go from being O(n) to O(1)
Drop the ; in if (found == true); because that reads as: if this condition is true, do notihng and use braces always:
if (found == true) {
System.out.println(customer.returnFamilyName());
}
Also, include the increment inside the while loop, otherwise you are not really iterating anything.
This code seems to work because your first element happens to coincide with the searched element, try with a different one and you'll end up in a infinite loop.
Try with a version like this:
public void searchCustomer( String familyName ) {
for ( customer current : CustomerList ) {
if ( current.returnFamilyName().equalsIgnoreCase( familyName )) {
System.out.println( current.returnFamilyName() );
break;
}
}
}
Some additional remarks:
In Java clases should start with uppercase, so the class name should be declared as Customer instead of customer and variables start with lowercase, hence CustomerList should be customerList. Methods may avoid the return part and be named with a get
Also, search methods should better return the found value instead of printing it, so your final version could look like this:
public Customer searchCustomer( String familyName ) {
for ( Customer current : customerList ) {
if ( current.getFamilyName().equalsIgnoreCase( familyName ) ) {
return current;
}
}
return null;
}
You never increment index.
The code should be:
public void searchCustomer(String familyName) {
for (customer customer : CustomerList) {
if (customer.returnFamilyName().equalsIgnoreCase(familyName)) {
System.out.println(customer.returnFamilyName());
break;
}
}
}
Also, the 'customer' class should be called 'Customer' as class names should start with a capital, 'returnFamilyName' should be 'getFamilyName' as accessor methods by convention are named 'get' + the field name and 'CustomerList' should be 'customerList' as field names are supposed to start with a lowercase letter.
I would suggest try this:
System.out.println(customer.returnFamilyName());
index++;
if(found == true) { return;}
Don't forget to increment the while loop or it has the potential to run indefinitely.
You can elect to use what is known as an "enhanced for-loop", which allows you to eschew the need to increment values over CustomerList entirely. You have an object customer, so we can use that as follows:
for (customer cus: CustomerList) {
if(cus.returnFamilyName().equalsIgnoreCase(familyName)) {
System.out.println(cus.returnFamilyName());
return;
}
}
If you elect to stick with your original code (which is fine), then observe the changes in your code below.
while(index < CustomerList.size()) {
customer = CustomerList.get(index);
if (customer.returnFamilyName().equalsIgnoreCase(familyName)) {
System.out.println(customer.returnFamilyName());
break;
} else {
index++;
}
}