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.
Related
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?
So I am reading from a file with scanner it has the similar format:
title, name, age
Mr, Matthew, 20
mr, Paul, 30
miss, Anne, 24
CSV^
class person{
String name, title;
int age;
public crimeData(String csv){
String[]list = csv.split(",", -1);
name = list[0];
title = list[1];
age = list[2];
}
}
Console Program
Scanner input = new Scanner(System.in);
System.out.println("Please select what data you want to load:");
String selection = input.next();
int temp = 0;
for(int i=0; i< header.length; i++){
if(header[i].equals(selection)){
temp = i;
break;
}
}
temp will give us the index of the option specified so if it is 2 we will want to access the age property
When my console application runs I prompt them(the user) for the data that they want.
So they may enter "age" So I am lost on how I may take this "age" String and access the person object with it.
The ideal case for the program output should be: 20,30,24 going through each age and printing
I take their input so String input = scanner.nextLine();
Then I loop through my array of person objects to get the index of the input. Once I have this index I then want to access the property of person at the index. So like if my index was 1 I would want to access the property 'name'.
In javascript I could take the string and say person['age'] although java's a whole different story. I have looked into java's "reflection API" although it's a heavy learning curve.
I have looked into java's "reflection API" although it's a heavy learning curve.
Well, Reflection is the way to go. It's widely used in many frameworks.
But perhaps a simpler solution will fit your needs. Use a switch to decide which attribute to return, and encapsulate this in a method of the Person class:
class Person {
private String name, title;
private int age;
public loadData(String csv){
String[] list = csv.split(",");
name = list[0];
title = list[1];
age = Integer.parseInt(list[2]);
}
public Object attribute(String attribute) {
switch (attribute) {
case "name": return this.name;
case "title": return this.title;
case "age": return this.age;
default: throw new RuntimeException("Invalid attribute: " + attribute);
}
}
}
Encapsulating the switch inside the method is in line with OOP principles, since it hides how attributes are stored from other objects, only exposing an interface to query them. Reflection breaks all encapsulation.
Though in general I am not in favor of using Map for holding fields for an object, if the number of properties is large and could even potentially vary across CSV files (e.g., some file has the University a person attended, another does not), then using a Map to hold the properties might be appropriate.
In this case, one would define a simple Person class:
public class Person {
Map<String, String> props = new HashMap<>();
public void addProperty(String propertyName, String value) {
// could add error checking to ensure propertyName not null/emtpy
props.put(propertyName, value);
}
/**
* returns the value of the property; may return null
*/
public String getProperty(String propertyName) {
return props.get(propertyName);
}
}
If it is know that certain attributes/properties will always be loaded, then accessors such as getName() could be added:
public String getName() {
return props.get("name");
}
public int getAge() {
String age = props.get("age");
// or throw exception if missing
return (age != null ? Integer.parseInt(age) : -1);
}
Though note I would expect name to not be a single entry for most datasets, as there typically would be last name, first name, etc. Nonetheless, the pattern for a limited number of commonly expected values is the same. Also, you can adapt so that you could get integer values directly for certain well-known fields.
Then, when you parse the file, you keep the title row that has the attribute definitions. Then for each row that you subsequently read, you create a new Person object, and then add the properties in order.
List<Person> allPersons = new ArrayList<>();
while ( (line = READ_NEXT_LINE) ) {
// NOTE: this is not a safe way to handle CSV files; should really
// use a CSV reader as fields could have embedded commas
attrs[] = line.split(",");
Person p = new Person();
for (int i = 0; i < titleRow.length; ++i) {
p.addProperty(titleRow[i], attrs[i]);
}
allPersons.add(p);
}
You can then get a specific Person by Person myPerson = allPersons.get(index_of_person), and much akin to the way you would have used Javascript, you can do String val = myPerson.getProperty("age").
If you need to search by a given attribute, you can then stream/loop over the allPersons and check of equivalence based upon a given property.
// find all people of a given age
List<Person> peopleAge20 = allPersons.stream()
.filter(p -> p.getAge() == 20)
.collect(Collectors.toList());
System.out.println(peopleAge20);
// summary statics (average age) for all people
IntSummaryStatistics stats =
allPersons.stream().mapToInt(p -> p.getAge()).summaryStatistics();
System.out.printf("Average age: %f\n", stats.getAverage());
Note that this approach does break the idea of a Javabean, but that may or may not be an issue depending upon your requirements.
First thing, we should add a constructor to your Person class.
class Person {
public Person(String name, String title, int age) {
this.name = name;
this.title = title;
this.age = age;
}
}
Now while you read the input you can use a Map as follows. Here after reading each line, we create a Person object and then using that person's age we make an entry in the map with key as age and value as Person.
Map<Integer, Person> mapOfPeople = new HashMap<>();
while (input.hasNextLine()) {
String line[] = input.nextLine().split(",");
Perso person = new Perso(line[1], line[0], Integer.parseInt(line[2].trim()));
mapOfPeople.put(person.getAge(), person);
}
Now to fetch a particular Person by age just do
mapOfPeople.get(20);
I am currently working on a project for school and am really struggling. I am supposed to selection sort a group of Student objects and then display them in selection sort order.
Create an array with the size of 10 and assign student details (Name, BroncoId, age and TotalMarks) to the array. Perform the selection sort to sort the students in descending order based on their total marks.
a. Steps:
i. Create the student list (use Random class in java to generate the age (15-25) and total (0-100))
ii. Print the Student List in a table format
iii. Perform selection sort based on the total marks of the students
The place I am stuck at currently is making the selection sort. I understand how to create the selection sort, but I can't seem to translate it for this implementation.
My selection sort code:
public static Student[] selectionSort(Student[] studentList)
{
for(int i = 0; i <studentList.length-1; i++)
{
int minIndex = studentList[i].getGrades();
int pos = i;
for(int j = i + 1; j < studentList.length-2; j++)
{
if(studentList[j].getGrades() > studentList[minIndex].getGrades())
{
minIndex = studentList[j].getGrades();
pos = j;
}
}
int temp = studentList[pos].getGrades();
studentList[pos] = studentList[i];
int k = studentList[i].getGrades();
k = temp;
}
return studentList;
}
When I run this code, the console returns:
I sought tutoring to hopefully fix this problem, but my tutor gave me a few nonfunctional suggestions. We were both stumped at the end of the session.
My code for printing:
public static void printStudentInfo(Student[] students)
{
System.out.println("Name: AGE: idNumber: Score:");
for(Student student: students)
{
if(student.getName().length() <= 49)
System.out.printf("%-50s %-5d %-10s %-4d\n", student.getName(), student.getAge(), student.getID(), student.getGrades() );
else
{
System.out.printf("%-50s %-5d %-10s %-4d\n", student.getName().substring(0,48), student.getAge(), student.getID(), student.getGrades() );
System.out.println();
int i = 0;
while(i <= student.getName().length())
{
System.out.printf("%-50s", student.getName().substring(49 +48*i, 97+48*i) );
System.out.println();
i++;
}
}
}
}
As more of an issue out of passion, I sought to make an interesting print method. My problem is, also that I don't really know how to parse and format a string of 155 characters for instance. What do I put in this while lop to accomplish this?
I want the program to output one object name line like:
49 characters
49 chars
…
What ever is left
It probably won't ever go past three lines, but hey, who says I can't give an example like that? What do I put in the header of the while loop to accomplish this?
PS:
Here is the Student class if you need it.
public class Student
{
private String name;
private int age;
private String idNumber;
private int gradePoints;
public Student(String name, int age, String idNumber, int gradePoints)
{
this.name = name;
this.age = age;
this.idNumber = idNumber;
this.gradePoints = gradePoints;
}
public void setName(String name)
{
this.name = name;
}
public void setAge(int age)
{
this.age = age;
}
public void setidNumber(String idNumber)
{
this.idNumber = idNumber;
}
public void setPoints(int gradePoints)
{
this.gradePoints = gradePoints;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String getID()
{
return idNumber;
}
public int getGrades()
{
return gradePoints;
}
Welcome to SO Matthew.
Rather than giving you a solution I thought it might be useful to give you a process for solving the problem yourself.
Good practice in software development is to break your problem down into very small components, make sure each of those work perfectly (through unit testing) and then build your solution from those components.
In line with that practice I suggest you do the following:
list each of the individual steps required to do a selection sort on paper.
Pick the simplest one (e.g. swapping two elements).
Write a unit test that would pass if your swap method worked
run the unit test and verify that it fails
write the simplest code you can to make that test pass
write a new test to cover a more complex scenario that isn't yet supported
keep going until you believe that method works perfectly
move onto the next method
once all the components are working perfectly write the method that calls them all using the same process (i.e. test first then code)
If you follow this process then you will end up with a system that you understand perfectly, works, is maintainable, and that you can refactor. It has another very significant benefit: it means when you come to SO with a question you'll be asking about a specific item that you don't know how to solve rather than a 'why doesn't my code work' question. Specific questions tend to get better and faster responses.
In your case, I would start with methods for swapping items (hint: your code for this doesn't work which you'll discover quickly when you write a unit test) and then move on to finding the smallest item in a sublist. Then a method that uses those two to put the smallest item at the start of a sublist. Finally a method that performs that method for all sublist progressively. Make sure each method is working perfectly, including checking validity of arguments, before you move on to putting them together.
My program asks the user to enter the first name, last name and age of 5 people and stores them in an array. I want to write a method that asks the user whom they want to delete from the array and then deletes that employee. I know in arrays you cannot technically delete an object from an array, just replace it.
This is what I've done so far:
private void deleteEmployee(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter the first name of the employee you want to delete from the list")
String name = scan.nextLine();
for (int i = 0; i < employees.length; i++) {
if (employees[i].getFirstName().equals(name)){
employees[i] = employees[employees.length - 1];
break;
}
if (i == employees.length - 1) {
System.out.println("That requested person is not employed at this firm.")
}
}
My problem is that it does not decreases the array size by 1, it just replaces the person I want to delete with the last person in my array. My output has the last employee in the array repeated twice (in it's last index and in the index of the person I wanted to delete) How do I fix this?
you can replace the employee with null whenever want to delete it. when inserting a new emplyee, you can first look at a null index and place it.
private void deleteEmployee(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter the first name of the employee you want to delete from the list")
String name = scan.nextLine();
for (int i = 0; i < employees.length; i++) {
if (employee[i] != null && employees[i].getFirstName().equals(name)){
employees[i] = null;
break;
}
if (i == employees.length - 1) {
System.out.println("That requested person is not employed at this firm.")
}
}
You may want to use ArrayLists for this problem. ArrayLists are Java's way of creating a mutable array. With arraylists, the array can be automatically expanded and reduced based on the number of objects in the Array.
You can add and delete objects using the index or variable name.
Sample Code:
ArrayList<Employee> employees = new ArrayList<>;
Then you can use the following methods:
employees.remove(int index);
employees.remove(Object o);
Check this out for more reference: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
One possibility: although you can't change the actual length of the array, you can use another variable to keep track of the "real" length (i.e. the number of elements in the array that you know are valid):
int currentLength = employees.length;
for (int i = 0; i < currentLength; i++) {
if (employees[i].getFirstName().equals(name)){
employees[i] = employees[currentLength - 1];
// employees[currentLength - 1] = null; ... could help reclaim storage
currentLength--;
break;
}
if (i == currentLength - 1) {
System.out.println("That requested person is not employed at this firm.")
}
The program just "knows" that array elements from employees[currentLength] through employees[employees.length - 1] aren't meaningful. You could also set those meaningless elements to null so that there aren't unused references that could prevent some objects from being garbage-collected (this would be important in a larger program). This approach can be a bit error-prone, because you have to remember to use currentLength instead of employees.length. Overall, I think it's better to use an ArrayList, which has a way to delete elements.
The length of an array in Java can not be changed, it's initialized when you create it.
And you can not manual delete a element immediately(like C++). You can set it to null, then wait for the JVM to recycle it.
For convenience, you can use List collection in java.util package. They are convenient for remove/add elements.
I suggest you make use of ArrayList, it already had the remove method. That method also make the size of the list reduce by number of removed items
Hi things will be simpler for you if you use an ArrayList instead of an array, Here is how your code will look like assuming that you have a EmployerClass implementing the getFirstName() method
List<EmployerClass> employees = new ArrayList<EmployerClass>();
// Here is the new type of your employees pool
....
// do whatever you want to put employees in the poll using employees.add(...)
private void deleteEmployee(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter the first name of the employee you want to delete from the list")
String name = scan.nextLine();
EmployerClass tmpEmployer = null;
for(EmployerClass emp : employees) {
if(emp.getFirstName().equals(name)) {
break;
}
}
if(tmpEmployer != null){
// remove the employee to the pool
employees.remove(tmpEmployer);
} else {
System.out.println("That requested person is not employed at this firm.");
}
}
good luck !
You can't really delete it, but you can only make it null.
ArrayList or LinkedList is better for this task. In both you can use builtin methods to add or remove elements and size is handle automatically.
There are some points:
(1) Java array(use the symbol "[]") is a fixed size structure. It means you must specify the size(length) of the array when you create it. Like this:
int[] intArray = new int[10];
The purpose of the specific size is to tell Java compiler to allocate memory. Array is allocated in contiguous memory. Once the allocation has been done, its size could not be changed.(You can image there are other data "behind" the array, if the array is extende, will overlap the other data.)
(2) If you want to get a flexible data collection, for your adding/removing, you can use ArrayList or LinkedList. These Java built-in collections can be extended by themselves if needed.
What's more:
ArrayList is implemented by Java array, it will automatically create a new larger array and copy the data into it when its Capacity is not enough. It has good performance in loop, access elements by index.
LinkedList is implemented by Linked List. It has good performance in insert/remove elements.
For Both lists, if you want to use the remove(Object o) correctly, you have to implement your object's public boolean equals(Object) function.
Ref to the code:
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class ListTest {
public static void main(String[] args) {
List<Employee> employees = new LinkedList<Employee>();
// List<Employee> employees = new ArrayList<Employee>();
// Add 3 employees
employees.add(new Employee("Tom", "White", 10));
employees.add(new Employee("Mary", "Black", 20));
employees.add(new Employee("Jack", "Brown", 30));
// See what are in the list
System.out.println(employees);
// Remove the 2nd one.
employees.remove(new Employee("Mary", "Black", 20));
// See what are in the list after removing.
System.out.println(employees);
}
static class Employee {
private String firstName;
private String lastName;
private int age;
public Employee(String firstName, String lastName, int age) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public boolean equals(Object obj) {
if(super.equals(obj)) {
return true;
}
else {
if(obj.getClass() == Employee.class) {
Employee that = (Employee)obj;
return firstName.equals(that.getFirstName()) && lastName.equals(that.getLastName()) && (age == that.getAge());
}
else {
return false;
}
}
}
#Override
public String toString() {
return "Employee [firstName=" + firstName + ", lastName="
+ lastName + ", age=" + age + "]\n";
}
}
}
This is my school assignment. I need an inventory system which auto-updates product ID when users key-in a new product. I created an array of object named Product with 4 attributes(name,ID,price,quantity). The ID should not need a user input.
This part is in the input() method,which is in a different class from the Object.I didn't pass the ID to the object class like I did to the other three attributes.
x[i] = new Product(name,price,stock);
id = x[i].setID();
part of the object class:
/**
* Constructor
*/
public Product(){
id = 0; name = ""; price = 0.00; quantity = 0;
}
public Product( String n, double p, int q){
setName(n); setPrice(p); setQuantity(q);
}
public void setID(){
this.id = id++;
}
Thank you.
What you have won't work, because id is an instance variable. This means that every product you create will have an ID of 0. And calling setID() on every product you create will set the ID of avery product to 1.
You need a static counter, which would belong to the class, and not to each of its instances:
public class Product {
private static int nextId = 0;
...
public Product(String name, double price, int quantity) {
this.id = Product.nextId;
Product.nextId++;
this.name = name;
this.price = price;
this.quantity = quantity;
}
}
Note that this wouldn't work well in a multi-threaded environment, and that double is a bad choice for prices, but you'll learn that later.
See the Java tutorial for more information about instance and static variables.
Are you looking for a way of generating a unique id for each Product object? If so, the way you've coded it now doesn't work, because each Product has its own id, which is completely independent of all other Product objects. There are a couple of ways you could approach this:-
Look into what static variables mean in Java
Maintain a variable in your code that gets incremented every time you create a Product object. Pass this variable into the constructor of Product.