Java Scoping Error - java

I was trying to write a mapper class for a practice program and the compiler always gives me error that:
satMath and satVerbal might not have been initialized.
public class UniversityMapper extends Mapper <LongWritable,Text,Text,IntWritable> {
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// TODO convert record (value) to String
StringTokenizer iterator = new StringTokenizer (value.toString(),")" );
int state = 2;
int satVerbal;
int satMath;
while(state != 0 && iterator.hasMoreTokens())
{
String cur = iterator.nextToken();
if (cur.contains("sat verbal"))
{
state--;
StringTokenizer temp = new StringTokenizer(cur,"\\s+");
temp.nextToken();
temp.nextToken();
int satV = (new Integer(temp.nextToken())).intValue();
satVerbal = satV;
//context.write(new Text("satv"), new IntWritable(satVerbal));
}
else if (cur.contains("sat math"))
{
state--;
StringTokenizer temp = new StringTokenizer(cur,"\\s+");
temp.nextToken();
temp.nextToken();
int satM = (new Integer(temp.nextToken())).intValue();
satMath = satM;
//context.write(new Text("satm"), new IntWritable(satMath));
}
}
if (state == 0)
{
System.out.println(satVerbal);
System.out.println(satMath);
context.write(new Text ("satv"), new IntWritable(satVerbal));
context.write(new Text ("satm"), new IntWritable(satMath));
}
} }
If I reposition the context.write() method within the scope of the if statements (commented out in the code) I no longer get this error. I cannot understand why. I usually code in c++ and python I am really new to Java and I need to finish this program. Can somebody help me with this, thanks in advance :)

This is fairly straightforward. If this else if does't execute:
else if (cur.contains("sat math"))
Then you never initialize satMath, and you try to access it later via:
context.write(new Text ("satm"), new IntWritable(satMath));
Same goes with if (cur.contains("sat verbal")) and satVerbal.
If you wish to avoid these altogether you could just initialize + declare those variables yourself:
int satVerbal = 0;
int satMath = 0;
But you should be absolutely certain that they will be assigned something else inside your while, otherwise you will actually use their initialized values (0) later in your context.write, which I assume isn't desirable for you.

Related

Where to place constant attributes?

I want to write clean code in java and I am very insecure where to place my attriutes.
I often cannot decide, if I place them on top of the class, in a constructor or directly in the method. Are there some rules out there? The only logic one for me is, to place attributes on top of the class when these attributes are used in more than one method.
Can you evaluate this code in terms of clean code? Should I place the constant currency attributes in the constructor? Can I also put some of the class attributes in a method? Thanks for the advice
public class CsvFileReader {
private SimpleDateFormatStringToDate formatter = new SimpleDateFormatStringToDate();
private IataExchangeRateDataSet exchangeRateDataSet= new IataExchangeRateDataSet();
private final String SEMICOLON_DELIMITER = ";";
// Currency attributes index
private final int CURRENCY_VALUE = 1;
private final int CURRENCY_ISO_CODE = 2;
private final int CURRENCY_PERIOD_START = 3;
private final int CURRENCY_PERIOD_END = 4;
public CsvFileReader(IataExchangeRateDataSet exchangeRateDataSet) {
this.exchangeRateDataSet = exchangeRateDataSet;
}
public void readCsvFile(String fileName, final int maxLengthOfColumn) {
BufferedReader fileReader = null;
try {
String line = "";
fileReader = new BufferedReader(new FileReader(fileName));
while ((line = fileReader.readLine()) != null) {
String[] tokens = line.split(SEMICOLON_DELIMITER);
//TODO: Noch auf Vollständigkeit der Zeile, Korrektheit der Datumsformate und ähnliches überprüfen
if ( tokens.length== maxLengthOfColumn && DateFormat.checkDateFormat(tokens[CURRENCY_PERIOD_START]) && DateFormat.checkDateFormat(tokens[CURRENCY_PERIOD_END])) {
//format currency value in csv
tokens[CURRENCY_VALUE]=tokens[CURRENCY_VALUE].replace(",", ".");
IataExchangeRateData iataExchangeRateData = new IataExchangeRateData(
new BigDecimal(tokens[CURRENCY_VALUE]), tokens[CURRENCY_ISO_CODE],
formatter.parseStringToDate(tokens[CURRENCY_PERIOD_START]),
formatter.parseStringToDate(tokens[CURRENCY_PERIOD_END]));
exchangeRateDataSet.getExchangeRateDataSet().add(iataExchangeRateData);
}
}
}
catch (Exception e) {
System.out.println("Error in CsvFileReader");
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
System.out.println("Error while closing fileReader !!!");
e.printStackTrace();
}
}
}
}
If any attribute is used for calculation or manipulation inside a method then use that attribute inside only the method.
If any attribute is being used such that any method can refer it then use it at the top of all the methods.
If any attribute does not depend on the class specifically like counting the number of threads of a particular object then use it as a class variable by making it static.
clean code questions usually spark off arguments, some right and others not so right. But I have felt the way you do now about constants and I have used them just the way you did in your code i.e. right above the constructor. But more recently, I put them in an interface. Something a little like this
public interface CurrencyConstants {
int CURRENCY_VALUE = 1;
int CURRENCY_ISO_CODE = 2;
int CURRENCY_PERIOD_START = 3;
int CURRENCY_PERIOD_END = 4;
}
Then I simply import the interface and use the constants like so..
CurrencyConstants.CURRENCY_VALUE
This helps if the constants are used in more than one class. Cheers!

