Looping the wrong way? - java

The assignment for my class asks me to create a program that tells a supermarket which customer, on a daily basis, has spent the most money in the store. The program must find this customer and display their name.
Goals of assignment - To work with multiple classes, work with ArrayLists and apply the knowledge gained.
My question:
How should I loop my two output statements in my main class? Is that right in my main method? I need it to loop until the sentinel is used.
How is this going to affect my sentinel?
What type of questions should I be asking myself when dealing with loops? I'd like to think I'm overthinking this portion.
I really want to understand what I am doing here, so any help in the right direction would be appreciated! Thanks, in advance, for taking the time to help me out!
import java.util.Scanner;
public class main {
public static void main(String[] args) {
System.out.println("* * * * * THE SUPERMARKET * * * * *");
System.out.println(" Written by Nate Irwin");
System.out.println();
double finalTotal = -1;
String anAccountName;
Scanner input = new Scanner(System.in);
Store store = new Store();
do {
System.out.println("Enter the customer name: ");
if(input.hasNextLine()){
anAccountName = input.nextLine();
System.out.println("Enter customer total price, hit 0 to QUIT: ");
finalTotal = input.nextDouble();
store.addAccount(anAccountName, finalTotal);
System.out.println();
}
} while (finalTotal != 0);
System.out.println(store.getHighestCustomerTotal() + " has spent the most with us today!");
}
}
Store class:
import java.util.ArrayList;
public class Store {
// Creates an ArrayList.
private ArrayList<CustomerAccount> accounts = new ArrayList<CustomerAccount>();
//
public void addAccount(String anAccountName, double finalTotal) {
accounts.add(new CustomerAccount(anAccountName, finalTotal));
}
// Gets the HIGHEST customer total.
public String getHighestCustomerTotal() {
CustomerAccount highest = accounts.get(0);
for (int i = 1; i < accounts.size(); i++) {
if (accounts.get(i).getTotal() > highest.getTotal())
{
highest = accounts.get(i);
}
}
return highest.getAccountName();
}
}
CustomerAccount class:
public class CustomerAccount {
// Variables defined to this class.
private String accountName;
private double total;
// Constructor.
public CustomerAccount(String anAccountName, double finalTotal) {
accountName = anAccountName;
total = finalTotal;
}
// Gets total from each customer.
public double getTotal() {
return total;
}
// Gets a customer's name.
public String getAccountName() {
return accountName;
}
}

I think your approach is fine, it gets the job done.
I'm not too sure what you're asking by saying how should you loop the two output statements, followed by if it should be in the main method. From what I understand, and by looking at your code, running this input loop is perfectly fine from the main class. The do-while is fine although I'd move the first 'introductory' output outside the loop so you don't see it every time the loop reiterates.
Also, I notice you're not actually calling/instantiating the Store class in your main method, there's no data being added to the Store class for when it iterates through the accounts ArrayList.
As far as the answer that stated a more "modern" approach, I think the for loop you used is fine. I think the person was referring to the for-each loop. It doesn't really matter how you loop through it with the little amount of data you have.
There's some error in the logic for that loop. The getHighestCustomerTotal() is referencing an empty accounts ArrayList. You declared an ArrayList within the Store class and tried to loop through it but it's empty unless you called the addAccount() method from your main method at some point, so you'd need some error checking on that.

Your loop in main:
Doesn't really use the data you type in... One would expect this data to be used to create CustomerAccount instances
Has a completely unnecessary while(Condition) test at the end. This kind of loop is normally done with a While True and some test in the loop breaks out of the loop.
In getHighestCustomerTotal()
you can use a more "modern" form of the for() where you iterate elements of the list directly instead of iterating the index.

Related

How to update a variable in a java object array

