I have created two arrays. One to store names and one to store sales. I am trying to link the indexes of each together so that index 1 from then name array will bring up the value of index 1 of the sales array. I am trying to get it to sort out the sales array and return the max sales and the person that brought in those sales. All the values are inputted by the user including the size of the arrays.
import java.util.Scanner;
import java.util.Arrays;
public class EmpArray {
public static int employee(){
Scanner input = new Scanner(System.in);
int numemp;
System.out.println("Enter how many employees to be compared: \n");
numemp = input.nextInt();
String name[] = new String[numemp];
int annsales[] = new int[numemp];
int maxannsales;
for (int i = 0; i < name.length; i++) {
System.out.println("Enter your name: \n");
String employeename = input.next();
name[i] = employeename;
System.out.println("\n");
}
for (int j = 0; j < annsales.length; j++) {
System.out.println("Enter in your annual sales: \n");
int employeesales = input.nextInt();
annsales[j] = employeesales;
System.out.println("\n");
}
System.out.println("Employee Name: " + Arrays.toString(name));
System.out.println("Total Sales: " + Arrays.toString(annsales));
Arrays.sort(annsales);
//look at page 456 of starting out with java and page 460 of the same book, p.464
System.out.println("Top Salary is : $"+annsales[annsales.length-1]);
maxannsales = annsales[annsales.length-1];
return maxannsales;
}
}
What am I doing wrong I have been at this for two weeks now.
You should make a class to store the date rather than the use two separate arrays.
public class Employee {
private int sales;
private String name;
public Employee(String name, int sales){
this.name = name;
this.sales = sales;
}
public String getName(){
return this.name;
}
public int getSales(){
return this.sales;
}
}
Now store the name and sales as local variables when you read in from your Scanner and pass them to the Employee constructor. You can then create an Employee array[] or ArrayList<Employee> and sort this array/arraylist on Employee.getSales()
Like so:
import java.util.Scanner;
import java.util.Arrays;
public class EmpArray {
public static void main(String[] args){
employee();
}
public static int employee(){
Scanner input = new Scanner(System.in);
int numEmp;
System.out.println("Enter how many employees to be compared: ");
numEmp = input.nextInt();
input.nextLine();
Employee[] employees = new Employee[numEmp];
for (int i = 0; i < numEmp; i++) {
System.out.print("Enter your name: ");
String employeeName = input.nextLine();
System.out.println();
System.out.print("Enter in your annual sales:");
int employeeSales = input.nextInt();
input.nextLine();
System.out.println();
//creates an Employee object based on the constructor defined in Employee
Employee employee = new Employee(employeeName, employeeSales);
employees[i] = employee;
}
//initialize maxSeller to first employee
Employee maxSeller = employees[0];
for(int i = 0; i < employees.length; i++){
//using the getters we created in Employee
System.out.println("Employee Name: " + employees[i].getName());
System.out.println("Total Sales: " + employees[i].getSales());
System.out.println();
//checks if employees[i] sold more than maxSeller
if(maxSeller.getSales() < employees[i].getSales()){
maxSeller = employees[i];
}
}
System.out.println();
System.out.println("Top Seller: " + maxSeller.getName());
System.out.println("Top Sales: " + maxSeller.getSales());
return maxSeller.getSales();
}
}
If you sort the array with the numbers, then that gets sorted. You can find the top or bottom sales amount, but you cannot get the name of the salesperson. The two arrays are not linked in any way, so you cannot expect sorting one to cause the sorting of the other.
You need to take an approach that is fundamentally different., using different data structures.
For instance, one approach would be to have a single Array, but not to make it of String(s) or int(s), but to store both the name and the sales together, as a pair. You could pout the pair into an object as shown by sunrize920, or you could put them both in a map.
Having paired them together into some type of object, you can then have an Array of such objects.
Then, you could sort that array. To do so, you will need to write a custom comparator.
Alternatively, keep your two arrays and don;t do any sorting. Just loop through on and find the largest number. Remember the position of the largest sales number. Then, look up the name in the other array, using the same position.
Related
I am new to java and I am currently trying to make a program that uses an array of 10 inputted names and ages. What I want to do is add an option so that if the user types "done" when prompted to enter a name, the program will skip straight to listing the names and ages already entered.
Code:
import java.util.Arrays;
public class array2 {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
input.useDelimiter(System.getProperty("line.separator"));
int numofpeople = 10;
Person[] persons = new Person[numofpeople];
for (int i = 0; i < numofpeople; i++) {
System.out.print("Enter the person's name: ");
String person = input.next();
System.out.print("Enter the persons's age: ");
int age = (Integer) input.nextInt();
persons[i] = new Person(person, age);
}
Arrays.sort(persons);
System.out.print("Name" + "\tAge");
System.out.print("\n----" + "\t----\n");
for (int i = 0; i < persons.length; i++) {
System.out.println(persons[i].person + "\t" + persons[i].age);
}
System.out.println("The oldest person is: " + persons[numofpeople-1].person);
System.out.println("The youngest person is: "+ persons[0].person);
}
}
class Person implements Comparable<Person> {
public String person;
public Integer age;
public Person(String s, Integer g) {
this.person = person;
this.age = g;
}
#Override
public int compareTo(Person o) {
return (this.age>o.age?1:-1);
}
}
What I'm thinking is that I need to use a boolean if statement that defines whether or not done has been entered, and if it has, then the program skips asking the user for the rest of the names and ages and instead jumps to printing the already entered ones. I am not sure on this so, any help would be appreciated!
Your thought is correct, the simplest way would be checking if person is equal to "done". If this is true, break the loop and code should continue, and it should produce the result you want.
You can do comething like this:
for (int i = 0; i < numofpeople; i++) {
System.out.print("Enter the person's name: ");
String person = input.next();
if (!person.equals("done")) {
System.out.print("Enter the persons's age: ");
int age = (Integer) input.nextInt();
persons[i] = new Person(person, age);
} else {
//print table or enter here a break; directive
}
}
If user enter done instead of any name, your program will straight to listing the names and ages already entered.
this also jumps out of the for loop and moves on to printing the list if the user types in "done":
for (int i = 0; i < numofpeople; i++) {
System.out.print("Enter the person's name: ");
String person = input.next();
if(person == "done"){break;}
System.out.print("Enter the persons's age: ");
int age = (Integer) input.nextInt();
persons[i] = new Person(person, age);
}
The question is from the Nested For Loops chapter, so I assume that I should use Nested For Loops for this.
In an entrance examination, students have answered English, Maths and Science papers. Write a program to calculate and display average marks obtained by all the students. Take number of students appeared and marks obtained in all three subjects by every student along with the name as inputs.
And this is my code:
import java.io.*;
class average
{
public static void main(String args[]) throws IOException
{
InputStreamReader read = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(read);
int i,j,m,s,e,sum;
String name;
double a;
System.out.println("Enter number of students that appeared");
int n = Integer.parseInt(in.readLine());
for(i=1;i<=n;i++)
{
System.out.println("Enter name");
name = in.readLine();
System.out.println("Enter marks obtained in English");
e = Integer.parseInt(in.readLine());
System.out.println("Enter marks obtained in Maths");
m = Integer.parseInt(in.readLine());
System.out.println("Enter marks obtained in Science");
s = Integer.parseInt(in.readLine());
sum = e + m + s;
a = sum/3.0;
System.out.println("Average Marks = "+a);
}
}
}
So how do I exactly use Nested For Loop with this? Have I misunderstood the question? If so, then what should I do?
I think you should not use nested loop in the code snippet. You should split it with two parts: receive student's data and pring student's data.
First, define a class that represents student's score:
public final class StudentScore {
private final String name;
private final int scoreEnglish;
private final int scoreMaths;
private final int scoreScience;
// TODO a put this parameter hered, but probably it's is better to calculate id every time when required
private final double avg;
public StudentScore(String name, int scoreEnglish, int scoreMaths, int scoreScience) {
this.name = name;
this.scoreEnglish = scoreEnglish;
this.scoreMaths = scoreMaths;
this.scoreScience = scoreScience;
avg = (scoreEnglish + scoreEnglish + scoreEnglish) / 3.;
}
// getters
}
Second, define a method that use Scanner (this is more useful that InputStreamReadr when working with console) to receive amount of students and student's data:
private static List<StudentScore> getStudentsScore() {
try (Scanner scan = new Scanner(System.in)) {
System.out.print("Enter number of students that appeared: ");
int total = scan.nextInt();
List<StudentScore> studentScores = new ArrayList<>(total);
for (int i = 0; i < total; i++) {
System.out.print("Enter name: ");
String name = scan.nextLine();
System.out.print("Enter marks obtained in English: ");
int scoreEnglish = scan.nextInt();
System.out.print("Enter marks obtained in Maths: ");
int scoreMaths = scan.nextInt();
System.out.println("Enter marks obtained in Science");
int scoreScience = scan.nextInt();
studentScores.add(new StudentScore(name, scoreEnglish, scoreMaths, scoreScience));
}
return studentScores;
}
}
Third, all you left to do is just receive list of student's data and pring required parameters:
List<StudentScore> studentScores = getStudentsScore();
studentScores.forEach(studentScore -> System.out.format("Average Marks for student '%s' is '%.2f'\n", studentScore.getName(), studentScore.getAvg()));
P.S.
It is not pretty clear what exaclty average score should you calculate, but when you receive List<StudentScore> studentScores, you can calculate all you need.
I have a program that takes students' names and grades as user input and then performs some operations on them, which are irrelevant for the scope of the question. The code is as follows:
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Student {
// Four attributes that define Student
private String name;
private double points;
private int startYear;
private int[] grades;
public Student(String name, double points, int startYear, int[] grades) {
this.name = name;
this.points = points;
this.startYear = startYear;
this.grades = grades;
}
//Constructor. Everyone starts with 0 points and this year
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); //Create scanner
System.out.println("Please enter the number of students:");
int count = sc.nextInt(); // Number of students
System.out.println("Please enter the number of grades:");
int count1 = sc.nextInt(); // Number of grades
Student students[] = new Student[count]; // Create array of student objects based on previously entered value
int[] temp = new int[count1]; // Temporary array for storing grades entered
for (int i = 1; i < count + 1; i++) {
System.out.println("Please enter the name of student " + i);
String name = sc.next();
students[i - 1] = new Student(name,0.0,2018,temp); // Creating student object
System.out.println("Please enter grades of " + name);
for (int k = 0; k < count1; k++) {
int personal_grades = sc.nextInt();
temp[k] = personal_grades; //filling the temporary array
//System.out.println(grades.length); //for debugging
}
students[i - 1].setGrades(temp); //transferring from temporary array to student object array
students[i-1].printGrades();
}
System.out.println((students[0].name));
System.out.println((students[1].name));
System.out.println(Arrays.toString(students[0].grades));
System.out.println(Arrays.toString(students[1].grades));
for(int i = 0; i < count; i++) {
System.out.println("Grades of " + students[i].name + " are:");
//students[i].printGrades();
}
for(int i = 0; i < count; i++) {
System.out.println("Average of " + students[i].name + " is:");
// students[i].average();
}
int passed=0;
for(int i = 0; i < count; i++) {
if(students[i].average()>5.5)
{
passed++;
}
}
System.out.println(passed+" students passed!");
}
public void setGrades(int[] temp) {
this.grades = temp;
}
public int[] getGrades() {
return grades;
}
public void printGrades() {
System.out.println(Arrays.toString(grades));
}
public float average (){
int k = 0;
int sum=0;
float average=0;
while (k < this.grades.length) {
sum=sum+this.grades[k];
k++;
}
average = sum/(float)this.grades.length;
System.out.println(average);
return average;
}
}
The problem I am having with the code is as follows: the setter method appears to set the values for all of the objects that were ever created. Take this test run as an example:
You can see that the grades for the last student entered appear in every student's record. I have debugged and found that it is the setGrades method that causes this. However, I am using the this keyword - why does it set the value for all the objects then?
You need to move the
int[] temp = new int[count1]; // Temporary array for storing grades entered
inside the outer for loop, otherwise all created Students will have a reference to same grades array and all will end up with the grades of the last student.
It's because you are using the same array for all the grades of everyone.
Moving
temp = new int[count1]; inside the first loop should fix it
Note how both Student's constructor and Student::setGrades() get grades by reference.
This means that for each Student's instance, its grades field points to the parameter that was received during its initialization.
However, you only initialize temp once and therefore all the instances point to the same grades array. Once this array is changed, calling student.printGrades() will print the shared array's contents.
This can be solved by initializing temp on every iteration, before creating a new Student instance; Or by copying the array by value inside setGrades() method:
public void setGrades(int[] temp) {
this.grades.clone(temp);
}
Move the array (temp) holding the grades inside the loop where you create individual Students
for (int i = 1; i < count + 1; i++) {
...
int[] temp = new int[count1]; //The array holding the grades must be *specific* for each student
students[i - 1] = new Student(name, 0.0, 2018, temp); // Creating student object
...
students[i - 1].setGrades(temp); //transferring from temporary array to student object array
students[i - 1].printGrades();
}
In your original code, you are using just one array i.,e temp was pointing to the same array all the time. After you finish initializing the first Student, when you loop populating the grades for the second student, you are mutating (or modifying) the same grades array created for the first student.
This question already has answers here:
Sorting a collection of objects [duplicate]
(9 answers)
Closed 8 years ago.
Almost done with this program, but when it's sorted out the weight is being arranged to from least to greatest, which is correct. The only problem is that the name and age associated with the weight are not sorted with the weight.
for example
mike 25 180
jen 36 105
sam 22 120
I should get
jen 36 105
sam 22 120
mike 25 180
but I get
mike 25 105
jen 36 120
sam 22 180
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public class Lab0 {
public static void main(String[] args) {
//Scanner and variables
Scanner keyboard = new Scanner (System.in);
String name = "";
int age;
double weight;
int number;
//Creates list for name, age, and weight
ArrayList<String> Name = new ArrayList<String>();
ArrayList<Integer> Age = new ArrayList<Integer>();
ArrayList<Double> Weight = new ArrayList<Double>();
System.out.println("Enter the information needed.");
//Ask user to enter information needed
while (true){
System.out.print("Enter last name: ");
name = keyboard.nextLine();
if(name.equalsIgnoreCase("FINISHED")){
break;
}
else {
Name.add(name);
System.out.print("Enter age: ");
age = keyboard.nextInt();
Age.add(age);
System.out.print("Enter weight: ");
weight = keyboard.nextDouble();
Weight.add(weight);
keyboard.nextLine();
System.out.println("==========================================\n");
}
}
//new list to sort weight and age and name
ArrayList<String> NameList = Name;
ArrayList<Integer> AgeList = Age;
ArrayList<Double> WeightList = Weight;
Collections.sort(Weight);
for(int i=0; i<Weight.size(); i++){
for (int j=0; j<Weight.size(); j++){
if(WeightList.get(j) == Weight.get(i)){
Name.set(j, NameList.get(i));
Age.set(j, AgeList.get(i));
}
else;
}
}
//prints out information entered
for (int k=0; k<Weight.size(); k++){
System.out.println("Name: " + Name.get(k) + " Age: " + Age.get(k)
+ " weight: " + Weight.get(k));
}
while (true){
System.out.println("=============================================");
System.out.print("Enter a last name that you listed: ");
String Search = keyboard.next();
int index = Name.indexOf(Search);
if (index >=0){
System.out.println("Age: " + Age.get(index));
System.out.println("Weight: " + Weight.get(index));
}
else if(Search.equalsIgnoreCase ("DONE")){
System.exit(0);
}
else{
System.out.println("NOT FOUND");
}
}
}
}
The problem is, that the relation is loosing between the single-informations.
A person is a tripel like (name, age, weight).
You have three lists and after sorting the list with weights, you're want to concatenate the single-informations.
That is the problem-section of your code:
ArrayList<String> NameList = Name;
ArrayList<Integer> AgeList = Age;
ArrayList<Double> WeightList = Weight;
Collections.sort(Weight);
for(int i=0; i<Weight.size(); i++){
for (int j=0; j<Weight.size(); j++){
if(WeightList.get(j) == Weight.get(i)){
Name.set(j, NameList.get(i));
Age.set(j, AgeList.get(i));
}
else;
}
}
Your first problem is:
If two or more persons having the same weight, you're not find a clearly relation. (Not the topic of your question, but a problem.)
Your secound problem is:
(If all weights are different.)
Collections.sort(Weight);
This method sorts the list 'Weight'.
But it is the same list with the name 'WeightList '.
You're copy the reference.
You shold clone the list first, bevore you're use sort.
And you need to change i and j in 'Name.set(...)' and 'Age.set(...)'.
This should help:
ArrayList<String> NameList = (ArrayList<String>) Name.clone();
ArrayList<Integer> AgeList = (ArrayList<Integer>) Age.clone();
ArrayList<Double> WeightList = (ArrayList<Double>) Weight.clone();
Collections.sort(Weight);
for (int i = 0; i < Weight.size(); i++) {
for (int j = 0; j < Weight.size(); j++) {
if (WeightList.get(j) == Weight.get(i)) {
Name.set(i, NameList.get(j));
Age.set(i, AgeList.get(j));
}
else
;
}
}
I think that's the answer for your problem.
In addition:
You should think about 'ChrisForrence' comment of your qurestion.
It is better using a class for person which implements the interface 'Comparable'.
You should use comparators in my opinion.
That is the general method for getting flexibility.
package javaapplication2;
import java.util.Scanner;
public class JavaApplication2
{
public static void main(String[] args)
{
person_type salespeople[] = new person_type [100];
person_type person = new person_type();
int counter = 0;
person.gross=0;
person.salary=0;
System.out.println("How many workers are there?");
Scanner number_of_workers = new Scanner(System.in);
counter=number_of_workers.nextInt();
for(int i=0; i<counter; i++)
{
salespeople[i] = person;
System.out.println(person.salary);
}
for(int i=0; i<counter; i++)
{
System.out.print("Enter the salary of the salesperson ");
System.out.print(i+1);
System.out.println(":");
Scanner salary = new Scanner(System.in);
salespeople[i].salary = salary.nextInt();
System.out.print("Enter the gross of the salesperson ");
System.out.print(i+1);
System.out.println(":");
Scanner gross = new Scanner(System.in);
salespeople[i].gross = gross.nextInt();
System.out.println("1---- " + salespeople[0].salary);
System.out.println(i);
}
System.out.println("First worker's salary is: " + salespeople[0].salary);
System.out.println("First worker's gross " + salespeople[0].gross);
System.out.println("Second worker's salary is: " + salespeople[1].salary);
System.out.println("Second worker's gross is: " + salespeople[1].gross);
}
private static class person_type
{
int salary;
int gross;
}
}
I am trying to put every employee stored to the array, but all the employees' details are overwritten by the very last one entered by the user. Can you please help? Thanks in advance!!
All the elements in the array refer to the same person_type instance :
for(int i=0; i<counter; i++)
{
salespeople[i] = person;
System.out.println(person.salary);
}
You must create a new person_type instance for each index of the array.
for(int i=0; i<counter; i++)
{
salespeople[i] = new person_type ();
}
BTW, I suggest you change your class name to either Person or PersonType to conform to Java naming conventions.