Android Search ArrayList of objects for only one paramater, return index of object

I am having a big problem with this, now I have a class called FileRelationship, and I have two constructors with it. Class is shown below. I also overrode the equals method in this class.
public class FileRelationship {
String fileName;
String firstLink;
String secondLink;
String thirdLink;
public FileRelationship(String fileName) {
this.fileName = fileName;
}
public FileRelationship(String fileName, String firstLink, String secondLink, String thirdLink) {
this.fileName = fileName;
this.firstLink = firstLink;
this.secondLink = secondLink;
this.thirdLink = thirdLink;
}
public boolean equals(Object o) {
if(o == null) {
return false;
}
if(this == o) {
return true;
}
if(o instanceof FileRelationship) {
return this.fileName.equals(((FileRelationship)o).fileName);
}
return false;
}
}
Now I have an arrayList of FileRelationships and I want to be able to search through this list (These all use the constructor with 4 Strings in it (fileName, firstLink, secondLink, thirdLink)) Now I have a method in another class that is supposed to search this arrayList and this find the index of one that has a matching fileName. When I call this method I am only passing into the constructor with the fileName and that is all. (This is the only I can do it, I will not know the other strings).
This is how I set up the ArrayList of FileRelationships.
fileRelationships = new ArrayList<FileRelationship>();
String MasterLine;
InputStream inputStream = this.getResources().openRawResource(R.raw.masterfile);
InputStreamReader inputreader = new InputStreamReader(inputStream);
BufferedReader buffreader = new BufferedReader(inputreader);
// Creates the arrayList of all the relationships for later use of retreival.
try {
while (( MasterLine = buffreader.readLine()) != null) {
MasterLineArray = MasterLine.split(",");
String filename = MasterLineArray[0];
String choice1 = MasterLineArray[1];
String choice2 = MasterLineArray[2];
String choice3 = MasterLineArray[3];
FileRelationship fr = new FileRelationship(filename, choice1, choice2, choice3);
fileRelationships.add(fr);
}
} catch (IOException e) {
} finally {
closeQuietly(buffreader);
}
This is my method for finding the relationship and then setting it to the variable I need. I want to be able to find the index of the list and apply it to the variable.
public void findRelationship(String nextFileName) {
int pageIndex = fileRelationships.indexOf((new FileRelationship(nextFileName)));
selectedRelationship = fileRelationships.get(pageIndex);
currentPage = pageIndex;
}
EDIT : I'm sorry forgot to say what was wrong. No it doesn't work. pageIndex is returning a -1 (So in other words it isn't finding anything). I don't know what else to do, maybe use HashCode but honestly I've even looked up stuff about it and I can't really figure out how to use that either.
I really really need help on this, as this is for a school project due soon. I have most of the project done as once I get this part finished I should be almost done. Thanks.
Search like this
public void findRelationship(String nextFileName) {
for(FileRelationship file:fileRelationships)
{
if(file.firsFileName.equals(nextFileName))
{
currentPage=fileRelationships.indexOf(file);
}
}
}
list returns -1 when list doesn't contain that object. In your case you where using indexOf() obj by creating new object
int pageIndex = fileRelationships.indexOf((new FileRelationship(nextFileName)));
this is not the right way. because you are creating new object and list does not contains new object
And also make getter setter method for each fields in FileRelationship class directly accessing each field is not the good practice

Glpk java and .mod file

I've got a .mod file and I can run it in java(Using netbeans).
The file gets data from another file .dat, because the guy who was developing it used GUSEK. Now we need to implement it in java, but i dont know how to put data in the K constant in the .mod file.
Doesn't matter the way, can be through database querys or file reading.
I dont know anything about math programming, i just need to add values to the already made glpk function.
Here's the .mod function:
# OPRE
set K;
param mc {k in K};
param phi {k in K};
param cman {k in K};
param ni {k in K};
param cesp;
param mf;
var x {k in K} binary;
minimize custo: sum {k in K} (mc[k]*phi[k]*(1-x[k]) + cman[k]*phi[k]*x[k]);
s.t. recursos: sum {k in K} (cman[k]*phi[k]*x[k]) - cesp <= 0;
s.t. ocorrencias: sum {k in K} (ni[k] + (1-x[k])*phi[k]) - mf <= 0;
end;
And here's the java code:
package br.com.genera.service.otimi;
import org.gnu.glpk.*;
public class Gmpl implements GlpkCallbackListener, GlpkTerminalListener {
private boolean hookUsed = false;
public static void main(String[] arg) {
String[] nomeArquivo = new String[2];
nomeArquivo[0] = "C:\\PodaEquipamento.mod";
System.out.println(nomeArquivo[0]);
GLPK.glp_java_set_numeric_locale("C");
System.out.println(nomeArquivo[0]);
new Gmpl().solve(nomeArquivo);
}
public void solve(String[] arg) {
glp_prob lp = null;
glp_tran tran;
glp_iocp iocp;
String fname;
int skip = 0;
int ret;
// listen to callbacks
GlpkCallback.addListener(this);
// listen to terminal output
GlpkTerminal.addListener(this);
fname = arg[0];
lp = GLPK.glp_create_prob();
System.out.println("Problem created");
tran = GLPK.glp_mpl_alloc_wksp();
ret = GLPK.glp_mpl_read_model(tran, fname, skip);
if (ret != 0) {
GLPK.glp_mpl_free_wksp(tran);
GLPK.glp_delete_prob(lp);
throw new RuntimeException("Model file not found: " + fname);
}
// generate model
GLPK.glp_mpl_generate(tran, null);
// build model
GLPK.glp_mpl_build_prob(tran, lp);
// set solver parameters
iocp = new glp_iocp();
GLPK.glp_init_iocp(iocp);
iocp.setPresolve(GLPKConstants.GLP_ON);
// do not listen to output anymore
GlpkTerminal.removeListener(this);
// solve model
ret = GLPK.glp_intopt(lp, iocp);
// postsolve model
if (ret == 0) {
GLPK.glp_mpl_postsolve(tran, lp, GLPKConstants.GLP_MIP);
}
// free memory
GLPK.glp_mpl_free_wksp(tran);
GLPK.glp_delete_prob(lp);
// do not listen for callbacks anymore
GlpkCallback.removeListener(this);
// check that the hook function has been used for terminal output.
if (!hookUsed) {
System.out.println("Error: The terminal output hook was not used.");
System.exit(1);
}
}
#Override
public boolean output(String str) {
hookUsed = true;
System.out.print(str);
return false;
}
#Override
public void callback(glp_tree tree) {
int reason = GLPK.glp_ios_reason(tree);
if (reason == GLPKConstants.GLP_IBINGO) {
System.out.println("Better solution found");
}
}
}
And i'm getting this in the console:
Reading model section from C:\PodaEquipamento.mod...
33 lines were read
Generating custo...
C:\PodaEquipamento.mod:24: no value for K
glp_mpl_build_prob: invalid call sequence
Hope someone can help, thanks.
The best way would be to read the data file the same way you read the modelfile.
ret = GLPK.glp_mpl_read_data(tran, fname_data, skip);
if (ret != 0) {
GLPK.glp_mpl_free_wksp(tran);
GLPK.glp_delete_prob(lp);
throw new RuntimeException("Data file not found: " + fname_data);
}
I resolved just copying the data block from the .data file into the .mod file.
Anyway,Thanks puhgee.

How to save variables to be later accessed?

I am trying to make a text based game in which you have different levels of different aspects of life and other variables. I'm trying to save them to some sort of file so I can get them back later.
So far, this is what I have with the variables:
public class baseLevels {
public boolean gameOver = false;
//100 is a normal level
public int happyLevel = 100;
public int sleepLevel = 100;
public int angerLevel = 100;
public int healthLevel = 100;
public int popularityLevel = 100;
public int smartLevel = 100;
public int weight = 100;
//0 = Single 1 = Not very close, but dating 2 = close and dating 3 = engaged 4 = married
public int relationshipStatus = 0;
public boolean children = false;
public int numberOfChildren = 0;
//Tests if the player is injured, 1-5 on severeness
public boolean injured = false;
public int severity = 1;
public boolean healthCare = false;
//Money status: 1 is poor, 5 is rich
public int money = 5000;
public int wealthStatus = 1;
//Family is alive or dead
public boolean momDead = false;
public boolean dadDead = false;
public boolean sisterDead = false;
public boolean brotherDead = false;
public boolean grandmaDead = false;
public boolean grandpaDead = false;
//Misc. variables
public boolean car = false;
public boolean house = false;
public boolean dead = false;
public boolean likeMusic = false;
}
After looking at the property method someone posted, I like it, but I need a way to set a property value as a number. When I try this, I get an error saying I can't have a string and an integer.
java.util.Properties is probably the best class for something simple like this. It has built-in methods for loading from a file and saving to a file.
Properties props = new Properties();
props.load(new FileInputStream("data.props"));
String someProp = props.getProperty("myName");
props.setProperty("myName", "John Smith");
props.store(new PrintWriter("data.props"));
One option is to use object serialization.
To use serialization your class must implement the Serializable interface.
Suppose you have an instance of your class baseLevels that you want to write to a file, "save.dat":
baseLevels obj = new baseLevels();
Using object serialization you would first create an object output stream to your save file: "save.dat".
ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( "save.dat" ) );
To write your baseLevels instance, obj, to the file you would invoke writeObject( obj ):
out.writeObject( obj );
Always remember to close the stream:
out.close();
To restore the object to the state it was in when you wrote it to the save file, you would use an object input stream:
ObjectInputStream in = new ObjectInputStream( new FileInputStream( "save.dat" ) );
And invoke method readObject() which reads the next object from the input stream. The return type of readObject() is Object so we need to cast it to the appropriate type; in this example we have only written one object and we know that it is of type baseLevels thus we can safely cast the returned object to baseLevels:
baseLevels obj = (baseLevels)in.readObject().
close the stream:
in.close();
Complete example(Assumes that baseLevels implements Serializable):
// Initialize
String fileName = "save.dat";
baseLevels lvl1 = new baseLevels();
// Set level attributes
lvl1.angerLevel = 0;
lvl1.happyLevel = 200;
// Write level
try( ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( fileName ) ) ) {
out.writeObject( lvl1 );
}
catch( IOException e ) {
System.err.println( e.getMessage() );
}
// Read level
baseLevels lvl2;
try( ObjectInputStream in = new ObjectInputStream( new FileInputStream( fileName ) ) ) {
lvl2 = (baseLevels)in.readObject();
}
catch( IOException e ) {
System.err.println( e.getMessage() );
}
catch( ClassNotFoundException e ) {
System.err.println( "Class definition could not be found" );
System.err.println( e.getMessage() );
}
For more information on serialization you should look at: http://docs.oracle.com/javase/tutorial/essential/io/objectstreams.html.
The example linked to from the above site - because it is easy to miss if you only skim the site: http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/essential/io/examples/ObjectStreams.java )
As far as a Game Development concerned in java its best approach to user MVC
also you might be using all of the classes and variables differently like you mentioned
100 is a normal level
0 = Single 1 = Not very close, but dating 2 = close and dating 3 = engaged 4 = married
Tests if the player is injured, 1-5 on severeness
Money status: 1 is poor, 5 is rich
and to use them you will need some getters and setters in your classes so its better approach if you use Beans and a separate package for all of the beans with different Bean classes.
javadoc and
Collections inorder to use and map you data with objects
Saving Variables in game

