Is there a way to pass an argument from a class into an array individually (I am not sure how to word it correctly so let me try it with an example).
Suppose I have a class named Lab and from this class there is an instance variable named grade with a getter and setter. Also, there is an array.
public class Lab {
private double grade;
private double[] array = new double[10];
public void setGrade(double grade) { //sets grades for lab reports
}
public double getGrade() {
return grade;
}
Now, from a main class called Teacher I want to call lab and pass students grades into setGrade individually and for each grade passed into the parameter I want those grades to be placed in an array so that in a later class (that I will create) I can retrieve those lab grades.
Scanner input was my first thought but I was just wondering if there is another way to do this using getters, setters, constructors, etc.
You could use an ArrayList. That way you could do the following:
private ArrayList<Double> grades = new ArrayList<>();
public void addGrade(double grade){
grades.add(grade);
}
A grade will be added to 'grades' everytime you call addGrade(double grade).
Because you want to pass a single value each time to an array, you need to keep track of where you can safely add the next value
public class Lab {
private double grade;
private double[] array = new double[10];
private int insertPoint = 0;
public void setGrade(double grade) {
if (insertPoint < array.length) {
array[insertPoint] = grade;
insertPoint++;
}
}
Now, to get a value, you'll need to know which value you want to get...
public double getGrade(int index) {
double value = 0;
if (index >= 0 && < insertPoint) {
value = array[insertPoint];
}
return value;
}
Another option might be to pass the index you want to set...
public void setGrade(int index, double grade) {
if (index >= 0 && index < array.length) {
array[index] = grade;
}
}
Or you could use variable arguments...
public void setGrade(double... grade) {
for (int index = 0; index < grade.length && index < array.length; index++) {
array[index] = grade;
}
This would allow you to pass a single value or multiple values to the same method...
Lab lab = new Lab();
lab.setGrade(1);
lab.setGrade(1, 2, 3, 4, 5);
double grades[] = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
lab.setGrabe(grades);
Just remember, in above example, each call to setGrades replaces the elements in the array (up to the number of elements you pass)
It would be simpler to use some kind of List though
If your Lab class has to hold multiple grades then it should make it clear as
public class Lab {
private double[] studentGrades;
public void setStudentGrades(double[] grades) { //sets grades for lab reports
studentGrades = grades;
}
public double[] getStudentGrades() {
return studentGrades;
}
Now, in your Teacher class you'll collect the grades in a local array and use the setter to set the values on your Lab class object as
int numOfStudents = scanner.nextInt();
double[] grades = new double[numOfStudents];
for(i = 0; i < numOfStudents; i++) {
grades[i] = scanner.nextDouble();
}
lab.setStudentGrades(grades);
Related
I've made a bit of a mess on a project of mine. I have to create an array of objects. I have made an array but it only has 1 field 'myMonths' referring to the length of time of the project.
In my main method:
case 1:
int n = 1; //int n = number of projects
Scanner sc = new Scanner(System.in);
//myMonths = new int[amount];
System.out.println("** Only projects with a duration between 2 and 12 months can be included **");
System.out.println("What was the duration of your projects in months?");
for(int i=0; i<1; i++){
int a = sc.nextInt();
//display error message
if((a < 2) || (a > 12)){
System.out.println(" Please enter an amount between 2 and 12 months. ");
}
//add to the array
else{
myMonths[index++] = a;
}
}
calc.setMyMonths(myMonths); //creating the object
break;
In my class on separate file:
public class MenuTestClass{
private int myMonths[];
private double average; //store average value of numbers
private boolean averageCanBeCalculated;
private int max; // store max number from array. to be calculated
public MenuTestClass(){
myMonths = new int[5];
}
public MenuTestClass(int[] myMonths){
this.myMonths = myMonths;
}
public void setMyMonths(int[] values){ //declare setter method
myMonths = values;
}
I should have added in two more fields, both strings. Is there a way I can add more fields/attributes to this array and have them viewable at the same time under 1 index? For example at [0] projectName, projectManager, myMonths ie(string, string, integer).
Any advice would be great, I am getting really confused with OOP. Thanks in advance!
Yes, create a class containing your three properties:
class MyContainer {
public MyContainer(int durationMonths, String projectName, String projectManager) {
this.durationMonths = durationMonths;
this.projectName = projectName;
this.projetManager = projectManager;
}
public int durationMonths;
public String projectName;
public String projectManager;
}
Then create an array of this class with:
MyContainer[] myArray = new MyContainer[numberOfProjects];
Add items to the array like this:
myArray[0] = new MyContainer(3, "super project", "awesome manager");
When I try to use scanner on another class I can't update the array.
private int numClients;
private int[] clients;
These are variables from my class Rooms.
public Hotel(String name, int numRooms, int numClients){
this.name = name;
this.numRooms = numRooms;
this.numClients= numClients;
this.clients = new int[numClients];
}
Of course I added setters and getters:
public String getName() {
return name;
}
public void setNaziv(String name) {
this.name = name;
}
public int getNumRooms() {
return numRooms;
}
public void setNumRooms(int numRooms) {
this.numRooms = numRooms;
}
public int getNumClients() {
return numClients;
}
public void setNumClients(int numClients) {
this.numClients = numClients;
}
When I tried to add it to test it in another class, name and numRooms change. numClients change too but array doesn't update.
Hotel h1 = new Hotel(" ", 0, 0);
String name= sc.nextLine();
h1.setName(name);
int numRooms= sc.nextInt();
h1.setNumRooms(numRooms);
int numClients= sc.nextInt();
h1.numClients(numClients);
h1.show();
This is the show method:
public void show(){
System.out.println("Name: " + this.name);
System.out.println("Rooms: " + this.numRooms);
System.out.println("Number of clients: " + this.numClients);
for(int i = 0; i < clients.length; i++) {
System.out.println(clients[i]);
}
}
Maybe there will be some typing errors I translated the var names to English for question purposes.
Once you have created the array, it's size is fixed. You can test this with a few rows:
int size = 10; // Start with size 10
int[] array = new int[size]; // Array is 10 elements long
System.out.println(size); // Prints 10
System.out.println(array.length); // Also prints 10
size = 1000; // Change size ??
System.out.println(size); // Prints 1000
System.out.println(array.length); // Still prints 10
Output:
10
10
1000
10
You also don't appear to actually set any elements in the array in your code. That would be something like
h1.getClients()[0] = 3;
Edit
When this line in your constructor is exectuted:
this.clients = new int[numClients];
The array is created with the size that numClients has right at that moment. After that, there is no relation between numClients and clients anymore.
You would need to create a new array, copy contents (if you want to preserve it) and reassign clients with the new array in order to change the size.
You can do this with Arrays.copyOf() :
int newLength = 20;
array = Arrays.copyOf(array, newLength);
System.out.println(array.length); // Prints 20!!
The constructor will run once for a single object. So, if you want to add more values in the clients array then a method is a must.
The main Class:
class Main {
public static void main(String[] args) {
Hotel hotel = new Hotel("romeo",5,10);
hotel.addClients(6);
hotel.addClients(10);
hotel.addClients(5);
hotel.show();
}
}
The Hotel Class:
class Hotel{
private int numRooms,numClients;
private String name;
private int clients[] = new int[10];
public Hotel(String name, int numRooms, int numClients){
this.name = name;
this.numRooms = numRooms;
this.numClients= numClients;
this.clients[0] = numClients;
}
The method to add Clients in the clients array:
public void addClients(int numClients){
for(int i = 0; i < clients.length; i++){
if(clients[i] == 0){
clients[i] = numClients;
break;
}
}
}
Show method output:
Name: romeo
Rooms: 5
Number of clients: 10
10
6
10
5
The Total number of clients can be found by summation of the clients array.
To make the array dynamic, the linked list data structure can be applied.
What I did to fix this without updating and making new methods is defining values with scanner and putting it into constructor.
public void test(){
Scanner sc = new Scanner(System.in);
System.out.print("Type in the name of Hotel: ");
String name= sc.nextLine();
System.out.print("Type in number of rooms: ");
int numRooms = sc.nextInt();
System.out.print("Type in the number of clients");
int numClients= sc.nextInt();
Hotel h1 = new Hotel(name, numRooms, numClients);
h1.show();
}
In the following code i am trying to find which is the best day to buy and sell a stock. However i am only able to calculate the profit that i have from buying and selling at the correct days but i am not able to find the days (index) since they are lost in the recursion. I don't want to use any static variable. The only solution i am thinking is to add a new private method that will hold the correct days.
public class Stock {
public static int maximum(int[] half) {
int max=half[0];
int index=0;
for (int i=1; i<half.length; i++) {
if (half[i]>max) {
max = half[i];
index=i;
}
}
return max;
}
public static int minimum(int[] half) {
int min=half[0];
int index=0;
for (int i=1; i<half.length; i++) {
if (half[i]<min) {
min = half[i];
index=i;
}
}
return min;
}
private static int maxProfit(int[] stock) {
if (stock.length<= 1)
return 0;
int left[] = Arrays.copyOfRange(stock, 0, stock.length/2);
int right[] = Arrays.copyOfRange(stock, (stock.length/2), stock.length);
int maxLeft = maxProfit(left);
int maxRight = maxProfit(right);
int bothSides = maximum(right) - minimum(left);
return Math.max(Math.max(maxLeft,maxRight), bothSides);
}
public static void main(String[] args) {
int[] stock_t = { 13, 5, 2, 12, 3, 15 };
int fi = maxProfit(stock_t);
System.out.println(fi);
}
}
I want to retain the last updated value of days
You can add an instance variable to your class to retain the last updated value for days:
public class Stock{
private int days;
public int getDays(){
return days;
}
}
To retain the value for days after calculation, update the value before the method exits:
//In Stock class
public int maximum(int[] half) { //Make this an instance method (remove static)
int max=half[0];
int index=0;
for (int i=1; i<half.length; i++) {
if (half[i]>max) {
max = half[i];
index=i;
}
}
days = index; //update before method exits
return max;
}
You may also update days in whichever place that is appropriate.
To get the value for days:
public static void main(String[] args) {
int[] stock_t = { 13, 5, 2, 12, 3, 15 };
Stock s = new Stock(); //create Stock object
int fi = s.maxProfit(stock_t); //calculations will update days attribute
System.out.println(s.getDays()); //get days according to last calculation
}
All your methods are static which seems a little weird to me in terms implementation. If your Stock class is supposed to act as a template for creating Stock objects and each individual Stock object retains its own state, your methods and attributes are more appropriate to be declared as non-static.
If your Stock class is to be used as an utility class for just invoking methods, then those methods can be static. But according to your question, this doesn't seems to be the case.
This is from a project that I recently submitted, and I'm kind of frustrated that I couldn't figure this out.
I've got an ArrayList of my objects called studentList; the Student objects' state consists of the following:
private String studentName;
private double quiz1;
private double quiz2;
private double quiz3;
private double quiz4;
private double midTermOne;
private double midTermTwo;
private double finalTest;
private String letterGrade;
I couldn't figure out how to modularize the following code in order to prevent repeating it for each column (i.e. test scores for a student):
...
double quiz1Total = 0.0;
double quiz1Avg = 0.0;
double quiz1min = studentsList.get(0).getQuiz1();
double quiz1max = studentsList.get(0).getQuiz1();
for (int i = 0; i < studentsList.size(); i++) {
quiz1Total += studentsList.get(i).getQuiz1();
if (studentsList.get(i).getQuiz1() > quiz1max) {
quiz1max = studentsList.get(i).getQuiz1();
} // if
if (studentsList.get(i).getQuiz1() < quiz1min){
quiz1min = studentsList.get(i).getQuiz1();
} // if
} // for
quiz1Avg = quiz1Total / studentsList.size();
...
Is the recommendation to extract the test scores into a temp array first and then just pass that to the average/min/max method?
I'm not having trouble with the average/min/max concepts, just the model that I should be using so that I can modularize it.
Thanks.
In Java 8 you could use a method reference or lambda.
But I would simply change the way all of your data is stored in your student class. You could use an array, but I'd use an enum:
public enum Quiz {
QUIZ_1,
QUIZ_2,
QUIZ_3,
QUIZ_4,
MID_TERM_1,
MID_TERM_2,
FINAL_TEST
}
public final class Student {
private final EnumMap<Quiz, Double> grades
= new EnumMap<>(Quiz.class);
public void setGrade(Quiz quiz, double grade) {
grades.put(quiz, grade);
}
public double getGrade(Quiz quiz) {
Double grade = grades.get(quiz);
if (grade == null) {
throw new IllegalArgumentException(
"Student has no grade yet for quiz " + quiz);
}
return grade;
}
}
static double computeAverage(List<Student> students, Quiz quiz) {
double sum = 0;
for (Student student : students) {
sum += student.getGrade(quiz);
}
return sum / students.size();
}
Update: Since you mentioned that you are using Java 8, there's an even easier way, which makes use of some advanced Java 8 features.
Assuming your Student class has methods like getQuiz1(), getQuiz2(), etc., you could do:
List<Student> students = ...
DoubleSummaryStatistics stats = students.stream()
.mapToDouble(Student::getQuiz1)
.summaryStatistics();
double quiz1average = stats.getAverage();
double quiz1max = stats.getMax();
// etc.
// And likewise for quiz2:
DoubleSummaryStatistics stats = students.stream()
.mapToDouble(Student::getQuiz2)
.summaryStatistics();
That is what structures like Arrays are good for.
Either extract the four quizes into an array or, if are allowed to, modify the student class to represent them as an Array in the first place. So your code will look something like:
for every quiz
for every student
...
Is the recommendation to extract the test scores into a temp array first and then just pass that to the average/min/max method?
Yes, you could do that. Or you could store them in arrays to begin with:
class Student {
double[] scores = new double[7];
static final int QUIZ1 = 0;
static final int QUIZ2 = 1;
...
static double average(Student[] students, int scoreIndex) {
...
for(Student student : students) {
sum += student.scores[scoreIndex];
}
...
}
}
(That might be unwieldy in practice, but probably uses concepts you are familiar with.)
Or you could use a Map:
class Student {
Map<String, Double> scores = new HashMap<>();
Student() {
scores.put("quiz1", 0);
scores.put("quiz2", 0);
...
}
static double average(Student[] students, String scoreKey) {
...
for(Student student : students) {
sum += student.scores.get(scoreKey);
}
...
}
}
Assuming quizzes are identifiable, let's say by a String name (or id, whatever), you should store their results for each student in a map:
private Map<String, Double> results = new HashMap<>();
Then add methods to student to get/set the results for a quiz:
public double getResult(String quiz) {
if (results.containsKey(quiz))
return results.get(quiz);
return 0; // hasn't done quiz, so zero score
}
public void setResult(String quiz, double result) {
results.put(quiz, result);
}
Then to calculate an average for a quiz for a some students:
public static double average(Collection<Student> students, String quiz) {
double total = 0;
for (Student student : students)
total += student.getResult(quiz);
return total / students.size();
}
You probably want to represent quiz1 quiz2 ect... as an array so something like this in your student object
class Student {
double[] myQuizs = new double[4];
public double[] getQuizScores(){
return myQuizs;
}
public double getQuiz(double num){
return myQuizs[n];
}
}
then you could do this:
double quizTotal[] = {0,0,0,0};
double quizNAvg[] = {0,0,0,0};
double quizNMin[] = new double[4];
double quizNMax[] = new double[4];
for (int n = 0; n < 4; n++){
for (int i = 0; i < studentsList.size(); i++) {
quizTotal[n] += studentsList.get(i).getQuiz1();
if (studentsList.get(i).getQuiz(n) > quizNMax[n])
quizNMax[n] = studentsList.get(i).getQuiz(n);
if (studentsList.get(i).getQuiz(n) < quizNMin[n])
quizNMin[n] = studentsList.get(i).getQuiz(n);
}
}
4 is the number of quizes i am assuming that there are. You could change that number.
You should modifie quizTotal and quizNAvg so that they have the ammount of quizes as they do elements.
Hoping I can get some help on this. I'm trying to instantiate a generic object Student with a generic arrayList as a list of grades. I can't get my Add method to work properly. I keep getting a null pointer exception- which is obvious as it is initialized to null- just not sure what is wrong with my add method. Any help would be greatly appreciated. Also, the requirements of this assignment are very strict- I have to do it this way. Thanks.
I have two classes: the first, Student:
import java.util.ArrayList;
public class Student <S>{
private String name;
private ArrayList<S> grades;
private double average;
// the constructor
public Student (String studentName, ArrayList<S> studentGrades){
name = studentName;
grades = studentGrades;
}
// get the name
public String getName() {
return name;
}
//set the name
public void setName(String name) {
this.name = name;
}
// add a grade to the array
public void addGrade(S n){
grades.add(n);
}
// return a grade from the array. This will be used for the calculation.
public S getGrade(int n){
return grades.get(n);
}
// compute the average grade for each student
public double computeAverage(){
Double sum = 0.00;
for(S grade : grades){
if (grade instanceof Double){
sum += (Double)grade;
}
if (grade instanceof Integer){
sum += (Integer)grade;
}
}
average = sum.doubleValue()/ grades.size();
return average;
}
public String toString()
{
return name + "'s average grade is " + average;
}
}
And the second, test:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
// create the studentList array
ArrayList<Student> studentList = new ArrayList<Student>();
HashMap<String, Student> studentMap = new HashMap<String, Student>();
// the values for math.random to create the grades
int min = 0;
int max = 100;
double dmin = 0.00;
double dmax = 100.00;
// initialize the variables
ArrayList grades = null;
//------------------------------------
// Create the students (the method signature is wrong. It blows up regardless of what I try to add.)
Student<Integer> Fred = new Student<Integer>("Fred", grades);
//null pointer exception. Also points to the add method in the student class.
//-------------------------------------
Student<Integer> Wilma = new Student<Integer>("Wilma", grades);
Student<Double> Barney = new Student<Double>("Barney", grades);
Student<Double> Betty = new Student<Double>("Betty", grades);
// add the random grades
for(int i = 0; i < 5; i++){
Fred.addGrade((int) (Math.random() * (max - min) + min));
}
for(int i = 0; i < 5; i++){
Wilma.addGrade((int) (Math.random() * (max - min) + min));
}
for(int i = 0; i < 5; i++){
Barney.addGrade((double) (Math.random() * (dmax - dmin) + dmin));
}
for(int i = 0; i < 5; i++){
Betty.addGrade((double) (Math.random() * (dmax - dmin) + dmin));
}
// add the students to the array list
studentList.add(Fred);
studentList.add(Wilma);
studentList.add(Barney);
studentList.add(Betty);
studentMap.put(Fred.getName(), Fred);
studentMap.put(Wilma.getName(), Wilma);
studentMap.put(Barney.getName(), Barney);
studentMap.put(Betty.getName(), Betty);
//iterate through the list & print to the console
Iterator<Student> itr = studentList.iterator();{
while(itr.hasNext()){
System.out.println(itr.next().<Student>toString());
//Initialize the array to hold the key variables
Set<String> mapKeys = studentMap.keySet();
//mapKeys.add(something);
}
}
}
}
You need to initialize the ArrayList grades. Currently you are passing a null value. Do the following in that line:
ArrayList grades = new ArrayList();
A good practice would be to use generics while initializing the ArrayList but since your grades seem to be of differing types, I'm skipping it out.
You are initializing on Test the Grades as null
ArrayList grades = null;
and when you try to add a grade with
Fred.addGrade(...);
the internal code in Student does
grades.add(n);
But grades is initialized to null creating a Null Exception.
Initialize the grades with the proper type.
Example:
Student<Integer> Wilma = new Student<Integer>("Wilma", new ArrayList<Integer>());
Student<Double> Barney = new Student<Double>("Barney", new ArrayList<Double>());
Student<Double> Betty = new Student<Double>("Betty", new ArrayList<Double>());
In your Test class you have
ArrayList grades = null; - you need to create the grades ArrayList and fill it with data before using it.
You could do something like this:
public class Student<S>
{
// declare array
private final ArrayList<S> grades = new ArrayList<S>();
private String name;
// One arg constructor
public Student(String name)
{
this.name = name;
}
// Two arg constructor
public Student(String name, ArrayList<S> grades)
{
this(name);
this.grades.addAll(grades);
}
// etc
}
Edit your code in the following manner in Test class:
Student<Integer> Fred = new Student<Integer>("Fred", new ArrayList<Integer>());
//null pointer exception. Also points to the add method in the student class.
//-------------------------------------
Student<Integer> Wilma = new Student<Integer>("Wilma", new ArrayList<Integer>());
Student<Double> Barney = new Student<Double>("Barney", new ArrayList<Double>());
Student<Double> Betty = new Student<Double>("Betty", new ArrayList<Double>());
Hope, this will help.