Dynamic object creation from user input - java

I have a two classes, Student containing some basic info, and Course, containing some basic info and an ArrayList of Student objects. I want to dynamically (from user input) populate new instances of both classes. For example, user is prompted for course name, teacher and asked if they want to add students to the course. When done with the course and all the students' information, the loop goes back to asking to add another course.
What I do is, create a Course object and then add students. I manage Student objects by just creating them after collecting user unput with courseInstance.addStudent(new Student(name, age, phone)). It all works well for one course, but how do I manage multiple Course object, dynamically created from input?
Here is a code example:
public static void main(String[] args) {
// TODO code application logic here
Course course = new Course();
Scanner in = new Scanner(System.in);
String ans;
String name;
String gender;
String phone;
int age;
System.out.print("Enter course name: ");
ans = in.nextLine();
course.setName(ans);
System.out.print("Enter teacher name: ");
ans = in.nextLine();
course.setTeacher(ans);
while (true) {
System.out.print("Add student (yes or exit): ");
ans = in.nextLine();
if (ans.equals("exit")) {
break;
}
System.out.print("Enter name: ");
name = in.nextLine();
System.out.print("Enter age: ");
age = in.nextInt();
in.nextLine();
System.out.print("Enter gender: ");
gender = in.nextLine();
System.out.print("Enter phone number: ");
phone = in.nextLine();
course.addStudent(new Student(age, name, phone, gender));
}
in.close();
System.out.print(course);
}

How about having a List of Course objects, and asking (in your while(true) loop) what course each student is registering to?

Create a List which you can populate with courses like this:
ArrayList<Course> courses = new ArrayList<Course>();
When a student enters a name from the course, check if the course exists in the array. If not, add it to the array, else get it from the array and add the student.

Since the Name seems to be the primary attribute to identify a course, you should override the equals(Object o) method of course so it compares the two names of the courses.
public boolean equals(Object o){
return this.getName().equals((Course)o.getName());
}
Then you can simply have a List to store your courses and ask the list if it contains a specific course or not. If not you can add it to the list, otherwise you can add students or teachers to the already existing course.
EDIT: It should be getName() on both courses

Related

Access elements of arraylist of arraylist of arraylist?

