Finding specific instance of class? [duplicate] - java

This question already has answers here:
How to find an object in an ArrayList by property
(8 answers)
Closed 5 years ago.
I've just started learning java and I'm trying to create an application to register students.
Based on this question how-would-i-create-a-new-object... I created a while loop to create an instance of a class.
public class RegStudent {
ArrayList<Student> studentList = new ArrayList<>();
Scanner input = new Scanner(System.in);
public void reggaStudent(int start) {
while (start != 0) {
String programNamn, studNamn;
int totalPoint, antalKurser;
System.out.println("Vad heter programmet?");
programNamn = input.nextLine();
System.out.println("Vad heter studenten");
studNamn = input.nextLine();
System.out.println("Hur många poäng har studenten?");
totalPoint = input.nextInt();
System.out.println("Hur många kurser är studenten registrerad på?");
antalKurser = input.nextInt();
// Add student to list of students
studentList.add(new Student(totalPoint, antalKurser,
programNamn, studNamn));
System.out.println("Vill du registrera in en fler studenter? "
+ "Skriv 1 för ja och 0 för nej");
start = input.nextInt();
input.nextLine();
} // End of whileloop
}
}
The class is:
public class Student {
private int totalPoint;
private int antalKurser;
private String programNamn;
private String studNamn;
private static int counter;
public Student(int totalPoint, int antalKurser, String program, String studNamn) {
this.totalPoint = totalPoint;
this.antalKurser = antalKurser;
this.programNamn = program;
this.studNamn = studNamn;
counter++;
}
public int getTotalPoint() {
return totalPoint;
}
public void setTotalPoint(int totalPoint) {
this.totalPoint = totalPoint;
}
public int getAntalKurser() {
return antalKurser;
}
public void setAntalKurser(int antalKurser) {
this.antalKurser = antalKurser;
}
public String getProgramNamn() {
return programNamn;
}
public void setProgramNamn(String programNamn) {
this.programNamn = programNamn;
}
public String getStudNamn() {
return studNamn;
}
public void setStudNamn(String studNamn) {
this.studNamn = studNamn;
}
public static int getCount(){
return counter;
}
#Override
public String toString() {
return String.format(" Namn: %s, Program: %s, Antal poäng: %d, "
+ "Antal kurser: %d\n ", studNamn, programNamn, totalPoint, antalKurser);
}
}
How do I go about to get and set the instance variables in specific instance? I.e find the instances.
I understand it might be bad design but in that case I would appreciate some input on how to solve a case where i wanna instantiate an unknown number of students.
I've added a counter just to see I actually created some instances of the class.

