error : java.lang.ArrayIndexOutOfBoundsException on Android - java

I have this code :
indexOfChromosomes : 48
indexOfGens : 20
double Truncation;
double Crossover;
double Mutation;
int Generation;
private Context context;
int indexOfChromosomes;
int indexOfGens;
int gensNumber;
int chromosomesNumber;
public AdapterDB(int Bits, double Truncation, double Crossover, double Mutation, int Chromosomes, int Generation, Context ctx)
{
this.indexOfGens = Bits;
this.Truncation = Truncation;
this.Crossover = Crossover;
this.Mutation = Mutation;
this.indexOfChromosomes = Chromosomes;
this.Generation = Generation;
this.context = ctx;
DBHelper = new DatabaseHelper (context);
}
String [][] population = new String[indexOfChromosomes][indexOfGens];
public void generateChromosome()
{
for(chromosomesNumber = 0; chromosomesNumber < indexOfChromosomes ; chromosomesNumber++)
{
int o = 0;
for(gensNumber = 0; gensNumber < 12 ; gensNumber++)
{
Cursor l = db.rawQuery("SELECT _id, key_foodstuff, key_calorie, key_carbohydrate, key_fat, key_protein FROM (food INNER JOIN categories ON food.key_nocategory = categories.nocategories) WHERE key_type='primary' AND _id!=164 AND (key_carbohydrate!=0 OR key_protein!=0 OR key_fat!=0) ORDER BY RANDOM() LIMIT 1", null);
if((l.moveToFirst()) && (l!=null))
{
if (o == indexOfGens)
{
gensNumber = 0;
sumOfCarbohydrateMor = 0;
sumOfFatMor = 0;
sumOfProteinMor = 0;
sumOfCalorieMor = 0;
o = 0;
}
population[chromosomesNumber][gensNumber] = l.getString(0);
morning_food[k] = l.getString(3);
sumOfCarbohydrateMor = sumOfCarbohydrateMor + Double.parseDouble(morning_food[k]);
morning_food[f] = l.getString(4);
sumOfFatMor = sumOfFatMor + Double.parseDouble(morning_food[f]);
morning_food[p] = l.getString(5);
sumOfProteinMor = sumOfProteinMor + Double.parseDouble(morning_food[p]);
morning_food[c] = l.getString(2);
sumOfCalorieMor = sumOfCalorieMor + Double.parseDouble(morning_food[c]);
if (((sumOfCarbohydrateMor >= (morning_car-(morning_car*0.2))) && (sumOfCarbohydrateMor <= morning_cal*1.1)) && ((sumOfProteinMor >= (morning_pro-(morning_pro*0.2))) && (sumOfProteinMor <= morning_pro*1.1)) && ((sumOfFatMor >= (morning_fat-(morning_fat*0.2))) && (sumOfFatMor <= morning_fat*1.1)))
//if((sumOfCarbohydrateMor > (morning_car*0.6)) && (sumOfProteinMor > (morning_pro*0.7)) && (sumOfFatMor > (morning_fat*0.8)))
{
Log.e("lala", "lalala");
break;
}
if ((sumOfCarbohydrateMor > (morning_car*1.1)) || (sumOfProteinMor > (morning_pro*1.1)) || (sumOfFatMor > (morning_fat*1.1)) || (sumOfCalorieMor > (morning_cal*1.1))
{
morning_food[k] = l.getString(3);
sumOfCarbohydrateMor = sumOfCarbohydrateMor - Double.parseDouble(morning_food[k]);
morning_food[f] = l.getString(4);
sumOfFatMor = sumOfFatMor - Double.parseDouble(morning_food[f]);
morning_food[p] = l.getString(5);
sumOfProteinMor = sumOfProteinMor - Double.parseDouble(morning_food[p]);
morning_food[c] = l.getString(2);
sumOfCalorieMor = sumOfCalorieMor - Double.parseDouble(morning_food[c]);
gensNumber--;
o++;
}
}
}
and it error in line : 48
The error says that : java.lang.ArrayIndexOutOfBoundsException
any idea? Thx u

Try setting
population = new String[indexOfChromosomes][indexOfGens];
inside your adapterDB.
It looks like when you are initializing populatioin, indexOfChromosomes and indexOfGens are not initialized yet, so you are creating an array of size 0. So when you call
population[chromosomesNumber][gensNumber]
you get java.lang.ArrayIndexOutOfBoundsException

It's because you define the population string outside a function, without initializing the indexOfChromosomes to 48 and the indexOfGens to 20. Try defining the population at the top and setting it to something new in the adapter, AFTER you've set your variables. Something like this:
double Truncation;
double Crossover;
double Mutation;
int Generation;
private Context context;
int indexOfChromosomes;
int indexOfGens;
int gensNumber;
int chromosomesNumber;
String [][] population;
public AdapterDB(int Bits, double Truncation, double Crossover, double Mutation, int Chromosomes, int Generation, Context ctx)
{
this.indexOfGens = Bits;
this.Truncation = Truncation;
this.Crossover = Crossover;
this.Mutation = Mutation;
this.indexOfChromosomes = Chromosomes;
this.Generation = Generation;
this.context = ctx;
DBHelper = new DatabaseHelper (context);
//Create population after initializing variables.
population = new String[indexOfChromosomes][indexOfGens];
}

This is your problem:
String [][] population = new String[indexOfChromosomes][indexOfGens];
This occurs outside your constructor, and is therefore executed before your constructor, when indexOfChromosomes and indexOfGens are both still 0. Put the initialization inside your constructor. Here's a simpler example showing the same problem:
public class Test {
private int size;
public Test(int size) {
this.size = size;
}
private String[] array = new String[size];
public static void main(String[] args) {
Test t = new Test(5);
System.out.println(t.array.length);
}
}
And the fixed version:
public class Test {
private int size;
private String[] array;
public Test(int size) {
this.size = size;
array = new String[size];
}
public static void main(String[] args) {
Test t = new Test(5);
System.out.println(t.array.length);
}
}
Note that the positioning of the variable declaration with respect to the constructor makes no difference to the execution flow.
EDIT: As for why it's now looping forever - in the middle of your code you have:
if (o == indexOfGens)
{
gensNumber = 0;
...
}
which will reset the inner loop back to (nearly) the start (not quite the start, as gensNumber will be incremented at the end of the loop body, before the start of the next iteration).
It's not at all clear what you're trying to do, but I suspect that's not helping.
I'd also encourage you to use local variables wherever possible - it's very unusual to use an instance variable as a loop counter, for example.
Finally, I'd encourage you to break up your large method into smaller ones for readability.

Related

GC overhead limit exceeded while training OpenNLP's NameFinderME

I want to get probability score for the extracted names using NameFinderME, but using the provided model gives very bad probabilities using the probs function.
For example, "Scott F. Fitzgerald" gets a score around 0.5 (averaging log probabilities, and taking an exponent), while "North Japan" and "Executive Vice President, Corporate Relations and Chief Philanthropy Officer" both get a score higher than 0.9...
I have more than 2 million first names, and another 2 million last names (with their frequency counts) And I want to synthetically create a huge dataset from outer multiplication of the first names X middle names (using the first names pool) X last names.
The problem is, I don't even get to go over all the last names once (even when discarding freq counts and only using each name only once) before I get a GC overhead limit exceeded exception...
I'm implementing a ObjectStream and give it to the train function:
public class OpenNLPNameStream implements ObjectStream<NameSample> {
private List<Map<String, Object>> firstNames = null;
private List<Map<String, Object>> lastNames = null;
private int firstNameIdx = 0;
private int firstNameCountIdx = 0;
private int middleNameIdx = 0;
private int middleNameCountIdx = 0;
private int lastNameIdx = 0;
private int lastNameCountIdx = 0;
private int firstNameMaxCount = 0;
private int middleNameMaxCount = 0;
private int lastNameMaxCount = 0;
private int firstNameKBSize = 0;
private int lastNameKBSize = 0;
Span span[] = new Span[1];
String fullName[] = new String[3];
String partialName[] = new String[2];
private void increaseFirstNameCountIdx()
{
firstNameCountIdx++;
if (firstNameCountIdx == firstNameMaxCount) {
firstNameIdx++;
if (firstNameIdx == firstNameKBSize)
return; //no need to update anything - this is the end of the run...
firstNameMaxCount = getFirstNameMaxCount(firstNameIdx);
firstNameCountIdx = 0;
}
}
private void increaseMiddleNameCountIdx()
{
lastNameCountIdx++;
if (middleNameCountIdx == middleNameMaxCount) {
if (middleNameIdx == firstNameKBSize) {
resetMiddleNameIdx();
increaseFirstNameCountIdx();
} else {
middleNameMaxCount = getMiddleNameMaxCount(middleNameIdx);
middleNameCountIdx = 0;
}
}
}
private void increaseLastNameCountIdx()
{
lastNameCountIdx++;
if (lastNameCountIdx == lastNameMaxCount) {
lastNameIdx++;
if (lastNameIdx == lastNameKBSize) {
resetLastNameIdx();
increaseMiddleNameCountIdx();
}
else {
lastNameMaxCount = getLastNameMaxCount(lastNameIdx);
lastNameCountIdx = 0;
}
}
}
private void resetLastNameIdx()
{
lastNameIdx = 0;
lastNameMaxCount = getLastNameMaxCount(0);
lastNameCountIdx = 0;
}
private void resetMiddleNameIdx()
{
middleNameIdx = 0;
middleNameMaxCount = getMiddleNameMaxCount(0);
middleNameCountIdx = 0;
}
private int getFirstNameMaxCount(int i)
{
return 1; //compromised on using just
//String occurences = (String) firstNames.get(i).get("occurences");
//return Integer.parseInt(occurences);
}
private int getMiddleNameMaxCount(int i)
{
return 3; //compromised on using just
//String occurences = (String) firstNames.get(i).get("occurences");
//return Integer.parseInt(occurences);
}
private int getLastNameMaxCount(int i)
{
return 1;
//String occurences = (String) lastNames.get(i).get("occurences");
//return Integer.parseInt(occurences);
}
#Override
public NameSample read() throws IOException {
if (firstNames == null) {
firstNames = CSVFileTools.readFileFromInputStream("namep_first_name_idf.csv", new ClassPathResource("namep_first_name_idf.csv").getInputStream());
firstNameKBSize = firstNames.size();
firstNameMaxCount = getFirstNameMaxCount(0);
middleNameMaxCount = getFirstNameMaxCount(0);
}
if (lastNames == null) {
lastNames = CSVFileTools.readFileFromInputStream("namep_last_name_idf.csv",new ClassPathResource("namep_last_name_idf.csv").getInputStream());
lastNameKBSize = lastNames.size();
lastNameMaxCount = getLastNameMaxCount(0);
}
increaseLastNameCountIdx();;
if (firstNameIdx == firstNameKBSize)
return null; //we've finished iterating over all permutations!
String [] sentence;
if (firstNameCountIdx < firstNameMaxCount / 3)
{
span[0] = new Span(0,2,"Name");
sentence = partialName;
sentence[0] = (String)firstNames.get(firstNameIdx).get("first_name");
sentence[1] = (String)lastNames.get(lastNameIdx).get("last_name");
}
else
{
span[0] = new Span(0,3,"name");
sentence = fullName;
sentence[0] = (String)firstNames.get(firstNameIdx).get("first_name");
sentence[2] = (String)lastNames.get(lastNameIdx).get("last_name");
if (firstNameCountIdx < 2*firstNameCountIdx/3) {
sentence[1] = (String)firstNames.get(middleNameIdx).get("first_name");
}
else {
sentence[1] = ((String)firstNames.get(middleNameIdx).get("first_name")).substring(0,1) + ".";
}
}
return new NameSample(sentence,span,true);
}
#Override
public void reset() throws IOException, UnsupportedOperationException {
firstNameIdx = 0;
firstNameCountIdx = 0;
middleNameIdx = 0;
middleNameCountIdx = 0;
lastNameIdx = 0;
lastNameCountIdx = 0;
firstNameMaxCount = 0;
middleNameMaxCount = 0;
lastNameMaxCount = 0;
}
#Override
public void close() throws IOException {
reset();
firstNames = null;
lastNames = null;
}
}
And
TokenNameFinderModel model = NameFinderME.train("en","person",new OpenNLPNameStream(),TrainingParameters.defaultParams(),new TokenNameFinderFactory());
model.serialize(new FileOutputStream("trainedNames.bin",false));
I get the following error after a few minutes of running:
java.lang.OutOfMemoryError: GC overhead limit exceeded
at opennlp.tools.util.featuregen.WindowFeatureGenerator.createFeatures(WindowFeatureGenerator.java:112)
at opennlp.tools.util.featuregen.AggregatedFeatureGenerator.createFeatures(AggregatedFeatureGenerator.java:79)
at opennlp.tools.util.featuregen.CachedFeatureGenerator.createFeatures(CachedFeatureGenerator.java:69)
at opennlp.tools.namefind.DefaultNameContextGenerator.getContext(DefaultNameContextGenerator.java:118)
at opennlp.tools.namefind.DefaultNameContextGenerator.getContext(DefaultNameContextGenerator.java:37)
at opennlp.tools.namefind.NameFinderEventStream.generateEvents(NameFinderEventStream.java:113)
at opennlp.tools.namefind.NameFinderEventStream.createEvents(NameFinderEventStream.java:137)
at opennlp.tools.namefind.NameFinderEventStream.createEvents(NameFinderEventStream.java:36)
at opennlp.tools.util.AbstractEventStream.read(AbstractEventStream.java:62)
at opennlp.tools.util.AbstractEventStream.read(AbstractEventStream.java:27)
at opennlp.tools.util.AbstractObjectStream.read(AbstractObjectStream.java:32)
at opennlp.tools.ml.model.HashSumEventStream.read(HashSumEventStream.java:46)
at opennlp.tools.ml.model.HashSumEventStream.read(HashSumEventStream.java:29)
at opennlp.tools.ml.model.TwoPassDataIndexer.computeEventCounts(TwoPassDataIndexer.java:130)
at opennlp.tools.ml.model.TwoPassDataIndexer.<init>(TwoPassDataIndexer.java:83)
at opennlp.tools.ml.AbstractEventTrainer.getDataIndexer(AbstractEventTrainer.java:74)
at opennlp.tools.ml.AbstractEventTrainer.train(AbstractEventTrainer.java:91)
at opennlp.tools.namefind.NameFinderME.train(NameFinderME.java:337)
Edit: After increasing the memory of the JVM to 8GB, I still don't get past the first 2 million last names, but now the Exception is:
java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.resize(HashMap.java:703)
at java.util.HashMap.putVal(HashMap.java:662)
at java.util.HashMap.put(HashMap.java:611)
at opennlp.tools.ml.model.AbstractDataIndexer.update(AbstractDataIndexer.java:141)
at opennlp.tools.ml.model.TwoPassDataIndexer.computeEventCounts(TwoPassDataIndexer.java:134)
at opennlp.tools.ml.model.TwoPassDataIndexer.<init>(TwoPassDataIndexer.java:83)
at opennlp.tools.ml.AbstractEventTrainer.getDataIndexer(AbstractEventTrainer.java:74)
at opennlp.tools.ml.AbstractEventTrainer.train(AbstractEventTrainer.java:91)
at opennlp.tools.namefind.NameFinderME.train(NameFinderME.java:337)
It seems the problem stems from the fact I'm creating a new NameSample along with new Spans and Strings at every read call... But I can't reuse Spans or NameSamples, since they're immutables.
Should I just write my own language model, is there a better Java library for doing this sort of thing (I'm only interested in getting the probability the extracted text is actually a name) are there parameters I should tweak for the model I'm training?
Any advice would be appreciated.

How to extend a class array/ call class array attributes after extend a class?

for a larg-DB based dynamically-multiple-area-menu, I created a class MenuPoint:
class MenuPoint{
public int areaId;
public int preID;
public String name;
public String desc;
public String stepInImg = "bsp.img";
public String stepOutImg = "bsp.img";
public String detailedForm = "bsp.fxml";
public String detailedImg = "bsp.img";
public String [] additionalOptionForm = new String[0];
public String [] additionalOptionName = new String[0];
public String [] additionalOptionImg = new String[0];}
and initialised it as an 0-length array in my main class: MenuController
public MenuPoint [] menuItem = new MenuPoint[0];
I use a API call to get my DB stored information by initialisation of MenuController.
I store the results by using the following code:
int dataStructlength = 12;
String[] exampleApiResultKeys = new String[dataStructlength];
exampleApiResultKeys[0] = "SITE_NUMBER";
exampleApiResultKeys[1] = "SITE_DESC";
exampleApiResultKeys[2] = "SITE_NUMBER_EXT";
exampleApiResultKeys[3] = "CELL_NUMBER";
exampleApiResultKeys[4] = "CELL_DESC";
exampleApiResultKeys[5] = "CELL_TYPE";
exampleApiResultKeys[6] = "MACHINE_GROUP_NUMBER";
exampleApiResultKeys[7] = "MACHINE_GROUP_DESC";
exampleApiResultKeys[8] = "MACHINE_GROUP_TYPE";
exampleApiResultKeys[9] = "STATION_NUMBER";
exampleApiResultKeys[10] = "STATION_DESC";
exampleApiResultKeys[11] = "STATION_TYPE";
exampleApiController.test_mdataGetMachineAssetStructure(exampleApiFilter, exampleApiResultKeys);
for(int i = 0; exampleApiController.resultValues.value != null && i < exampleApiController.resultValues.value.length/12; i++)
{
boolean isUseless = false;
for(int a = 0; a < dataStructlength; a ++)
if(true == exampleApiController.resultValues.value[i*dataStructlength+a].trim().isEmpty())
isUseless = true;
if(!isUseless)
{
int preId= -1;
if("M".equals(exampleApiController.resultValues.value[i*12+5]))
{
if(giveItemId(0, preId, exampleApiController.resultValues.value[i*12]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12]);
else
preId = addMenuItem(0, preId, exampleApiController.resultValues.value[i*12], exampleApiController.resultValues.value[i*12+1], "bsp.form");
}
if("M".equals(exampleApiController.resultValues.value[i*12+5]))
{
if(giveItemId(1, preId, exampleApiController.resultValues.value[i*12+3]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12+3]);
else
preId = addMenuItem(1, preId, exampleApiController.resultValues.value[i*12+3], exampleApiController.resultValues.value[i*12+4], "bsp.form");
}
if("M".equals(exampleApiController.resultValues.value[i*12+8]))
{
if(giveItemId(2, preId, exampleApiController.resultValues.value[i*12+6]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12+6]);
else
preId = addMenuItem(2, preId, exampleApiController.resultValues.value[i*12+6], exampleApiController.resultValues.value[i*12+7], "bsp.form");
}
if("M".equals(exampleApiController.resultValues.value[i*12+11]))
{
if(giveItemId(3, preId, exampleApiController.resultValues.value[i*12+9]) >= 0)
preId = giveItemId(0, preId, exampleApiController.resultValues.value[i*12+9]);
else
preId = addMenuItem(3, preId, exampleApiController.resultValues.value[i*12+9], exampleApiController.resultValues.value[i*12+10], "bsp.form");
}
}
giveItemId:
public int giveItemId(int areaId_temp, int preId_temp, String name_temp)
{
for(int i = 0; i < menuItem.length; i++)
{
if(menuItem[i].areaId == areaId_temp && menuItem[i].name.equals(name_temp) && menuItem[i].preID == preId_temp)
return i;
}
return -1;
}
addMenuItem:
public int addMenuItem(int areaId_temp, int preId_temp, String name_temp, String desc_temp, String form_temp)
{
Object newArray1 = Array.newInstance(menuItem.getClass().getComponentType(), Array.getLength(menuItem)+1); // +1 Arrayfeld
System.arraycopy(menuItem, 0, newArray1, 0, Array.getLength(menuItem));
menuItem = (MenuPoint[]) newArray1; // expend but missing attributes
menuItem[menuItem.length-1].areaId = areaId_temp;
menuItem[menuItem.length-1].preID = preId_temp;
menuItem[menuItem.length-1].name = name_temp;
menuItem[menuItem.length-1].desc = desc_temp;
menuItem[menuItem.length-1].detailedForm = form_temp;
return menuItem.length-1;
}
I found out that menuItem donsĀ“t carry any attributes after expending it.
Do I have to create "new" Instances of MenuPoint to make it work?
Is it even possible to expend a class-array without loosing attributes or their values?
It shoud, because in the end menuItem is just a pointer-array, pointing on multiple workstorage-addresses, aren't it?
Thank you guys for any tips or better concept you can give me. (I know this class-concept is silly but I have no idea for a better one)
And please excuse my bad grammar.
You create a new array in method addMenuItem which is then populated with the members from the existing menuItem, but the element at index (new) length - 1 isn't initialized:
menuItem[menuItem.length-1] = new MenuPoint();
You should have gotten a NullPointerException when trying to set the fields.
All this usage of java.lang.reflect.Array is rather contrived. There are simpler ways to achieve this. Here is a simplified versio of addMenuItem
public int addMenuItem(int areaId, String name){
MenuPoint[] newMenuItem = new MenuPoint[menuItem.length + 1];
System.arraycopy(menuItem, 0, newMenuITem, 0, menuItem.length);
menuItem = newMenuItem;
menuItem[menuItem.length-1] = new MenuPoint();
menuItem[menuItem.length-1].areaId = areaId;
menuItem[menuItem.length-1].name = name;
return menuItem.length; // Why -1 ?
}
But, above all, do use a List<MenuPoint>.
For the answer of your question Do I have to create "new" Instances of MenuPoint to make it work?
Yes
From your code snippets you need to initialize MenuPoint class object to store its values to the array menuItem.
Initialize your array element with below line
menuItem[menuItem.length-1] = new MenuPoint();
Place above line after copying your array by menuItem = (MenuPoint[]) newArray1;
Without initialization there is NullPointerException exception for setting values to null object.
There are some better ways to maintain list of object using ArrayList class.
To use ArrayList you need following code change
public List<MenuPoint> menuItem = new ArrayList<MenuPoint>; //Initialize list
Your Function will be
public int addMenuItem(int areaId_temp, int preId_temp, String name_temp, String desc_temp, String form_temp)
{
MenuPoint menuPoint = new MenuPoint();
menuPoint.areaId = areaId_temp;
menuPoint.preID = preId_temp;
menuPoint.name = name_temp;
menuPoint.desc = desc_temp;
menuPoint.detailedForm = form_temp;
menuItem.add(menuPoint);
return menuItem.size()-1;
}
I think this is easy than using reflection with array.

Calling a constructor in another constructor (and getting the modified variables from cons.1)

I searched the web but did not find my answers. Here is my question.
The goal here is to use my verifications (if codeForme<0 || codeforme>9)... etc only in my first constructor, because my two other constructors are calling the first one.
But, when i enter for example codeforme = 20 in my second constructor, it is not modified as it should be after running the first constructor. I know the problem is probably from the this.codeForme = forme because it takes my parameter's forme instead of the codeForme from the first.
There should be an easy way, thanks!
Here is my code so far:
public class carteMere {
// variable(s) de classe s'il y a lieu
private static int identifiant = 0;
// variable(s) d'instance s'il y a lieu
private String marque;
private int codeForme = 0;
private int capaciteMaxMemoire = 8;
private int memoireInstalle = 0;
private int codeCarte;
// constructeur(s) s'il y a lieu
public carteMere( String marque,
int codeForme,
int capaciteMaxMemoire,
int memoireInstalle) {
this.marque = marque;
this.identifiant = identifiant+1;
this.codeCarte=this.identifiant;
if(codeForme < 0 || codeForme > 9){
codeForme = 0;
}
if(capaciteMaxMemoire<=0){
capaciteMaxMemoire = 8;
}
if(memoireInstalle < 0){
memoireInstalle = 0;
}else if (memoireInstalle> capaciteMaxMemoire){
memoireInstalle = capaciteMaxMemoire;
}
codeForme = codeForme;
capaciteMaxMemoire = capaciteMaxMemoire;
memoireInstalle = memoireInstalle;
}
public carteMere(int forme, int capaciteMax, int memoireInstalle){
this("ASUS", forme, capaciteMax, memoireInstalle);
this.codeForme = forme;
this.capaciteMaxMemoire = capaciteMax;
this.memoireInstalle = memoireInstalle;
this.codeCarte=this.identifiant;
}
public carteMere(int codeForme, int memoireInstalle){
this(codeForme, 8, memoireInstalle);
this.codeForme=codeForme;
this.memoireInstalle=memoireInstalle;
this.identifiant = identifiant;
this.codeCarte=this.identifiant;
}
Edit:
If I do:
carte1 = new carteMere(10, 8);
Then I inspect carte1, the codeForme is 10, and it should be 0 because it should have been modifed in the 1st constructor.
Use this to qualify your instance variables as you have done for marque, indentifiant, and codeCarte. Also use else on your ifs to assign the variable the normal value if not outside the validation range. E.g. for codeForme:
if(codeForme < 0 || codeForme > 9) {
this.codeForme = 0;
}
else {
this.codeForme = codeForme;
}
And similarly for capaciteMaxMemoire and memoireInstalle.

Method Not Displaying Properly

The method "aboveAverage" in the following code is not displaying correctly and I've tried everything I can. Could someone please explain what's going wrong?
My code:
import java.util.*;
public class DailyCatch
{
private int fishermanID, fisherID;
private String dateOfSample, date;
private double[] fishCaught = new double[10];
private int currWeight = 0;
private String summary;
private double average;
private int aboveAvg;
public DailyCatch() { }
public DailyCatch (int fishermanID, String dateOfSample)
{
fisherID = fishermanID;
date = dateOfSample;
}
public DailyCatch (int fishermanID, String dateOfSample, String weight)
{
this(fishermanID, dateOfSample);
readWeights(weight);
}
public void addFish(double weight)
{
if (currWeight > 10)
{
// array full
}
else
{
fishCaught[currWeight] = weight;
currWeight += 1; // update current index of array
}
}
private void readWeights(String weightsAsString)
{
String[] weightsRead = weightsAsString.split("\\s+");
for (int i = 0; i < weightsRead.length; i++)
{
this.addFish(Double.parseDouble(weightsRead[i]));
}
}
public String toString()
{
return "Fisherman ID: " + fisherID + "\nDate:" + date + "\nFish Caught with Weights: " + Arrays.toString(fishCaught);
}
public void printWeights()
{
for (int i = 0; i < fishCaught.length; i++)
{
System.out.println(fishCaught[i]);
}
}
public double averageWeight()
{
double sum = 0;
double count = 0;
for (int i = 0; i < fishCaught.length; i++)
{
if (fishCaught[i] != 0)
{
sum += fishCaught[i];
count += 1;
average = sum/count;
}
}
return average;
}
public String getSummary()
{ int storyTellerCount = 0;
int keeperCount = 0;
int throwBackCount = 0;
for (int i = 0; i < fishCaught.length; i++)
{
if (fishCaught[i] > 5)
{
storyTellerCount++;
}
else if (fishCaught[i] >=1 && fishCaught[i] <= 5)
{
keeperCount++;
}
else if (fishCaught[i] < 1 && fishCaught[i] > 0)
{
throwBackCount++;
}
} String summary = ("\nStoryteller - " + storyTellerCount+ "\nKeeper - " + keeperCount + "\nThrowback - " + throwBackCount);
return summary;
}
public int aboveAverage()
{
int greatAvgCount = 0;
for (int i = 0; i < fishCaught.length; i++)
{
if (fishCaught[i] > average)
{
aboveAvg = greatAvgCount++;
}
}
return aboveAvg;
}
}
Test Code:
public class BigBass
{
public static void main (String[]args)
{
//Part 1
DailyCatch monday1 = new DailyCatch(32, "4/1/2013", "4.1 5.5 2.3 0.5 4.8 1.5");
System.out.println(monday1);
//Part 2
DailyCatch monday2 = new DailyCatch(44, "4/1/2013");
System.out.println(monday2);
monday2.addFish(2.1);
monday2.addFish(4.2);
System.out.println(monday2);
//Part 3
System.out.println("\n\nSUMMARY OF FISHERMAN 32");
System.out.println(monday1.getSummary());
//Part 4
double avg = monday1.averageWeight();
System.out.printf("\nThere are %d fish above the average weight of %.1f.", monday1.aboveAverage(), avg);
}
}
I just need to get Part 4 to work here. What it does is return that there have been 2 fish caught that are above average when I know it should be 3. The average is 3.1.
A simple mistake.
public int aboveAverage() {
int greatAvgCount = 0;
for (int i = 0; i < fishCaught.length; i++) {
if (fishCaught[i] > 3.1) {
greatAvgCount++; // no 'return'
}
}
return greatAvgCount;
}
if (fishCaught[i] > 3.1)
{
return greatAvgCount++;
}
First try : 4.1 > 3.1
true
returns 0 ++ which is 0 basically
You can increment the counter inside the loop and keep the return statement for the end only.
try
public int aboveAverage() {
int greatAvgCount = 0;
for (int i = 0; i < fishCaught.length; i++) {
if (fishCaught[i] > 3.1) {
greatAvgCount++;
}
}
return greatAvgCount;
}
This line is your problem,
return greatAvgCount++;
you are incrimenting greatAvgCount then returning its initial value, there should be no "return" on this line
The aboveAverage method should be
public int aboveAverage()
{
int greatAvgCount = 0;
for (int i = 0; i < fishCaught.length; i++)
{
if (fishCaught[i] > 3.1)
{
greatAvgCount++;
}
}
return greatAvgCount;
}
Also, you may just be doing it for debug, in which case fair enough, but hardcoding the "average" as 3.1 is generally considered bad practice. If you want average to be always 3.1 (i.e. its a global average that you've looked up from a book then its more usual to declare a static variable called double AVERAGE=3.1 and then use that where ever average is required, that way if the "book value" changes you only need to change average in one place in your code. If average is calculated from your data obviously you should use the calculated value.
Also not directly related to your problem but why are you using an array for your caught fish with a predefined maximum of 10. If you used an ArrayList you could add to it as you saw fit and it would auto expand to accommodate
private double[] fishCaught = new double[10];
becomes
private ArrayList<Double> fishCaught = new ArrayList<Double>();

Java - NullPointerException in a method

I'm writing a program that could manage universitary students with courses and subjects. The problem of the class I'm showing you is that when the method
public CorsoStudi(String unNomeCorso, ArrayList unElencoMaterie, int unIdCorso)
is called it throws a NullPointerException at line elencoEsamiDati.add(q);. So, probably the problem is with this line and the line after this:
EsameDato q = new EsameDato(unElencoMaterie.get(contatore), 0);
Eclipse doesn't advice error on writing code.
Creatore.java
import java.util.ArrayList;
import java.util.Scanner;
public class Creatore {
int counterStudenti = 0;
int counterMaterie = 0;
int counterCorsi = 0;
//int counterEsami = 0;
ArrayList<Studente> listaStudenti = new ArrayList<Studente>();
ArrayList<Materia> listaMaterie = new ArrayList<Materia>();
ArrayList<CorsoStudi> listaCorsi = new ArrayList<CorsoStudi>();
//ArrayList<EsameDato> listaEsami = new ArrayList<EsameDato>();
public void iscriviStudente(String nomeStudente, String cognomeStudente, CorsoStudi corsoStudente){
listaStudenti.add(new Studente(nomeStudente, cognomeStudente, counterStudenti, corsoStudente));
counterStudenti++;
}
public void reimmatricolaStudente(int unaMatricola, int unIdCorso){
int c = 0;
CorsoStudi unCorso = null;
for(c = 0; c < listaCorsi.size(); c++){
if(listaCorsi.get(c).getIdCorso() == unIdCorso)
unCorso = listaCorsi.get(c);
}
int contatore = 0;
for(contatore = 0; contatore < listaStudenti.size(); contatore++)
if(listaStudenti.get(contatore).getMatricola() == unaMatricola){
iscriviStudente(listaStudenti.get(contatore).getNome(), listaStudenti.get(contatore).getCognome(), unCorso);
rimuoviStudente(unaMatricola);
};
}
public void rimuoviStudente(int matricola){
int contatore;
for(contatore = 0; contatore < listaStudenti.size(); contatore++){
if(listaStudenti.get(contatore).getMatricola() == matricola)
listaStudenti.remove(contatore);
}
}
public Materia creaMateria(String nomeMateria, int crediti){
listaMaterie.add(new Materia( nomeMateria, crediti, counterMaterie));
counterMaterie++;
return listaMaterie.get(counterMaterie - 1);
}
public void creaCorsoStudi(String nomeCorso, ArrayList<Materia> materieCorso){
CorsoStudi q = new CorsoStudi( nomeCorso, materieCorso, counterCorsi);
listaCorsi.add(q);
counterCorsi++;
}
public ArrayList<Studente> cercaStudente(int opzione, String pattern){
int contatore = 0;
ArrayList<Studente> listaRicercati = new ArrayList<Studente>();
//opzione 1 = ricerca per nome
if(opzione == 1)
for(contatore = 0; contatore < listaStudenti.size(); contatore++){
if(listaStudenti.get(contatore).getNome().equalsIgnoreCase(pattern))
listaRicercati.add(listaStudenti.get(contatore));
};
//opzione 2 = ricerca per cognome
if(opzione == 2)
for(contatore = 0; contatore < listaStudenti.size(); contatore++){
if(listaStudenti.get(contatore).getCognome().equalsIgnoreCase(pattern))
listaRicercati.add(listaStudenti.get(contatore));
};
//opzione 3 = ricerca per matricola
if(opzione == 3)
for(contatore = 0; contatore < listaStudenti.size(); contatore++){
if(listaStudenti.get(contatore).getMatricola() == Integer.parseInt(pattern))
listaRicercati.add(listaStudenti.get(contatore));
};
//opzione 4 = ricerca per corsoStudi
if(opzione == 4)
for(contatore = 0; contatore < listaStudenti.size(); contatore++){
if(listaStudenti.get(contatore).getCorsoStudi().getIdCorso() == Integer.parseInt(pattern))
listaRicercati.add(listaStudenti.get(contatore));
};
return listaRicercati;
}
public Materia materiaDaId(int id){
int c = 0;
Materia materiaDaRitornare = null;
for(c = 0; c < listaMaterie.size(); c++){
if(listaMaterie.get(c).getIdMateria() == id)
materiaDaRitornare = listaMaterie.get(c);
}
return materiaDaRitornare;
}
}
CorsoStudi.java
import java.util.ArrayList;
import java.util.Scanner;
public class CorsoStudi {
private String nomeCorso;
private int idCorso;
private ArrayList<Materia> elencoMaterie;
private ArrayList<EsameDato> elencoEsamiDati;
public CorsoStudi(String unNomeCorso, ArrayList<Materia> unElencoMaterie, int unIdCorso){
nomeCorso = unNomeCorso;
elencoMaterie = unElencoMaterie;
idCorso = unIdCorso;
int contatore = 0;
//EsameDato q = null;
for(contatore = 0; contatore < unElencoMaterie.size(); contatore++){
EsameDato q = new EsameDato(unElencoMaterie.get(contatore), 0);
elencoEsamiDati.add(q);
};
}
public String getNomeCorso(){
return nomeCorso;
}
public int getIdCorso(){
return idCorso;
}
public ArrayList<Materia> getElencoMaterie(){
return elencoMaterie;
}
public ArrayList<EsameDato> getElencoEsamiDati(){
return elencoEsamiDati;
}
public String toString(){
String s = "";
s = s + "Ecco le materie di questo Corso di Studi:\n";
int c = 0;
for(c= 0; c < elencoMaterie.size(); c++){
s = s + elencoMaterie.get(c).getIdMateria() + " ";
s = s + elencoMaterie.get(c).getNomeMateria() + " (";
s = s + elencoMaterie.get(c).getCrediti() + " crediti)\n";
}
return s;
}
}
You have not initialized the field elencoEsamiDati therefore the actual value is null.
Before adding elements to an ArrayList you need to create it:
private ArrayList<EsameDato> elencoEsamiDati = new ArrayList<EsameDato>();
You may also need to initialize other fields as well.
BTW it is not a good idea to use your own language when programming, use English instead.

Categories