I am new to Java, and I am currently using BlueJ for a project. I am having troubles accessing the objects inside an ArrayList of an ArrayList of such objects. Say I have a Student object:
public class Student
{
private String homeAddress;
private String monthBorn;
private String yearBorn;
private int;
public Student(String homeAddress, String monthBorn, String yearBorn,
int finalGrade)
{
this.homeAddress = homeAddress;
this.monthBorn = monthBorn;
this.yearBorn = yearBorn;
this.finalGrade = finalGrade;
}
}
And then methods to get address, month, year and grade. Then I have a class Class, which is an ArralyList of Student objects:
public class Classroom
{
private String classroom;
private ArrayList<Student> listOfStudents;
public Classroom (String classroom)
{
this.classroom = classroom;
listOfStudents = new ArrayList<Student>();
}
}
And this class includes methods to add Student objects, to list all the students in the class (listAllStudentsInClassroom) which returns an ArrayList of Student, to find the Student with the highest grade in the class (getHighestGradeStudent), and to a list of students with grades higher than a certain amount.
Finally, the class School, which is an ArrayList of Classroom:
public class School
{
private ArrayList<Classroom> school;
public School()
{
school = new ArrayList<Classroom>();
}
}
This includes methods to add a class object, and it should include methods to return the Student with the highest grade ever and a list of students from all classes with grades higher than a certain one. However, I can only get the methods to iterate through only the first class added! Here is the code for getHighestGradeStudentEver so far:
public Student getHighestGradeStudentEver ()
{
Student s = school.get(0).getHighestGradeStudent();
int highestGrade = school.get(0).listAllStudentsInClassroom().get(0).getFinalGrade();
for(int i =1; i< school.size(); i++){
int highestGrade = school.get(i).listAllStudentsInClassroom().get(i).getFinalGrade();
if(value > (highestValue)){
highestValue = value;
s = school.get(i).getHighestGradeStudent();
}
}
return s;
}
This only returns the student with the highest grade from the first classroom object added to School. What am I doing wrong? Sorry for the long question, I tried to be as clear as possible!
If you can already get the highest graded student in a class, you can get that for all the classes, and find the highest grade out of all of those.
// find the highest grade in each class
ArrayList<Student> highestInEachClass = new ArrayList<>();
for (Classroom classroom : school) {
highestInEachClass.add(classroom.getHighestGradeStudent());
}
// find the highest grade overall
Student highestGradeStudent = highestInEachClass.get(0);
for (Student student : highestInEachClass) {
if (highestGradeStudent.getFinalGrade() < student.getFinalGrade()) {
highestGradeStudent = student;
}
}
return highestGradeStudent;
Alternatively, use Stream:
return school.stream().flatMap(x -> x.getListOfStudents().stream())
.sorted(Comparator.comparing(Student::getFinalGrade).reversed())
.findFirst().orElse(null);
As I understand your question, you already have a function Classroom.getHighestGradeStudent() which gives you the best student of that class. You also have a way to get the grade of a given student, since the Student object contains .finalGrade.
You want to loop through all classrooms in the school, and find the student with the highest grade.
So you have your for loop, which iterates over the classrooms. And for every classroom, you get some arbitrary student's final grade:
int highestGrade = school.get(i).listAllStudentsInClassroom().get(i).getFinalGrade();
^
This is likely not what you want. Instead, you want the best student's grade from that classroom. For that, you should instead use
int highestGrade = school.get(i).getHighestGradeStudent().getFinalGrade();
(If my assumption is wrong and you do not have a function getHighestGradeStudent() of a given classroom, you would need to loop over the result of listAllStudentsInClassroom() (or store that list sorted))
Then, you can continue with your code as you're doing, by updating the stored best student s if the best student of the current classroom is better than what you previously had in s.
But make sure you use either highestGrade or highestValue, not both of them. As your code stands, I don't see highestValue defined anywhere.
Note, that it's possible to make this code more efficient, if you only search for the best student in a given class once. I would do
Student bestOfClassroom = school.get(i).getHighestGradeStudent();
int highestGrade = bestOfClassroom.getFinalGrade();
so you already have your student to store in s by simply doing s = bestOfClassroom instead of searching through the whole list again.
But this is an optimization that should not be relevant for the Correctness of your program.

Prevent duplicated ID entry in Java

I have a set up a constructor in a Book class, and another class I have set up an ArrayList of type Book. The book expects to receive a title, author, bookID, copies, timesLoaned, onLoan.
I am looking to find the most efficient way to ensure that there are no duplicated bookID before adding a book. I have not learned about Map etc, so would like to avoid this for now. I was thinking about the use of a for loop to check the bookID's before adding.
Below is my addBook method:
// Adding a book to ArrayList
public void addBook(){
System.out.println("==============================");
// Getting user input and assigns it to variables
System.out.print("Enter a title: ");
String title = sc.nextLine();
System.out.print("Enter an author: ");
String author = sc.nextLine();
System.out.print("Enter quantity of books: ");
int quantity = checkInput(sc); // checks for valid integer
// Generates random ID for book
int bookID = (int) Math.round(Math.random() * 1000000);
// Adding book the the ArrayList, using user input taken above
newBook.add(new Book(title, author, bookID, quantity, 0, false));
// Adding to maxReturns for returnBook()
maxReturns.add(quantity);
// Testing that it has added - TAKE OUT AFTER COMPLETION
for(int i = 0; i < newBook.size(); i++){
System.out.println(newBook.get(i).getBookID() + " " + newBook.get(i).getTitle());
}
// Showing its been added
System.out.println("Book has been added!");
System.out.println("==============================");
}
I would also suggest a Map, but if you want to use an ArrayList you should think that ArrayList implements the List interface, which has a contains method. You could thus just query whether your ArrayList contains the new book. The contains method will then loop through the ArrayList using the equals method to check whether each book is equal to the new one you want to compare against. It would be a good idea to (correctly) override your Book's HashCode in a safe way.

Accessing an Array list inside of another Array List through multiple classes