ArrayIndexOutOfBoundsException: 4

I'm writing a little program to analyze some data I have and this code, which worked yesterday, is no longer working.
For the life of me, I can't tell why. To my eye, everything is as it should be. I've tried re-syncing the folder on my computer with my GitHub Repo and still was receiving the same error. Maybe a second pair of eyes could help me out?
The text file being read from can be found here.
Here are the methods referred to by the stack trace:
public static void main(String[] args) throws IOException{
FileManagementMethods fmm = new FileManagementMethods();
fmm.runProgram();
}
void runProgram() throws IOException{
boolean doesFileExist = doesFileExist();
if(doesFileExist){
int numLines = getNumberOfLines();
String[] linesFromFile = getLines(numLines);
WeatherAnalysisMethods wam = new WeatherAnalysisMethods();
wam.parseFileAverageTemp(linesFromFile);
wam.parseFileAverageHumidity(linesFromFile);
wam.predictNextTemperature(linesFromFile);
} else{
try {
throw new IOException("Could not find log.txt in default directory");
} catch (IOException e) {
e.printStackTrace();
}
}
}
void parseFileAverageHumidity(String[] linesFromFile) throws IOException{
int[] humiditiesFromFile = new int[linesFromFile.length];
humiditiesFromFile = getHumiditiesFromFile(linesFromFile.length);
int averageFromFile = 0;
for(int i = 0; i < humiditiesFromFile.length; i++){
averageFromFile += humiditiesFromFile[i];
}
averageFromFile = averageFromFile / humiditiesFromFile.length;
String outString = "Average humidity for whole file = " + averageFromFile;
FileManagementMethods fmm = new FileManagementMethods();
fmm.saveAnalyzedData(outString);
}
int[] getHumiditiesFromFile(int numLines){
int[] humiditiesFromFile = new int[numLines];
FileManagementMethods fmm = new FileManagementMethods();
String[] lines = fmm.getLines(numLines);
int i = 0;
while(1 < numLines){
String[] lineDivides = lines[i].split(",");
String tempString = lineDivides[4];
humiditiesFromFile[i] = Integer.parseInt(tempString);
i++;
}
return humiditiesFromFile;
}
Line 51:
String tempString = lineDivides[4];
And here is the stack trace:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at org.weatheralert.analysis.WeatherAnalysisMethods.getHumiditiesFromFile(WeatherAnalysisMethods.java:51)
at org.weatheralert.analysis.WeatherAnalysisMethods.parseFileAverageHumidity(WeatherAnalysisMethods.java:22)
at org.weatheralert.analysis.FileManagementMethods.runProgram(FileManagementMethods.java:22)
at org.weatheralert.analysis.Main.main(Main.java:9)
If you guys need more information, don't hesitate to ask.
The problem is here, inside your getHumiditiesFromFile method:
while(1 < numLines){
It should be
while (i < numLines){
Since inside this loop you're calling humiditiesFromFile[i].
As Foo Bar User noted in comment, the error may be here:
String tempString = lineDivides[4];
It would be better to make sure there are at least 4 items in that array.
Besides that, the error noted in the section above (assuming it's not a typo) could also throw this Exception for being in an infinite loop.
You've hardcoded a 4 here without checking to see if it exists:
String tempString = lineDivides[4];
You will need to do some data validation beforehand. You're assuming that the line you read has at least three commas. Either change the code to check, or validate the file.
So, it was a silly issue.... JSoup had a couple bad connections and didn't save some of the data I needed it to save. So it didn't recognize some of the lines of data.
Once I fixed the actual data, it runs without issue again.
I apologize for wasting your time.

Categories

Resources