I am creating a member application using the scanner to input data into an array called memberList. The data is going into an object and then the object is being stored in the array. I am using string and integers in the object.
I am writing a method to change one of the string variables in the array from yes to no, it is whether the member has paid their fees or not.
I am trying to enter the members name by calling my getName method and using the setFeePaid to change the String to "yes" from "no".
There is something wrong with the loop, as it only lets me change the first member in the array. Could anyone help please.
public static void payMemberYearlyFees(){
for (int i=0; i < memberCount; i++) {
Member member = memberList[i];
System.out.println("Enter the name of the member who has to pay their fee:");
if (input.nextLine().equals(member.getName())) {
member.setFeePaid("yes");
System.out.println();
System.out.println(member.getName() +" has paid their membership fee.\n");
System.out.println("********Returning to Main Menu.********\n");
}
else{
System.out.println();
break;
}
}
}
In your for loop, you are first taking a member (the first one in the list) and then asking the user to input a name. It then checks if the input name is the same as the member that you've taken (remember, only the first of the list). If you input any other name, the if statement fails and you go to the else block, which stops the loop.
This should work:
public static void payMemberYearlyFees(){
System.out.println("Enter the name of the member who has to pay their fee:");
String inputName = input.nextLine();
for (int i=0; i < memberCount; i++) {
Member member = memberList[i];
if (inputName.equals(member.getName())) {
member.setFeePaid("yes");
System.out.println();
System.out.println(member.getName() +" has paid their membership fee.\n");
System.out.println("********Returning to Main Menu.********\n");
break;
}
}
}
Then call this method as many times as you want. If you want your code to be a bit cleaner, you can do the for loop this way:
for (Member member : memberList){
if (inputName.equals(member.getName())) {
member.setFeePaid("yes");
System.out.println();
System.out.println(member.getName() +" has paid their membership fee.\n");
System.out.println("********Returning to Main Menu.********\n");
break;
}
}
That way you just take the members of your list one by one without having to deal with the i variable and manually pick the i member of the list.

How to properly display contents of a shared array within objects

I'm having a difficult time figuring how to display the shared personArray with the appropriate course object. For example, I need to display a list of a course and the people that are in that course, and again for the next course. I feel that there's something wrong with my nested for loop or the personCount variable because not every course has the same amount of people so how do I deal with this?
Hopefully you all can get a clear picture of the stripped down code below.
Note* I must use aggregation and toStrings, and not allowed to use lists, arraylists, or scanner.
Thanks!
public class School {
private static Course[] courseArray = new Course[5];
public static void printList(){
String print = "";
for (int x = 0; x < courseCount; x++) {
print += courseArray[x].getCourseName() + "\n";
for (int y = 0; y < personCount; y++){
print += courseArray[y].personArray[y].getPersonName()+ "\n";
//^ I thought I could use the 1st forloop index to stay in the 1 course and print out all the people for that course(like the hardcode example below) but I get a nullpointer
}
}
JOptionPane.showMessageDialog(null,print);
/*
If I hardcode the print String like below I get the correct output.
So I know my objects are being stored properly, but I can't figure out how to get the correct display with a loop
print += courseArray[0].personArray[0].getPersonName(); //tim (bio)
print += courseArray[0].peopleArray[1].getPersonName(); //bob (bio)
print += courseArray[1].peopleArray[2].getPersonName(); //john (art)
*/
}
}
------------------------
public class Course {
private Person[] personArray = new Person[50];
//constructor for course
// get/set courseName methods
public String toString(){
// not sure how to use this the right way
}
}
-----------------------------------
public class Person extends Course {
//constructor for person
// get/set personName methods
public String toString(){
return getPersonName();
}
}
Make sure that all 50 of the people in your personArray are initialized first; check to see if they are by printing out the entire array like so (you will need to import java.util.Arrays):
System.out.println(Arrays.toString(course[x].personArray));
If that gives back any "null" values then you know that not every single Person in the PersonArray was initialized first.
You should change courseCount to courseArray.length and personCount to courseArray.getPersonArraySize() and implement getPersonArraySize() in Course class to return length of personArray.
replace your loops with these below..
for (Course c : courseArray) {
print += c.getCourseName() + "\n";
for (Person p : c.personArray){
print += p.getPersonName()+ "\n";
}
}