I am doing some practice with Java and had an example in my textbook that continues to stump me. The problem reads:
"P8.7 Modify the grade book application of How To 7.1 so that it can deal with multiple
students. First, ask the user for all student names. Then read in the scores for all
quizzes, prompting for the score of each student. Finally, print the names of all students
and their final scores. Use a single class and only static methods.
P8.8 Repeat Exercise P8.7, using multiple classes. Modify the GradeBook class so that it
collects objects of type Student. Each such object should have a list of scores."
I am currently on the 8.8 exercise. I understand how to use multiple classes and have a general understanding of how this problem should be solved. Earlier I created a program that acted as a "bank". This bank contained multiple "accounts" which were contained as separate objects of the "BankAccount" class. Each account had a separate balance and account number. I was able to create a method in the "bank" class to search by account number.. This did not get the balance however only told whether the account existed.
In my current problem I have a GradeBook class that will contain numerous objects of the "Student" class. Each of these "Students" will contain a list of grades kept as an ArrayList. The problem that I'm having is knowing exactly how to call an individual array list for a student so that it can be displayed. I've tried numerous methods but can't seem to wrap my mind around doing it. Could someone look at my code and tell me how I would retrieve the list of individual grades for a student in the final tester class? My tester class is not complete because I am stuck at this step but I believe you can get the picture..
GradeBookTester class
package gradebook_multi_class;
import java.util.ArrayList;
import java.util.Scanner;
import bankAccount.Bank;
public class GradebookTester
{
public static void main(String args[]){
Scanner in = new Scanner(System.in);
int counterMain=0;
ArrayList<String> list = new ArrayList<String>();
GradeBook book = new GradeBook();
System.out.println("Welcome to the gradebook utility!");
do{
System.out.println("Please enter a student name: ");
String name = in.next();
System.out.println("Please enter the student quiz grade: ");
String grade = in.next();
list.add(grade);
list.add("3");
book.addStudent(new Student(name,list));
System.out.println("Do you have more students to add? (Y/N)");
String input = in.next();
if(input.equalsIgnoreCase("Y")){
}else{
counterMain=1;
}
}while(counterMain==0);
}
}
GradeBook Class
package gradebook_multi_class;
import java.util.ArrayList;
public class GradeBook
{
private ArrayList<Student> students;
public GradeBook(){
students = new ArrayList<Student>();
}
public void addStudent(Student a){
students.add(a);
}
public Student find(String aName){
for(Student a: students){
if(a.getName().equals(aName))
return a;
}
return null;
}
}
Student Class
package gradebook_multi_class;
import java.util.ArrayList;
public class Student
{
private String studentName;
private ArrayList<String> grades = new ArrayList<String>();
public Student(String aName, ArrayList<String> list){
studentName = aName;
grades=list;
}
public String getName(){
return studentName;
}
public ArrayList<String> getGrades(){
return grades;
}
}
You have already done all of the work, in your find method of the GradeBook class.
You'd just do, in your main class:
Student desiredStudent = book.find("Joe");
desiredStudent.getGrades();
Finally, print the names of all students and their final scores.
If that is the problem then just like Student.getGrades() add a method GradeBook.getStudents(),
public ArrayList<Student> getStudents() {
return students.AsReadOnly();
}
Then in the main() method,
for (Student student : students) {
System.out.println("Student: " + student.getName());
System.out.print("Grades: ");
for (String grade : student.getGrades())
System.out.println(grade + " ");
}

how do i add or delete something from an array?

