I need help with understanding structure for my "small student management app". I need to:
Create SUBJECT.
Subject has a name and number of categories which are types of grades eg. Java, 2, Homework, Project
Each type of grade has weight e.g. Homework, 10
Save that in file
Input grades for STUDENT for selected SUBJECT
Student has ID, name, and grades for each of categories that SUBJECT was chosen.
Save to file
Do some calculations with weight from SUBJECT and inserted grades for student.
I have wrote two methods:
private void createSubject(String name,
int numberOfCat,
List<String> category,
List<Integer> weight);
private void insertGrade(int id, String name, List<Integer> grade);
These methods save input to subjects.txt and students.txt as my database tables. I have also methods for editGrade and deleteSubject as well as viewGrades and viewSubjects
Right now I can add to my filines like that e.g.:
subjects.txt -> (Java, Homework, 10, Project, 40, Final,50,)
students.txt -> (001, John)
My problems start here. I can't imagine right now how can I:
Select one SUBJECT from subjects.txt
Insert grades for student. Number of grades must match number of categories in selected SUBJECT.(Thats why in insertGrade I have saved only ID and name)
Retrieve weights so I can do calculations with grades inserted by user.
If anyone can help me with understanding how can I make it. I don't need a code but I would love to get some clarification how to look at it. Thank you and I'm ready to talk and learn ;)
Are you trying to abstract Subject and Student into classes?
public class Execute {
public static void main(String[] args){
//1.Creating some instance of Grade
Grade grade1 = new Grade("Homework", 10);
Grade grade2 = new Grade("Project,", 40);
Grade grade3 = new Grade("Final,", 50);
//2.Putting all these grades in an ArrayList
List<Grade> grades = new ArrayList<Grade>();
grades.add(grade1);
grades.add(grade2);
grades.add(grade3);
//3.Creating an instance of Subject
Subject Java = new Subject("Java", grades);
//4.Putting the subject in an ArrayList
List<Subject> subjects = new ArrayList<Subject>();
subjects.add(Java);
//5.Creating an instance of Student
Student student = new Student("001", "John", subjects);
/**
* Now you have a student called John, choosing a subject called Java.
* There are 3 parts of this course: Homework, Project, and Final exam.
*/
}
}
public class Student {
private String id;
private String name;
private List<Subject> subjects;
public Student(String id, String name, List<Subject> subjects) {
this.id = id;
this.name = name;
this.subjects = subjects;
}
}
public class Grade {
private String name;
private Integer weight;
public Grade(String name, Integer weight) {
this.name = name;
this.weight = weight;
}
}
public class Subject {
private String name;
private List<Grade> grades;
public Subject(String name, List<Grade> grades) {
this.name = name;
this.grades = grades;
}
}
Well, if I understand you correctly, you do work on the text files. I would not do that.
Load both files on startup and get their content into corresponding classes like students and subjects.
Now with all data loaded, you can easily work on them (like iterate over you lists and so on). At the end, replace the files with the new content.
For the subjects, maybe a map would be nice, if it is really just the two information.
Is it helping you or did I get you wrong?
Related
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.
Thanks for your help! I abandoned the advanced for loop, and it runs fine now. But the requirement still makes me confused. The requirement is to throw an exception if the test case passes more than 5 objects. But it also says "Do not use java scan, build allocation programmatically". I cannot get the point. If I do not use scan, how can I know how many objects the user passes? How can I decide whether it is more than 5 or equals 5? Or is there a way to populate an array without knowing how many objects I'm going to pass?
Teacher's requirement:
• When populating the array of Book objects, application should throw an exception, if test case passed more object than array capacity. Array capacity is defined as (nBooks = 5 ;). Do not use java scan, build allocation programmatically.
• Use ONLY ARRAY NOT LIST for this assignment.
The Book Class
public class Book {
private int id;
private String name;
private double price;
public Book() {
id = 0;
name = "";
price = 0;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setPrice(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
}
The BookApp Class:
public class BookApp {
public static Book[] populateBooks() {
Scanner input = new Scanner(System.in);
Book[] books = new Book[5];
for (int i = 0; i < books.length; i++) {
books[i] = new Book();
System.out.print("Enter book id: ");
books[i].setId(input.nextInt());
System.out.print("Enter book name: ");
books[i].setName(input.next());
System.out.print("Enter book price: ");
books[i].setPrice(input.nextDouble());
}
return books;
}
}
But it also says "Do not use java scan, build allocation
programmatically". I cannot get the point. If I do not use scan, how
can I know how many objects the user passes? How can I decide whether
it is more than 5 or equals 5? Or is there a way to populate an array
without knowing how many objects I'm going to pass?
"build allocation programmatically" means you don't have to request or parse any user input - just write code to do it directly.
However, the requirements mention a "test case". That means you should have separate logic for managing the array (testing capacity and throwing an exception) and doing this programmatic allocation. It doesn't sound like you're expected to use a testing framework, so simply give the BookApp class the array as instance variable, an addBook() method, and do the testing in its main method.
I am writing a pension program and I am stuck.
The program looks like this:
First I read in a file where every line has the name of the person, the age, and their first deposit.
I use a method called ReadFile to do that. Inside that method I call upon a class called class savingswhich is in a separate file to calculate their pension.
But I have the following problem: I would like to sort their names according to their pensions (highest to lowest) but I don't know how to do that.
Here is the method in the Readfile class:
#SuppressWarnings("resource")
public void readFile(double rate) {
while(scan1.hasNextLine()) {
String input = scan1.nextLine();
scan2 = new Scanner(input).useDelimiter("/");
String a = scan2.next();
int b = scan2.nextInt();
int c = scan2.nextInt();
// calculate savings
savings s = new savings();
s.totalSavings(a, b, c, rate);
// add savings to an array
}
}
1st, create a class say Person :
class Person{
private String name;
private int age;
private BigDecimal firstDeposit;
private BigDecimal pension;
//Setters and getters method
}
Now Create the List which will hold the information of every Person :
List<Person> personList=new ArrayList<Person>();
Now sort your list based on Pension :
Collections.sort(personList, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return p1.getPension().compareTo(p2.getPension());
}
});
Given you the hint to go about your problem, but as suggested by other users, kindly go through the basics of java.
I have two constructors for Student and am trying to use both of them with one object. But I should be doing it wrong because my output is not what I expect it to be.
Output:
School: null
Grade Level: 0
Intended Major: null
Student's ID number is: 154324
Student's name: Sam Bay
Student's GPA: 3.56
Code for class definition:
public class Student
{
private int id, gradeLevel;
private String name, school, major;
private double gpa;
//constructor to initialize the instance variables of student object
public Student(int id, String name, double gpa)
{
this.id = id;
this.name = name;
this.gpa = gpa;
}
public Student(int gradeLevel, String school, String major)
{
this.gradeLevel = gradeLevel;
this.school = school;
this.major = major;
}
//toString() to display the attributions of the student object
public String toString()
{
return "School: " + school +
"\nGrade Level: " + gradeLevel +
"\nIntended Major: " + major + "\n" +
"\nStudent's ID number is: " + id +
"\nStudent's name: " + name +
"\nStudent's GPA: " + gpa;
}
}//end class
code for main:
public class StudentDrive
{
public static void main(String [] args)
{
//creating student objects
Student sam = new Student(12, "Alpha High School", "Biology");
sam = new Student(154324, "Sam Bay", 3.56);
System.out.println(sam);
}
}
It seems like I've initialized the first part but I get null and 0??!!!
You can't use two constructors simultaneously on a single object.
In your code:
Student sam = new Student(12, "Alpha High School", "Biology");
creates a new Student object and assigns its reference to the variable sam.
On your next line:
sam = new Student(154324, "Sam Bay", 3.56);
This creates another Student object, separate from the first, and reassigns sam to refer to it instead. In the process, you end up orphaning the original Student and leave it open to garbage collection.
What you really want to do is either pass all data required for by a Student through a single constructor, or provide getters/setters (e.g. setGradeLevel(int level)) and a layer of exceptions that prevent methods from accessing a Student object until all fields are filled. The first option is generally more sound.
For example, a complete constructor would look something like this (formatted for readability):
public Student(int id, int gradeLevel, String name,
String school, String major, double gpa)
{
// fill your fields in here
}
I think you should read through the docs for a constructor again ;)
With Student sam = new Student(12, "Oakton High School", "Biology");
you are creating a Student-object with the given parameters and storing it in the variable sam.
When you call sam = new Student(154324, "Sam Bay", 3.56); you are again creating a new Student-object and storing it in sam. You are not modifying the first object but rather discarding it and creating a new one.
You should try adding a method to your Student object like:
public void setAdditionalValues(int id, String name, double gpa){
this.id = id;
this.name = name;
this.gpa = gpa;
}
Hope this is helpful :)
EDIT: as mentioned earlier you could also use one constructor that takes all the arguments or implement setters for each attribute of the Student-object like this:
public void setName(String name){
this.name = name;
}
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