Understanding ArrayLists and how they are used for a TUI

Beforehand: This is a homework assignment so I need answers with explanations.
I am a first year student and my teacher is extremely vague while teaching so
I need some help understanding how to use the ArrayList in his instructions.
**I just need help understanding how this all works. I'm writing the code but I don't know how any of it works.
The Textual User Interface is supposed to be written in another class that I haven't done yet.**
My instructions were:
GradeManager Class 
Start by developing a class to describe a GradeManager. Because this exercise is far more about writing an interactive application, we'll keep this class SIMPLE. Our GradeManager will just keep track of an ArrayList of scores and define the following methods:
A single constructor that accepts no parameters, but sets up the ArrayList so that it is 
capable of holding some scores 
A method called addScore that will accept a score and add it to the ArrayList 
A method called getAverage that will return the average of all scores in the ArrayList
GradeTUI Class 
This class will keep track of a GradeManager object as an instance variable.  You will need to write a 
constructor that accepts the GradeManager object that it will be using.  
 
This class will also contain a method named run.  This method will give the user the ability to either (1) 
enter a score to be stored (in the GradeManager object) or (2) display the average of all scores entered 
so far.  Allow the user to continue this program by choosing one of these options until they are finished. 
 
Driver Class 
Once you are satisfied that these classes are defined and working properly, develop a driver class 
containing a main method that will create an instance of GradeManager, pass this object to the 
GradeTUI constructor, and then use the GradeTUI object to call run. 
This is what I wrote:
public class GradeManager {
private ArrayList<Integer> gradeList;
public GradeManager() {
ArrayList<Integer> gradeList = new ArrayList<Integer>();
this.gradeList = gradeList;
}
public void addScore(int score) {
this.gradeList.add(score);
}
public double getAverage(ArrayList<Integer> gradeList) {
Integer aScore = 0;
if (!gradeList.isEmpty()) {
for (Integer grade : gradeList) {
aScore += grade;
}
return aScore.doubleValue() / gradeList.size();
}
return aScore;
}
}
First: I think the getAverage Method should use the internal ArrayList instead of a parameter.
Otherwise you don't have any read access to that lists contents.
You can use your GradeManager in the following way:
GradeManager manager = new GradeManager();
while(condition) {
int score = readScoreFromInput();
manager.addScore(score);
}
double averageScore = manager.getAverage();
print(averageScore);
So you get the average of all the scores you have just input.
The concrete implementation of the loop (and the exit condition) is up to you - it could be a predefined number of iterations or a special input like -1 for example.

Utilizing Comparable for 2 Sort Criteria when Sorting an Array of Objects