I am writing this program that will take in the names, ages and salaries for 5 different people from the user and will put them in an array.
I then want to write a method that will ask the user for another name, age and salary and add that into the array. Also a method that will as for the name of someone who's already in the array and will delete the information of the person with that age from the array.
The first method will increase the array size by 1 and the second will decrease the array size by 1. so far this is what I have:
ArrayList<details> details = new ArrayList<details>();
for(int x = 0; x < 4; x++) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter the first name: ");
String firstName = scan.nextLine();
System.out.println("Enter the last name: ");
String lastName = scan.nextLine();
System.out.println("Enter the age: ");
int age = scan.nextInt();
System.out.println("Enter the salary: ");
double salary = scan.nextDouble();
details.add (new details(firstName, lastName, age, salary));
}
I don't know how to go about doing this. I need some help!
thanks!
You can have a class Person with the class variables you require (name,age,salary)
class Person {
private int age;
private dobule salary;
private String firstname;
private String lastname;
}
Define the getter and setter methods for each of the class variables. For e.g
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
In your main class read the input from STDIN as you are doing it. Instantiate the Person object for each of the 5 person.
Person employee = new Person();
employee.setAge(x);
employee.setFirstName(x);
employee.setLastName(y);
employee.setSalary(y);
Now, you can add each Person to your list and remove them too.
For removing any Person you would have to search for the Person through the ArrayList by name. That would be iterating over the length of ArrayList and comparing the name of each.
The final class would look like,
public class Solution{
private ArrayList<Person> details = new ArrayList()<Person>;
public static void main(){
// Here you loop for reading from STDIN as you are already doing.
// addPerson() would be used to add to ArrayList and removePerson() for the other
}
public addPerson(String firstName, String lastName, int age, int salary){
//Create the Person object
details.add(<person object>);
}
public removePerson(name){
details.remove(index);
// to get index it would require iterating over the ArrayList.
// It would be better if you use a Map instead (as other suggest)
// with name as the key
}
}
Hope this helps.
dud first of all, i can see that u have used arrayList name & Class name both same so please update that.
secondary use Map in place of Class like in if condition
if(){
Map userDetails = new HashMap();
map.put("firstname",firstname);
..
..
map.put("salary",scan.nextDouble());
details.add(map)
}
and on time of delete iterate ArrayList
for(int i=0;i<details.size();i++){
Map tempMap = details.get(i);
if(temp.get("firstname").toString() == "Given Name"){
}else{
// your logic
}
}
Hope will help you please let me know if any doubts.
use this code for removing employee
void removeEmployee(String name){
for(Employee emp :details){
if(name.equals(emp.getName())){
details.remove(emp);
break;
}
}
}
and do include exception handling

print toString() from another class

I asked a question earlier on this same project but I'm still having issues that I can't get through.
The project has a Person class, Validator class, Customer class, and Employee class. The Person class stores data about the person (name, email) the Customer class extends the person class and adds a customer number to the toString method. The Employee class also extends the Person class and extends a social security number to the toString method by overriding it.
At the bottom of the page I am trying to print the toString methods from my customer class OR my employee class. I want to make sure I am printing the right class based on what the user selected (if they are entering customer info or employee info)
The assignment specifically says "To print the data for an object to the console, this application should use a static method named print that accepts a Person object."
I think I have it started but I'm getting all kinds of red lines under what I have coded. Starting around the
public void toString()
line down towards the bottom.
I'm starting to think I am getting deeper into trouble by looking it up online so if someone can help me through it I would be greatful. My book doesn't show much on how to do this and all of the examples it shows seem to create the input and then print it but I'm trying to get the input from a user so I'm getting confused.
import java.util.Scanner;
public class PersonApp
{
public static void main(String[] args)
{
//welcome user to person tester
System.out.println("Welcome to the Person Tester Application");
System.out.println();
Scanner in = new Scanner(System.in);
//set choice to y
String choice = "y";
while (choice.equalsIgnoreCase("y"))
{
//prompt user to enter customer or employee
System.out.println("Create customer or employee (c/e): ");
String input = in.nextLine();
if (input.equalsIgnoreCase("c"))
{
String firstName = Validator.getString(in, "Enter first name: ");
String lastName = Validator.getString(in, "Enter last name: ");
String email = Validator.getEmail(in, "Enter email address: ");
String custNumber = Validator.getString(in, "Customer number: ");
Customer customer = new Customer(firstName, lastName, email, custNumber);
}
else if(input.equalsIgnoreCase("e"))
{
String firstName = Validator.getString(in, "Enter first name: ");
String lastName = Validator.getString(in, "Enter last name: ");
String email = Validator.getEmail(in, "Enter email address: ");
int empSoc = Validator.getInt(in, "Social security number: ");
Employee employee = new Employee(firstName, lastName, email, empSoc);
}
public void toString()
{
Person p;
p = c;
System.out.println(c.toString());
p = e;
System.out.println(e.toString());
}
System.out.println("Continue? y/n: ");
choice = in.nextLine();
System.out.println();
}
}
}
You can't define methods inside another method. The way you have the brackets, toString is defined inside main, which is illegal.
Also, you can't have toString return void, since it overrides the toString method from Object. Rename your method or have it return a String.
Your toString method needs to be moved out of your main method. It also needs to return a string. You'll probably have to call the method by some other name. Also, if Employee and Validator are in a separate package structure, you'll have to import that

Categories