I need to make a method which deletes all objects in an array of objects that have the variable grade=1 and return the "resized" array of objects.
the objects looks like this:
public class Exam {
private Course course; // Course is a class
private Student student; // Student is a class
private Integer grade;
private LocalDateTime date; }
public class Student{
private String id;
private LocalDate birthDate; }
public class Course {
private String id;
private String name;
private Integer ECTS;
private Profesor subjectBearer;
private Student[] student;}
the method needs to look something like this:
private Exam[] filterPassedExams(Exam[] exams) { ...}
any help or advice on how to solve the problem without using the lists would be awesome [on the course we didn't learn list yet so we can't really use them
(But I would like to know that solution also if its faster for the future usage)].
I'd stream the array, filter the exams you need to retain, and convert the stream back to an array:
private Exam[] filterPassedExams(Exam[] exams) {
return Arrays.stream(exams).filter(e -> e.grade.intValue() != 1).toArray(Exam[]::new);
}
My approach is to iterate over exams and at once collect the passed exams in a new array passedExams:
private Exam[] filterPassedExams(Exam[] exams) {
Exam[] passedExams = new Exam[exams.length];
int size = 0;
for (Exam exam : exams) {
if (exam.getGrade() != 1) {
passedExams[size++] = exam;
}
}
return size == exams.length ?
exams :
Arrays.copyOf(passedExams, size);
}
Since all exams might be passed the new array passedExams is initialized with the length of exams. If all exams has been passed, we return the original array. Otherwise we resize the passedExams array using Arrays.copyOfwhich returns a new array with the counted size.
Since an array has a fixed size, it's not possible to delete elements. Elements can be set null but not deleted. Thus it's impossible to resize an array. A new array with the filtered elements has to be created.
Java is always pass-by-value. Your exams array is a copy of the argument you sent.
Anyhow, as you are not supposed to use list you can run a loop and check for grades that are not 1, keep a counter. Then create a new array with the size of the counter. Filter the exams array again and this time assign the passed objects to newly created array. return the filtered array.
private Exam[] filterPassedExams(Exam[] exams) {
int size = 0;
for(int i=0; i<exams.length; i++)
if(exam[i].getGrades !=1)
size++;
Exam[] filteredExams = new Exam[size]; //create a new array
size = -1; //lets reuse this
for(int i=0; i<exams.length; i++)
if(exam[i].getGrades !=1)
filteredExams[++size] = exam[i]; // assign the passed exam object to new filtered exam array
return filteredExams;
}
private Exam[] filterPassedExams(Exam[] exams) {
int size = 0;
for(int i=0;i<exams.length;i++){
if(exams[i].getGrade() != 1)
size++;
}
Exam[] tmp = new Exam[size];
size=0;
for(int i=0;i<exams.length;i++){
if(exams[i].getGrade() != 1)
tmp[size++] = exams[i];
}
return tmp;
}
Related
I have an object array containing two fields per object.
I have to write a method that will sort my array by the first field.
I already have a method which extracts the first field from each object
I always get an error message when I call my method to sort.
Here is my code:
public static void trier(String[]code, String[]nom, int nbObj) {
for(int i = 0; i < nbObj-1; i++) {
int indMin = i;
for (int j = i+1; j < nbObj; j++)
if (code[j].compareTo(code[indMin]) < 0)
indMin = j;
if (indMin != i) {
// permutation :
String tempo = code[i];
code[i] = code[indMin];
code[indMin] = tempo;
// permutation :
String temp = nom[i];
nom[i] = nom[indMin];
nom[indMin] = temp;
}
}
}
and the call :
Classe.trier(tableau, tableau, nbObj);
I also tried Class.sort(array.getCode(), array.getName(), nbStudent);
But I still have compilation errors
thank you in advance for your help
First of all, you don't have to use 2 separate arrays to contain your data. You can put everything in a single array, but better way is to use Java Collections. Perfect choice is ArrayList. However, you still better combine two fields into a single object. You can do it like this:
public class MyObject {
String code;
String nom;
MyObject(String code, String nom) {
this.code = code;
this.nom = nom;
}
}
Now you have a class containing 2 fields. Your aim is to sort a collection of such objects by their second field (nom). You can do this easily since Java 8:
public static void sort1(ArrayList<MyObject> list) {
list.sort((obj1, obj2) -> obj1.nom.compareTo(obj2.nom));
}
Or
public static void sort2(ArrayList<MyObject> list) {
list.sort(Comparator.comparing(MyObject::getNom));
} // However for this you need to add method getNom to MyObject
Remember to put your objects in the collection properly.
For example:
MyObject a = new MyObject("abc", "abide");
MyObject b = new MyObject("cab", "whatever you want");
ArrayList<MyObject> list = new ArrayList<>();
list.add(a);
list.add(b);
trier(list);
My code is supposed to print out the student with the highest range. There is a method in my Student class which calculates the range, while in my Classroom class there is another method that determines which student had the highest growth. My problem comes in the class Student, I get an Out of Bounds Exception in the addExamScore method.
Main class:
public class ClassroomTester
{
public static void main (String[] args)
{
Classroom c = new Classroom(2);
Student ada = new Student("Ada", "Lovelace", 12);
ada.addExamScore(44);
ada.addExamScore(65);
ada.addExamScore(77);
Student alan = new Student("Alan", "Turing", 11);
alan.addExamScore(38);
alan.addExamScore(24);
alan.addExamScore(31);
c.addStudent(ada);
c.addStudent(alan);
c.printStudents();
Student mostImproved = c.getMostImprovedStudent();
System.out.println("The most improved student is " + mostImproved.getName());
}
}
Student class:
public class Student
{
private static final int NUM_EXAMS = 4;
private String firstName;
private String lastName;
private int gradeLevel;
private double gpa;
private int[] exams;
private int numExamsTaken;
public Student(String fName, String lName, int grade)
{
firstName = fName;
lastName = lName;
gradeLevel = grade;
exams = new int[numExamsTaken];
numExamsTaken = 0;
}
public int getExamRange()
{
int maximum = 0;
int minimum = 0;
for(int i = 0; i < exams.length; i++){
if(exams[i]<exams[minimum]){
minimum = i;
}
else if(exams[i]>exams[maximum]){
maximum = i;
}
}
return exams[maximum]-exams[minimum];
}
public String getName()
{
return firstName + " " + lastName;
}
public void addExamScore(int score)
{
exams[numExamsTaken] = score;
numExamsTaken++;
}
public void setGPA(double theGPA)
{
gpa = theGPA;
}
public String toString()
{
return firstName + " " + lastName + " is in grade: " + gradeLevel;
}
}
First, you're initializing exams in the constructor the line before you initialize numExamsTaken, the order should be reversed because you need to know what numExamsTaken is before using it. I'd recommend storing the maximum and minimum as scores instead of indexes but that's just personal preference I think it makes the code more readable, so up to you. The index out of bounds problem probably has to do with your addExamScore method. If you've taken 4 exams it might look like [90, 85, 74, 82] where the indexes are 0, 1, 2, 3 and numExamsTaken = 4. Indexes starting at 0 is called zero-indexing and is used in most if not all programming languages.
exams[3] = 82 and exams[4] is going to give you an out of bounds error. Since you're not using an arrayList every time you want to add an element you're going to need to create an empty array of one size bigger than your current array, copy the previous scores over, and slide the new score into the last slot (in the case above would be index 4, which isn't out of bounds in the new array). Store your new array where your old array was in exams[].
Index out of bounds exception shows when array crosses it limits to store the value.
You have declared array of size '0' inside the constructor
in the line exams = new int[numExamsTaken];
initialize the size of the array with your expected range or use ArrayList to add values without specifying the size in prior
The problem with your code here is that you are trying to access a value in an array, which has not been allocated there. This is why the output is giving a ArrayIndexOutOfBoundsException, since you are trying to access an index in an array that is out of bounds of the array. In Java, arrays are fixed in size, meaning once you call new on an array, you cannot change the size of it without calling new on another array with a different size. In this case, it will be easiest to use a List, like an ArrayList, which does all of the resizing, copying, etc. for you, so you can use it as if it were a dynamically sized array. Your code would change to look something like this:
public class Student
{
// ...
private List<Integer> exams;
// ...
public Student(String fName, String lName, int grade)
{
// ...
exams = new ArrayList<>();
// ...
}
public int getExamRange()
{
int maximum = 0;
int minimum = 100;
for(int i = 0; i < exams.length; i++){
if (exams.get(i) > maximum) {
maximum = exams.get(i);
}
if (exams.get(i) < minimum) {
minimum = exams.get(i);
}
}
return maximum - minimum;
}
public void addExamScore(int score)
{
exams.add(score);
numExamsTaken++;
}
}
You can look more into List and ArrayList documentation at the java API website. Also, your logic for getting the minimum element is not correct, since if you have no scores that are less than 0, it will always assume that the minimum score is 0. You can fix this by setting the initial value to 100(the maximum possible value of a test score), or using another method that you prefer.
I have two classes that basically function as the most simplest database, where the user is supposed to enter a string and the program adds it in the array using a class that holds all the methods. Except that when i enter the first name it gives me java.lang.ArrayIndexOutOfBoundsException: 0. I know this means that no memory is being allocated for the array but i thought i did this in my second class where there is a constructer that defines the size of the array. Im not experienced enough with arrays to fix this debug on my own. Much help would be appreicated!
import java.util.*;
public class TestDatabase {
//contant value for data base 'size' of array
public static final int constant = 10;
public static void main (String[] args){
//Database object sets the array size to constant value
Database get = new Database(constant);
//input stream
Scanner in = new Scanner (System.in);
//varaibles for the count and index; prompt
int count = 0;
int index = 0;
System.out.println("Please enter 10 names to add them to the database. Name: " + (count += 1));
//while the count is lower than or equal to 10...
while(count<=10){
//input stream equal to input
String input = in.nextLine();
//if the count equals, stop the loop
if (count == 10)
{
//breaks the loop
break;
}
//prints out the current name
System.out.print(" Name: " + (count +=1));
//adds the input to the array
get.add(index,input);
//increments index by 1
index++;
}
//prints the array
get.print();
}
}
Here is my class with my all my methods:
import java.util.*;
public class Database{
//size of array
public int _size;
//array which has a varaible size
String[] userArray = new String[_size];
//contructer for the array size
public Database(int size){
_size = size;
}
//add method which adds a value to an index of an array
public void add(int index, String name){
//the values of string is placed into some index of the array
userArray[index] = name;
}
//print method which prints the contents of the array
public void print(){
//prints array
System.out.println(Arrays.toString(userArray));
}
//sort method which sorts the array
public void sort(){
//sorts the array
Arrays.sort(userArray);
}
//find method which finds a particular string in any index
public void find(String value){
Arrays.asList(userArray).contains(value);
}
}
Your ArrayList is never instantiated properly, you need to move it into your constructor so when the new operator is called, then the arraylist is created with the size variable that is passed, so something like this:
public Database {
private String[] data;
public Database(int size){
this.data = new String[size];
}
}
With your current code, the array is created before the size is actually given, so it defaults to a size of 0.
userArray init with zero length before your constuctor set _size. Create userArray in constructor.
there next steps performed when you create class:
_size init with 0
userArray init with zero length array
_size init with size value.
Change the code as below
String[] userArray;
public Database(int size){
_size = size;
userArray = new String[_size];
}
I have a text file that contains about 80000+ words. I'm trying to check the length of these words and see if it matches a number entered without using an Array Lists.
Say that an array has these global variables:
public static int INITIAL_SIZE = 100;
public static int size;
public String[] array = new String[INITIAL_SIZE];
I'm going to create an object:
PartArray part = new PartArray();
And a field:
part.array = new String[INITIAL_SIZE];
(And then proceed to expand the array with another method by multiplying the initial size by 2 until it can contain all 80000+ words)
But I want to assign every word in the array at 0, 1, 2, ..... (80000 -1) to something of the extent;
part.array[part.size++] = "aardvark";
.....
part.array[part.size++] = "zymurgy";
so that I can print the words that have this specific length.
part.array[0];
But how would I do that? Should I create another class in java? I just don't want to put "String" in front of every word in that text file.
I am not totaly sure if I understood what you were trying to do, but from what I understand, you want to implement something similar to an ArrayList..
First let's clarify something. The code example you posted will always result in an ArrayIndexOutOfBoundsException:
part.array[part.size++] = "aardvark";
.....
part.array[part.size++] = "zymurgy";
No matter how big your array is, you'll try to access memory, which is outside of that array.
If you really do not want to use an ArrayList (or any other List), you might want to create your own class which behaves in a similar way..
public class StringList{
public static final int DEFAULT_INITIAL_SIZE = 100;
public static final float DEFAULT_SCALE_FACTOR = 2;
private String[] content;
private float scaleFactor;
private int counter = 0;
public StringList(){
this(DEFAULT_INITIAL_SIZE);
}
public StringList(int initialSize){
this(initialSize, DEFAULT_SCALE_FACTOR);
}
public StringList(int initialSize, float scaleFactor){
this.scaleFactor = scaleFactor;
content = new String[initialSize];
}
public void add(String toAdd){
//check if we ran out of space for new content..
if(counter == content.length){
//create a new array with twice the current arrays size
String[] temp = new String[(int) (content.length * scaleFactor)];
//efficiently copy content from current array to temp
System.arraycopy(content, 0, temp, 0, content.length);
content = temp;
}
content[counter++] = toAdd;
}
public String get(int index){
return content[index];
}
public int size(){
return counter;
}
}
That class should do everything you need..
Here a short example..
StringList stringList = new StringList();
stringList.add("aardvark");
// add more stuff...
stringList.add("zymurgy");
for (int i = 0; i < stringList.size(); i++) {
String someText = stringList.get(i);
// do stuff with your string...
}
So what I'm trying to do here is initialize my strings to an empty string and my ints to 0. The display report is kind of a debugger at the moment, and when I run the program that calls displayReport, it only displays my ints and strings as null. It has to be something in my for loop, but I can't seem to figure out what I am doing wrong.
EDIT: To be clear, I HAVE to use private void initializeString(String[] s) and private void initializeInt(int[] a). And my constructor has these guidelines
public constructor: Initializes arrays holding soft drink name and ID to hold all empty strings (calls intitializeString twice to perform the tasks). Initializes arrays holding starting inventory, final inventory, and the counts of the number of transaction to zero (calls initializeInt three times to perform the tasks).
import java.util.Scanner;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class SoftDrinkInventory {
static final int MAXSIZE = 100; // maximum size of 100
private String[] names; // softdrink names
private String[] ids; // softdrink identifications
private int[] startingInventory; // starting inventory of the softdrinks
private int[] finalInventory; // final inventory of the softdrinks
private int[] transactionCounts; // number of transactions per softdrink
private int trueSize; // total number of softdrinks
/**-----------------------------------------------------------------------
* constructor
*
* Initializes arrays holding soft drink name, ID number to the
* empty string. Initializes starting inventory, final inventory,
* and transaction counts are to zero.
*/
public SoftDrinkInventory() {
initializeString(names);
initializeString(ids);
initializeInt(startingInventory);
initializeInt(finalInventory);
initializeInt(transactionCounts);
}
/**-----------------------------------------------------------------------
* displayReport
*
* Displays a report including soft drink name, ID, starting inventory,
* final inventory, and number of transactions processed.
*/
public void displayReport() {
System.out.printf("%-22s %-16s %-23s %-23s %s %n", "Soft Drink", "ID",
"Starting Inventory", "Final Inventory",
"# transaction");
for(int i = 0; i < 10; i++) {
System.out.printf("%-22s %-16s %-23f %-23f %f %n", names, ids,
startingInventory, finalInventory,
transactionCounts);
}
}
/**-----------------------------------------------------------------------
* initializeInt
*
* Takes an int array parameter and initializes its array values to zero.
* #param a int array
*/
private void initializeInt(int[] a) {
a = new int[MAXSIZE];
for(int i = 0; i < a.length; i++) {
a[i] = 0;
}
}
/**-----------------------------------------------------------------------
* initializeString
*
* Takes a String array parameter and initializes its array values to
* the empty string.
* #param s string array
*/
private void initializeString(String[] s) {
s = new String[MAXSIZE];
for(int i = 0; i < s.length; i++) {
s[i] = "";
}
}
}
Java uses pass by value. This means the references you pass in are being modified, not the originals. The simplest solution is to return the array you want.
names = initialiseString(100);
However, a better approach is to use a List of Objects like
private final List<Item> items = new ArrayList<>();
// to add
items.add(new Item("name", "id", 1234, 10, 1224));
// you can add any size 0 up to 2 billion.
int actualSize = items.size();
class Item {
private String name; // softdrink name
private String id; // softdrink identification
private int startingInventory; // starting inventory of the softdrink
private int finalInventory; // final inventory of the softdrink
private int transactionCount;
}
You can't overwrite a reference, that was passed as an argument to a method, inside that method. When you're doing a = new int[MAXSIZE]; you are creating an array that is visible only to that method. What you need to do is return the created array. You might consider doing something like this:
private int[] initializeInt(int size) {
...
}
...
startingInventory = initializeInt(MAXSIZE);
Because you are initializing the arrays local to those initializing methods. Instead of passing argument to the methods, simply create and initialize a new array within the methods and return those arrays to respective instance variables.
For example change your initializeString(String[]) to public String[] initializeString() and within this method write.:
String[] names = new String[MAXSIZE];
for(int i = 0; i < names.length; i++) { names[i] = "";} return names;
And then call this method within your constructor as follows
names = initializeString();
There are Java functions that take an array as a parameter, put data in the array, and it is available to you.
For example:
BufferedReader.read(char[] cbuf, int off, int len)
However, you must first create the array, and it just fills it. So you must first do this before calling that function:
char[] cbuf = new char[100];
Since your methods are initializing arrays in the same class, you can just do Vishal K said, and not pass the arrays to the methods. In situations where you are calling methods elsewhere, you can pass objects as parameters to methods in other classes as long as you create the object first. The callee can use the passed reference to modify your object.
Of course there are better ways to do this (such as using List of Objects, as suggested by Peter Lawrey), but since this is in the specs you have, you can try this: when you declare your arrays, also allocate memory for them :
private String[] names = new String[MAXSIZE]; // softdrink names
private String[] ids = new String[MAXSIZE]; // softdrink identifications
private int[] startingInventory = new int[MAXSIZE]; // starting inventory of the softdrinks
private int[] finalInventory = new int[MAXSIZE]; // final inventory of the softdrinks
private int[] transactionCounts = new int[MAXSIZE]; // number of transactions per softdrink
Then, in your functions, you can simply assign values to 0 and empty String:
private void initializeInt(int[] a) {
for(int i = 0; i < a.length; i++) {
a[i] = 0;
}
}
and
private void initializeString(String[] s) {
for(int i = 0; i < s.length; i++) {
s[i] = "";
}
}
Please note that you have an error in your displayReport() function too. You are using %f to display int values (%f is used for floats). Instead, change it to %d. Also, in your for loop, you are not actually looping through your arrays. Just use i as an index when iterating. Another thing is that you are displaying only 10 entries, whereas your MAXSIZE, which you use to initialise arrays is 100, so if you want to display all array elements, change 10 to MAXSIZE:
public void displayReport() {
System.out.printf("%-22s %-16s %-23s %-23s %s %n", "Soft Drink", "ID",
"Starting Inventory", "Final Inventory",
"# transaction");
for(int i = 0; i < MAXSIZE; i++) {
//change "%-22s %-16s %-23f %-23f %f %n" to the below
//and names etc. to names[i] etc.
System.out.printf("%-22s %-16s %-23d %-23d %d %n", names[i], ids[i],
startingInventory[i], finalInventory[i],
transactionCounts[i]);
}
}