You simply query objects for certain properties, like:
for (Student student : studentList) {
if (student.getProgramName().equals("whatever")) {
some match, now you know that this is the student you are looking for
In other words: when you have objects within some collection, and you want to acquire one/more objects with certain properties ... then you iterate the collection and test each entry against your search criteria.
Alternatively, you could "externalize" a property, and start putting objects into maps for example.

studentList.add(new Student(totalPoint, antalKurser,
programNamn, studNamn));
You now have your Student objects in a list. I assume you have something like
List<Student> studentList = new ArrayList<>();
somewhere in your code. After you populate the list with Student objects, you can use it to find instances. You need to decide what criteria to use for a search. Do you want to find a student with a specific name? Do you want to find all students in a given program? Do you want to find students with more than a certain number of points?
Maybe you want to do each of these. Start by picking one and then get a piece of paper to write out some ideas of how you would do the search. For example, say you want to find a student with the name "Bill". Imagine that you were given a stack of cards with information about students. This stack of cards represents the list in your program. How would you search this stack of cards for the card with Bill's name on it? Describe the steps you need to take in words. Don't worry about how you will code this yet. The first step in writing a computer program is breaking the solution down into small steps. After you have a clear idea how you might do this by hand in the physical world, you can translate your description into Java code.

Related

JAVA: Having trouble printing Array [duplicate]

This question already has answers here:
What's the simplest way to print a Java array?
(37 answers)
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 2 years ago.
I have an assignment where I have to have a class named Employee with two variables and a class called Salary that inherits those variables and declares new ones. Within the Salary class, I have to create a method that will take user input for the different variables. The first number inputted is the number of employees you are giving information for and tells the loop how many times to go around. After typing in the information for all the employees the information must be presented like this
123 John engineer 40000.0
124 Emma Testing 33000.0
The only other thing that is required in the program is a function that will check the salary variable and if it is under 20000, not display the employee information to the console.
I have the user input working but I can't seem to get the array to display properly. Whatever I try I either get gibberish or null. I have tried putting the array and the array printing function in the display method and the main method and it doesn't make a difference. How can I fix this?
Side note: I know having different scanners for each input is not the best way of doing things it's just temporary. I'm trying to get the program to work before cleaning it up. The reasoning for it is a type mismatch error using one scanner as a result of scanning an int, then two strings, then a double.
This is the code I have right now:
import java.util.Scanner;
class Employee {
int employee_id;
String employee_name;
Employee(int employee_id, String employee_name) {
}
Employee() {
}
}
class Salary extends Employee {
double monthly_salary;
String designation;
int num_of_employees;
int n = 0;
Salary(int employee_id, String employee_name, String designation, double monthly_salary) {
super(employee_id, employee_name);
}
Salary() {
}
void display() {
Scanner s = new Scanner(System.in);
Scanner c = new Scanner(System.in);
Scanner a = new Scanner(System.in);
Scanner e = new Scanner(System.in);
Scanner t = new Scanner(System.in);
num_of_employees = s.nextInt();
for (;n<num_of_employees;) {
employee_id = c.nextInt();
employee_name = a.nextLine();
designation = e.nextLine();
monthly_salary = t.nextDouble();
n++;
}
s.close();
c.close();
a.close();
e.close();
t.close();
}
}
public class Solution2 {
public static void main(String[] args) {
Salary sal = new Salary();
Salary salary[] = new Salary[10];
sal.display();
salary[sal.n] = new Salary(sal.employee_id, sal.employee_name, sal.designation,
sal.monthly_salary);
if (sal.monthly_salary >= 20000) {
System.out.println(salary[sal.n]);
}
else {
System.out.println("");
}
}
}
The result from the array with this code is
Salary#7b23ec81

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.

Sorting Student names

im having a trouble finishing my work because i dont know how to do the sorting of names together with the grade in ascending and descending. i hope you guys can help.
import java.util.Scanner;
public class SortingStudents {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print("Enter the number of students: ");
int capacity = s.nextInt();
String [] name = new String[capacity];
Double [] grade = new Double[capacity];
for(int i = 0; i < capacity; i++) {
System.out.print("student's name: ");
name [i] = s.next();
System.out.print("grade: ");
grade [i] = s.nextDouble();
}
Scanner input = new Scanner(System.in);
System.out.println("Type A for Ascending D for Descending:");
char a=input.nextLine().charAt(0);
if(a == 'A' || a == 'a'){
for(int i = 0; i<grade.length;i++){
System.out.println(grade[i]+"\t" +grade[i]);
}
}
}
You are using Java, which is an object-oriented programming language. This means you can think about your problem in terms of classes which represent state in your problem domain and have behavior (methods) which manipulate this state.
In this case your code shows several responsabilities, for which you could create useful classes and/or methods:
entering data via the command line (number of students, name and grade and desired sorting direction)
a registry of students with a fixed size
sorting the student registry in the desired direction
Class names that come to mind are: DataEntry, Student, StudentRegistry. For sorting the students in different ways the standard approach is creating a Comparator class, see below.
The classes could look roughly like this:
public class Student {
private String name;
private Double grade;
// getters and setters ommitted for brevity
}
The registry:
public class StudentRegistry {
// it's easier to use a List because you are adding students one by one
private List<Student> students;
public StudentRegistry(int capacity) {
// ...constructor code initializes an instance of StudentRegistry
}
public void addStudent(Student student) {
// add a student to the list
}
public Student[] getStudents(Comparator<Student> comparator) {
// sort the list using the comparator and Collections.sort()
// use List.toArray() to convert the List to an array
// alternatively (java 8) return a Stream of Students
// or return an unmodifiable List (using Collections.unmodifiableList())
// you don't want to expose your modifiable internal List via getters
}
}
A comparator which can sort Ascending or Descending. You could consider adding the capability to sort either by grades or by names, that would be quite easy.
public class StudentComparator implements Comparator<Student> {
public enum Direction {
ASCENDING, DESCENDING
}
// optional addition:
//public enum Field{
// NAME, GRADE
//}
// if used, add Field parameter to the constructor
public StudentComparator(Direction direction) {
// initialize instance
}
#Override
public int compare(Student a, Student b) {
// implement Comprator method, see JavaDoc
}
#Override
public boolean equals(Object o) {
// implement equals, see JavaDoc
}
}
Class for letting the user enter data:
public class DataEntry {
public int getNumberOfStudents() {
// ...
}
public Student getStudent() {
// ...
}
public StudentComparator.Direction getSortingDirection() {
// ...
}
}
And a main class:
public class Main {
public static void main(String[] args) {
DataEntry dataEntry = new DataEntry();
int capacity = dataEntry.getCapacity();
StudentRegistry studentRegistry = new StudentRegistry(capacity);
for(int i=0; i<= capacity; i++) {
studentRegistry.addStudent(dataEntry.getStudent());
}
StudentComparator comparator = new StudentComparator(dataEntry.getSortingDirection());
Student[] students = studentRegsitry.getStudents(comparator);
}
}
This approach separates concerns of your problem in separate classes and methods, making the code much easier to understand, debug and test.
For example, to test the Main class you could set up a mock DataEntry class which provides predetermined values to your test. See the topic of unit testing.
If you want to do it your way without changing how the arrays are stored separately. You will not be able to use the Arrays.sort() method to sort your grades because that will not take the name array into account and you will lose the link between them so that the grades will no longer match with the names.
You could very quickly code up your own bubble sorter to quickly sort the array, and then you could use your loop to affect the name array at the same time. But if you don't want to code your own sorter, you will need to organise your grades and names array so that can be treated as one unit i.e in a separate class.
If you choose to code your own sorter then here is a great link to learn that: http://www.java-examples.com/java-bubble-sort-example
If you choose to change the way that you store the grades and names, here is how you can use the Arrays.sort() method:
http://www.homeandlearn.co.uk/java/sorting_arrays.html
You could just concatenate the name and grade and sort them, that way it could be a lot easier.

Sorting three different arrays [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
This is the problem: Write a program that prompts the user to enter goods sale information including the name of the goods, quantity, and amount. First, the user is required to input the number of goods, and then input goods sale information one by one. Then the program will print out the goods information sort by quantity (from largest to smallest), and sort by amount (from largest to smallest) respectively. I'm having trouble sorting the information from the user by quantity and amount. For example, the output should be something like this:
Sort by quantity:
Item Qty Amount
CD 32 459.20
T-Shirt 22 650.80
Book 14 856.89
Sort by amount:
Item Qty Amount
Book 14 856.89
T-Shirt 22 650.80
CD 32 459.20
import java.util.Scanner;
public class SalesAnalysis {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("Enter the number of goods");
int number=1;
int goods=input.nextInt();
for(int i=1;i<=goods;i++){
System.out.println("Enter information for item"+ number);
number++;
System.out.println("Name:");
String name=input.next();
String array[]=new String[]{name};
System.out.println("Quantity:");
int quantity=input.nextInt();
int ar[]=new int[]{quantity};
System.out.println("Amount (in USD):");
double amount=input.nextDouble();
double a[]=new double[]{amount};
getQuantity(array,ar,a);
getAmount(array,ar,a);
}
public static void getQuantity(String array[],int ar[],double a[]){
System.out.println("Sort by Quantity:");
System.out.println("--------------------");
System.out.print("Item"+" " +"Qty"+ "Amount" );
}
}
Seems like you don't know java well.
Create a class for Item. Keep name, quantity and amount as fields in it.
implement comparable interface while creating this class. Implete compareTo method to compare based on quantity.
While taking inputs from user, keep creating a object for a every single item with required details, keep adding these items in a arraylist.
Sort that arraylist (it will sort on quantity as you have implemented compareTo method).
Iterate over list, and print details.
I know you don't many of the things I mentioned here, but you will end up learning quite a few things about OOP and Java, this way.
EDIT: New and improved answer.
So to start out doing this you are going to want to make an Item class, that can store information such as the item's name, the items quantity, and the items price. Here is how I have done this:
public class Item {
private String name;
private int quantity;
private double price;
public void setName (String name) {
this.name = name;
}
public String getName () {
return this.name;
}
public void setQuantity (int quantity) {
this.quantity = quantity;
}
public int getQuantity () {
return this.quantity;
}
public void setPrice (double price) {
this.price = price;
}
public double getPrice () {
return this.price;
}
}
As you can see, I have made all of the stored variables private so I am using getters and setters.
From here you are going to want to make a way for users to input items. I have not set up an UI for this but instead I have made it where the program reads the file in its folder named input.txt. I did this like so:
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class ItemManager {
public Item[] items;
public Item[] sortedByQuantity;
public Item[] sortedByPrice;
public static void main(String[] args) {
String filepath = "input.txt";
if(args.length >= 1) {
if(args[0] != null) {
filepath = args[0];
}
}
ItemManager runProgram = new ItemManager();
runProgram.AssignValues(filepath);
runProgram.Display();
}
From here the system then analyzes the contents of input.txt using a scanner such as you have done. The input file should be formatted like this:
ItemName(no spaces) Quantity Price
new line for new item
public void AssignValues(String filepath) {
try{
Scanner scanner = new Scanner(new File(filepath));
StringBuilder sb = new StringBuilder();
while(scanner.hasNextLine()){
sb.append(scanner.nextLine());
if(scanner.hasNextLine()){
sb.append(" ");
}
}
String content = sb.toString();
tokenizeTerms(content);
}
catch(IOException e){
System.out.println("InputDocument File IOException");
}
}
This method uses string builder to compile a single string out of the input text. From here it calls tokenizeTerms on the content. This method splits the string into a String[], using a space as a delimiter, hence not being able to use spaces in the item names.
public void tokenizeTerms(String content) {
String[] tokenizedTerms = content.split(" ");
Item[] itemArray = new Item[tokenizedTerms.length/3];
int currToken = 0;
for(int i = 0; i < itemArray.length; i++) {
itemArray[i] = new Item();
try {
itemArray[i].setName(tokenizedTerms[currToken]);
currToken++;
int foo = Integer.parseInt(tokenizedTerms[currToken]);
itemArray[i].setQuantity(foo);
currToken++;
double moo = Double.parseDouble(tokenizedTerms[currToken]);
itemArray[i].setPrice(moo);
currToken++;
} catch (Exception e) {
System.out.println("Error parsing data.");
}
}
this.sortedByPrice = itemArray;
this.sortedByQuantity = itemArray;
this.items = itemArray;
}
In this method it also creates a temporary array of Items. Which are then iterated though using a for-loop and the items are assigned there corresponding tokenized values from the input text. Now all we have to do is sort the arrays and print them in the console. As you can see above in the main method, we call Display().
public void Display() {
Arrays.sort(sortedByQuantity, (Item i1, Item i2) -> Double.compare(i1.getQuantity(), i2.getQuantity()));
Arrays.sort(sortedByPrice, (Item i1, Item i2) -> Double.compare(i1.getPrice(), i2.getPrice()));
System.out.println("Sorted by quantity:");
for(Item currItem : sortedByQuantity) {
System.out.println("Name: " + currItem.getName() + " Quantity: " + currItem.getQuantity() + " Price: " + currItem.getPrice());
}
System.out.println("Sorted by price:");
for(Item currItem : sortedByPrice) {
System.out.println("Name: " + currItem.getName() + " Quantity: " + currItem.getQuantity() + " Price: " + currItem.getPrice());
}
}
The code starts out by first using lambda expressions to sort the arrays based off a custom compare method. From here we just iterate through each array and print each value.
That is the basic setup for what you are looking for, you can now modify these methods to your liking and apply them in whatever way seems fit. You also could also modify it to allow users to directly input the values in the software, or modify it to allow item names to have spaces. Best of luck.

Implementing classes and objects in java, calling a method

I'm having trouble with calling a method. The basis of the program is to read in data from data.txt, grab the name token given, then all of the grades that follow, then implement some operations on the grades to give details of the person's grades. I do all of the methods in a separate file named Grades.java, which has the Grades class. I'm just having trouble because I MUST have the testGrades method in my code (which I don't find necessary). I have done everything I need to do for the results to be perfect in a different program without having two different .java files. But it's necessary to do it this way. I think I have mostly everything pinned down, I'm just confused on how to implement and call the testGrades method. I commented it out and have the question on where it is in the program. Quite new to classes and objects, and java in general. Sorry for the lame question.
public class Lab2 {
public static void main(String[] args) {
Scanner in = null; //initialize scanner
ArrayList<Integer> gradeList = new ArrayList<Integer>(); //initialize gradeList
//grab data from data.txt
try {
in = new Scanner(new File("data.txt"));
} catch (FileNotFoundException exception) {
System.err.println("failed to open data.txt");
System.exit(1);
}
//while loop to grab tokens from data
while (in.hasNext()) {
String studentName = in.next(); //name is the first token
while (in.hasNextInt()) { //while loop to grab all integer tokens after name
int grade = in.nextInt(); //grade is next integer token
gradeList.add(grade); //adding every grade to gradeList
}
//grab all grades in gradeList and put them in an array to work with
int[] sgrades = new int[gradeList.size()];
for (int index = 0; index < gradeList.size(); index++) {
sgrades[index] = gradeList.get(index); //grade in gradeList put into grades array
}
//testGrades(sgrades); How would I implement this method call?
}
}
public static void testGrades(Grades grades) {
System.out.println(grades.toString());
System.out.printf("\tName: %s\n", grades.getName());
System.out.printf("\tLength: %d\n", grades.length());
System.out.printf("\tAverage: %.2f\n", grades.average());
System.out.printf("\tMedian: %.1f\n", grades.median());
System.out.printf("\tMaximum: %d\n", grades.maximum());
System.out.printf("\tMininum: %d\n", grades.minimum());
}
}
This is a little snippet of the beginning of the Grades.java file
public class Grades {
private String studentName; // name of student Grades represents
private int[] grades; // array of student grades
public Grades(String name, int[] sgrades) {
studentName = name; // initialize courseName
grades = sgrades; // store grades
}
public String getName() {
return studentName;
} // end method getName
public int length() {
return grades.length;
}
well your test grades take a Grades object so you need to construct a Grades object using your data and pass it to your test grades method
i.e.
Grades myGrade = new Grades(studentName,sgrades);
testGrades(myGrade);
It looks like what you need to do is have some type of local variable in your main method, that would hold your custom Grade type. So you need add a line like..
Grades myGrades = new Grades(studentName, sgrades);
Then you can call your testGrades method with a line like...
testGrades(myGrades);
Looks like you may also need a toString method in your Grades class.
Seems like homework, so I tried to leave a bit to for you to figure out :)

Categories