I've been working at this for a couple hours now and I feel (I hope) I'm right on the verge of figuring it out. This program reads in a bunch of values from an external file and places them in an array of objects which seems to be working just fine.
The Objects properties are:
Bank Account #
Customer Name
Bank Account Balance
1. I can output them in order of Account # (That's how their read in from the file, no sorting is necessary)
2. I've setup a method from implementing Comparable to sort by Bank Account Balance and it's working fine.
3. I need a second sort method, to sort by Customer Name.
- The problem I'm having with this is based on the research I've done and what I've tried I've come to the conclusion that the only way to make this work will be to build my own Comparable Objects (sorry if my terminology is skewed.) I've attempted this as well multiple times with both Java Doc and some similar questions on SE.
When all is said and done I'm going to throw some Listeners into my checkbox group to allow the user to toggle the different sort methods.
Here's the chunks i'm working on:
public class bankAccounts implements Comparable<bankAccounts> {
/* PRIVATE FIELDS HERE, FOLLOWED BY TYPICAL GET AND SET METHODS */
/*SORTS BY ACCOUNT BALANCE WORKING GREAT*/
public int compareTo(bankAccounts b) {
if (accountBalance < b.accountBalance)
{
return -1;
}
if (accountBalance > b.accountBalance) {
return 1;
}
return 0;
}
/* BEGIN SNIPPET OF MAIN CLASS */
/*METHOD I CALL FROM MAIN CLASS, SORTS BY BALANCE ^^ AS SEEN ABOVE */
Arrays.sort(retrievedAccounts);
for (int i=0; i<retrievedAccounts.length; i++) {
String resultFull = Integer.toString(retrievedAccounts[i].getAccountNumber()) + retrievedAccounts[i].getAccountLastName() + Double.toString(retrievedAccounts[i].getAccountBalance());
box.append(resultFull + "\n");
}
/* NORMAL METHOD WHICH OUTPUTS IN ORDER OF ACCOUNT NUMBER, NO SORTING HAPPENING HERE */
for(int x = 0; x < retrievedAccounts.length; ++x)
{
String resultFull=Integer.toString(retrievedAccounts[x].getAccountNumber()) + retrievedAccounts[x].getAccountLastName() + Double.toString(retrievedAccounts[x].getAccountBalance());
box.append("\n\n\n" + resultFull + "\n\n");
}
I'm hoping someone will have some insight towards a next step which might allow me to finish this up. If you have suggestions to take this a completely different direction I'm open to that as well.
This is an idea haven't tested.
Create a another private method to store compareType
public class bankAccounts implements Comparable<bankAccounts> {
private int compareType = 0; // 0 - compare by balance 1-compare by name
In your compare method
public int compareTo(bankAccounts b) {
if(this.compareType == 0){
if (accountBalance < b.accountBalance)
{
return -1;
}
if (accountBalance > b.accountBalance) {
return 1;
}
return 0;
}else{
return customerName.compareTo(b.customerName)
}
Use an implementation of Comparator<bankAccounts> that compares the names of your objects and pass that into the Arrays.sort() method.
Use an anonymous class like this:
Arrays.sort(retrievedAccounts, new Comparator<bankAccounts>() {
public int compare(bankAccounts a, bankAccounts b) {
return a.getName().compareTo(b.getName());
}
});
This code assumes you have a getter method on bankAccounts for customer name called getName()
You would do well to follow java naming conventions:
class names start with a capital letter
class names are singular, not plurals

Can mutator methods be applied to objects in an ArrayList?

I'm having some trouble with my java program and I'm not sure if this is the problem but would calling a mutator method on an object inside an araylist work as intended?
For example
public class Account
{
private int balance = 0;
public Account(){}
public void setAmount(int amt)
{
balance = amt;
}
}
public class Bank
{
ArrayList<Account> accounts = new ArrayList<Account>();
public staic void main(String[] args)
{
accounts.add(new Account());
accounts.add(new Account());
accounts.add(new Account());
accounts.get(0).setAmount(50);
}
}
Would this work as intended or is there something that would cause this not to?
Is the problem but would calling a mutator method on an object inside an ArrayList work as intended?
Yes, if your intention is to update the first account in the list. Keep in mind that the array list doesn't store objects, but references to objects. Mutating one of the objects won't change the reference stored in the list.
The first account will be updated, and when referencing accounts.get(0) again it will show the updated balance.
Here's an ideone.com demo demonstrating it. (I've just fixed a few minor typos such as adding static in front of the accounts declaration.)
for (int i = 0; i < accounts.size(); i++)
System.out.println("Balance of account " + i + ": " +
accounts.get(i).balance);
yields
Balance of account 0: 50
Balance of account 1: 0
Balance of account 2: 0
which hopefully is what you would expect.
Yes, that should work as intended. It is no different than:
Account firstAccount = accounts.get(0);
firstAccount.setAmount(50);
Remember, ArrayList's get() method returns the actual object stored in the ArrayList, not a copy of it.

Categories