Convert from an array to an arrayList - java

Ok guys this code is part of an assignment that I have, I am to implement an equals() method to check if two lines are equal, Two Lines are defined as equal if two end points are the same. However i can't check it because when i run the program as-is here, its blank as if the array list is empty. My question is: Do I need to change the loop reading through the file, or do I need to uncomment the initial array and do something with it in regards to the arrayList?
Any help would be greatly appreciate!!
//Line[] lines;
ArrayList<Line> lines;
Scanner reader;
public MyDrawing()
super();
this.setPreferredSize(new Dimension(500,500));
}
/**
* Reads the file and builds an array of Line objects.
*
* #param fileName The name of the file that contains the lines
* #throws Exception
*/
public void read( File fileName ) throws Exception
{
reader = new Scanner(fileName);
//----------------
// Change to Arraylist. Make the name of the arraylist "lines" so that code in paintComponent works.
//---------------------
//Have to read the first number before starting the loop
int numLines = reader.nextInt();
//lines = new Line[numLines];
ArrayList<Line>lines = new ArrayList<Line>();
Here i instantiate the arrayList
//This loop adds a new Line object to the lines array for every line in the file read.
while( reader.hasNext() ) {
for( int i = 0; i < numLines; i++ ) {
int x = reader.nextInt();
int y = reader.nextInt();
Point beg = new Point(x,y);
x = reader.nextInt();
y = reader.nextInt();
Point end = new Point(x,y);
String color = reader.next();
Line l = new Line( beg, end, color );
//----------------
// Change to make sure that you only add lines that don't already exist.
//--------------------
lines.add(l);
//lines[i] = l;
and here i tried to add the line "l" to the list
}
}
if( lines != null ) {
for( Line l: lines ) {
int x1 = l.getBeg().getX();
int y1 = l.getBeg().getY();
int x2 = l.getEnd().getX();
int y2 = l.getEnd().getY();
g.setColor(l.color);
g.drawLine(x1, y1, x2, y2);
System.out.println(l);
}
}
//Print the action to the console
System.out.println( "drawing lines" );
}
}

You have an instance variable named lines but you are not using it inside the read method. Inside the read method you are declaring a local variable with the same name lines and reading into it but that’s not changing the instance field with the same name. Hence that instance field will be null at the later time when you try to use it. Unfortunately you are protecting that code with if(lines != null) instead of asking yourself why something is null which oughtn’t.
While your code that iterates over the instance field works regardless of whether lines is an array or an ArrayList your code that reads into it cannot work with an array as arrays don’t have an add method. So, when changing the instance variable to an array, the fact that the read method still compiles gives you a hint that it is not using that array.
Change the line ArrayList<Line>lines = new ArrayList<Line>(); inside the read method into lines = new ArrayList<Line>();. Then the list you are reading into will be stored in the instance field you are using later. And, of course, it won’t compile anymore if lines is declared as an array.

Related

JAVA seperate class method not incrementing a variable in my main class method

so this is the main code for my text-based game.
import java.util.Scanner;
public class D_M_RPG {
public static void main(String[] args) {
//Creating the class to call on my toolbox
D_M_RPGtoolbox toolbox = new D_M_RPGtoolbox();
//Creating the scanner class for user input
Scanner input = new Scanner(System.in);
//Initiating variables and final variables aswell as arrays
//token variable to validate open spots in an array
int slotCounter = 0;
int inventoryExpander = 11;
//First initiated will be the character creation variables
String hairColor = "";
String eyeColor = "";
String skinColor = "";
String gender = "";
//Initiating the arrays for character inventory slots
String[] weaponSlots = new String[10];
//initiating the arrays for the character creation
String[] hairColorARR = {"black","Green","Yellow","Brown","Blue","Blonde","Grey","White"};
String[] eyeColorARR = {"Green","Brown","Blue","Grey",};
String[] skinColorARR = {"White","brown","Black",};
String[] genderARR = {"Male","Female"};
//Creating the introduction title and introduction
System.out.println("Welcome to, COLD OMEN.");
System.out.println("\nNOVEMBER 12th, 2150: ONTARIO, CANADA");
System.out.println("\nYou hear loud shouts and gun fire all around you but can't pinpoint the location of anything, you feel a bit dazed until someone grabs you and you open your eyes and snap out of it.");
System.out.println("\nUnknown: 'Get up, its time to move out. Take this.'");
System.out.println("\nUnknown hands you a 'M4-A4 RIFLE'");
System.out.println("\nyou manage to catch a small glimpse of him before you get up.");
//Character creation screen
System.out.println();
//ONLY WORKS ONCE WONT INCREMEMENT THE SLOTCOUNTER
toolbox.insert(weaponSlots, slotCounter, inventoryExpander, "M4-A4 RIFLE");
System.out.println("\n" + weaponSlots[0]);
toolbox.insert(weaponSlots, slotCounter, inventoryExpander, "ak47");
System.out.println(weaponSlots[0]);
}
}
so I have this method I made to basically add an "item" to the weaponSlots array (the inventory) but whenever I run it it will add to the first element in the array [0] but it wont incremement the slotcounter which should go up by one every time the method is used so that I dont replace any items in the array It should just add items until its full which is checked using the inventoryExpander variable. at the moment I have it printing the element at 0 and 0 for the array but i have checked 1 aswell and 1 is just null no item added it only just replaces the element at 0. heres the code for the method to increment etc:
public class D_M_RPGtoolbox {
//method for random number generating to be used for crit hits, turns, loot generation etc
public int randomGen(){
int x = (int) (Math.random()*((20-0)+1)+0);
return x;
}
//method for inserting into an array ONLY WORKS ONCE WONT INCREMEMENT THE SLOTCOUNTER FIX
public void insert(String[] a, int b, int d , String c) {
if(b < d) {
a[b] = c;
b++;
}//end of if statement
}//end of method
}
What you are actually performing the ++ operation on in b is a copy of the value in slotCounter.
The variable slotCounter is passed into insert "by-value".
This unlike what you probably imagine, that it is passed "by-reference".
One solution would be to do the slotCounter++ from the call row instead; and another would be to let the toolbox own the slotCounter variable completely.
This question uses the image of passing a copy of document content (by value) where changes to the document would not be seen by the sender; or as a link to a shared document (by reference), where changes could be made to the same page that the sender sees.
Its always going to be zero since you are passing zero and incrementing the local variable b.
Try calling the method as below with post increment ++ to slotCounter and see if it works for you,
toolbox.insert(weaponSlots, slotCounter++, inventoryExpander, "M4-A4 RIFLE");

Reading a text file into an array and performing a sort in Java

I have a homework question I need help with
We have been given a text file containing one word per line, of a story.
We need to read this file into an array, perform a sort on the array and then perform a binary search.
The task also says I'll need to use an overload method, but I'm unsure where
I have a bubble sort, that I've tested on a small array of characters which works
public static void bubbleV1String(String[]numbers)
{
for(int i = 0; i < numbers.length-1; i++)
{
for(int j = 0; j < numbers.length-1; j++)
{
if(numbers[j] .compareTo(numbers[j+1])>0)
{
String temp = numbers[j+1];
numbers[j+1] = numbers[j];
numbers[j] = temp;
}
}
}
}`
And my binary search which I've tested on the same small array
public static String binarySearch(int[] numbers, int wanted)
{
ArrayUtilities.bucketSort(numbers);
int left = 0;
int right = numbers.length-1;
while(left <= right)
{
int middle = (left+right)/2;
if (numbers[middle] == wanted)
{
return (wanted + " was found at position " + middle);
}
else if(numbers[middle] > wanted)
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
return wanted + " was not found";
}
Here is my code in an app class to read in a file and sort it
String[] myArray = new String[100000];
int index = 0;
File text = new File("threebears.txt");
try {
Scanner scan = new Scanner(text);
while(scan.hasNextLine() && index < 100000)
{
myArray[index] = scan.nextLine();
index++;
}
scan.close();
} catch (IOException e) {
System.out.println("Problem with file");
e.printStackTrace();
}
ArrayUtilities.bubbleV1String(myArray);
try {
FileWriter outFile = new FileWriter("sorted1.txt");
PrintWriter out = new PrintWriter(outFile);
for(String item : myArray)
{
out.println(item);
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
When I go to run the code, I get a null pointer exception and the following message
Exception in thread "main" java.lang.NullPointerException
at java.base/java.lang.String.compareTo(Unknown Source)
at parrayutilities.ArrayUtilities.bubbleV1String(ArrayUtilities.java:129)
at parrayutilities.binarySearchApp.main(binarySearchApp.java:32)
Line 129 refers to this line of code of my bubblesort
if(numbers[j] .compareTo(numbers[j+1])>0)
And line 32 refers to the piece of code where I call the bubblesort
ArrayUtilities.bubbleV1String(myArray);
Does anyone know why I'm getting a null pointer exception when I've tested the bubblesort on a small string array? I'm thinking possibly something to do with the overloaded method mentioned earlier but I'm not sure
Thanks
You are creating an array of length 100000 and fill the lines as they are read. Initially all elements will be null and after reading the file quite a number of them is likely to still be null. Thus when you sort the array numbers[j] will eventually be a null element and thus calling compareTo(...) on that will throw a NullPointerException.
To fix that you need to know where in the array the non-null part ends. You are already tracking the number of read lines in index so after reading the file that would be the index of the first null element.
Now you basically have 2 options:
Pass index to bubbleV1String() and do for(int i = 0; i < index-1; i++) etc.
Make a copy of the array after reading the lines and before sorting it:
String[] copy = new String[index];
StringSystem.arrayCopy(myArray,0,copy,0,index);
//optional but it can make the rest of the code easier to handle: replace myArray with copy
myArray = copy;
Finally you could also use a List<String> which would be better than using arrays but I assume that's covered by a future lesson.
It seems that you have some null values in your numbers array. Try to debug your code (or just print array's content) and verify what you have there. Hard to tell anything not knowing what is in your input file.
Method overloading is when multiple functions have the same name but different parameters.
e.g. (taken from wikipedia - function overloading)
// volume of a cube
int volume(const int s)
{
return s*s*s;
}
// volume of a cylinder
double volume(const double r, const int h)
{
return 3.1415926*r*r*static_cast<double>(h);
}
Regarding your null pointer exception, you've created an array of size 100000, but it's likely you haven't read in enough information to fill that size. Therefore some of the array is empty when you try to access it. There are multiple ways you can go about this, off the top of my head that includes array lists, dynamic arrays or even moving the contents of the array to another one, once you know the size of the contents (however this is inefficient).

Extend array size

I'm trying to extend my array length with this logic, but I'm still having outOfBounds exception.. any idea or comment help. It seems like my logic is not right
any other way to do this will be great.. or any change to this is is fine to
public Student[] createNewArray(Student[] studentListArray){
for(int i = 0; i < studentListArray.length; i++) {
if (numberOfStudents == studentListArray.length) {
newStudentListArray = new Student[studentListArray.length * 2];
newStudentListArray = studentListArray;
}
}
return newStudentListArray;
}
Problem:
The line below creates a new array with a length twice as long as the original, and then assigns it to the newStudentListArray variable:
newStudentListArray = new Student[studentListArray.length * 2]; // Line A
The line below then proceeds to discard the previously created unused object and simply assigns the original array to the same variable:
newStudentListArray = studentListArray; // Line B
So line B above completely nullifies the word done on Line A.
Solution: Don't do that second line -- don't discard your newly created array. Instead use System.arraycopy to copy data from the original array into your new array. For example
newStudentListArray = new Student[studentListArray.length * 2]; // Line A
System.arraycopy(studentListArray, 0, newStudentListArray, 0,
studentListArray.length);

Java: Issue Reading Text file then Converting

I've got an issue getting a method to read a file, then converting it to an integer. Here is a brief explanation of the program. It is essentially a car dealership inventory that keeps track of the vehicles in the lot by keeping them written down in a text file. When the program starts it will need to read the file and put all the current cars into an array so they can be displayed. Then the rest of the program will do other things like remove cars and add news ones etc. The part I am at is when the program first starts it needs to read the file, but I can't seem to get it to work.
The text file consists of 6 lines in total; 4 numbers first then 2 words respectively. I want the method to read the first four lines and convert those into integers and store them in a temporary array. Then after that it will read the next two lines and store those in a temporary array as well. Afterwards I take all these stored values and send them to a constructor. The constructor is then stored in an Arraylist and the Arraylist can be accessed anytime. In the output it does all of this just fine. But it wants to run through the method a second time despite barriers in place to prevent this.
Here is the code. Its a class and not the main program. I will try to explain the program as best I can inside the code.
public class Vehicle {
//All the different private variables for the constructors and methods
private int intholder[], year, type, kilometres, price, loop;
private String make, model, myline, holder[];
//The Arraylist that the different vehicle objects will be stored
ArrayList<Vehicle> allCars = new ArrayList<Vehicle>();
//The Default constructor
public Vehicle(){
make = "Vehicle Make";
model = "Vehicle Model";
type = 0;
year = 0;
kilometres = 0;
price = 0;
}
//The constructor that has information sent to it
public Vehicle(int _type, int _year, int _kilometres, int _price, String _make, String _model){
make = _make;
model = _model;
type = _type;
year = _year;
kilometres = _kilometres;
price = _price;
}
//Text file information
/*
* CAR TYPE CODE:
* 1 - Sedan
* 2 - Truck
* 3 - Crossover
* 4 - SUV
* 5 - Sports
*
* There is a total of 6 lines for each car and are as follows
* 1 - int Type integer
* 2 - int Year
* 3 - int Kilometres
* 4 - int Asking price
* 5 - String Make
* 6 - String Model
*/
//The method in question. It reads through the file, converts the integers and stores them,
//stores the strings, and sends all the information to the constructor
public void readCars()throws IOException{
BufferedReader readFile = new BufferedReader(new FileReader("C:/Users/David/Desktop/FinalProject/Carlot.txt"));
//Setting the length of the temporary arrays
holder = new String[2];
intholder = new int[4];
//The main loop in the method.
do{
//Read the first 4 lines of the file and convert them to integers.
//The try catch shouldn't have to be there because the first 4 lines
//of the file are all numbers, but I put it in there to see when it was messing up.
for(int i = 0; i < 4; i++){
myline = readFile.readLine();
try{
intholder[i] = Integer.parseInt(myline);
}
catch(NumberFormatException e){
System.out.println(e);
}
//Had this in here to see how many lines down the file it would go before messing up.
System.out.println(myline);
}
//Loop to store the Strings
for(int i = 0; i < 2; i++){
myline = readFile.readLine();
holder[i] = myline;
System.out.println(myline);
}
//Sends all the data to the constructor
Vehicle V = new Vehicle(intholder[0], intholder[1], intholder[2], intholder[3], holder[0], holder[1]);
//Several if statements to determine which subclass of vehicle it is.
if(intholder[0]==1){
Sedan S = new Sedan();
allCars.add(S);
}
else if(intholder[0]==2){
Truck T = new Truck();
allCars.add(T);
}
else if(intholder[0]==3){
Crossover C = new Crossover();
allCars.add(C);
}
else if(intholder[0]==4){
SUV U = new SUV();
allCars.add(U);
}
else if(intholder[0]==5){
Sports P = new Sports();
allCars.add(P);
}
//Only break the loop if the myline equals null
}while(myline != null);
//if the loop breaks, close the file
readFile.close();
}
Now I think I know where it is going wrong. At the end of the do/while, it checks if "myline" is null. And because the last time it read the file it was still a String the loop continues. The last time it goes through the loop, everything is null so trying to convert the integer is impossible so I get errors. But I have no idea how to get it to read the file at the end of the loop without going to the next line. Here is what the text file looks like.
1
2007
150250
5000
Toyota
Corolla
2
2005
240400
4500
Chevorlet
Silverado
I can't have it read at the end of the loop because if it does and there are still more cars after the one I just did, It goes into the next line when the loop restarts everything is thrown off.
Any help is appreciated, Thanks!
Use a labeled break statement in your for loops to simply exit out of the main do while loop when myline becomes null. The way other objects are being instantiated within the loop doesn't leave much room for easy refactoring hence the use of a labeled break makes sense here.
outerloop:
do {
for (int i = 0; i < 4; i++) {
if ((myline = readFile.readLine()) == null) break outerloop;
// ..
}
for (int i = 0; i < 2; i++) {
if ((myline = readFile.readLine()) == null) break outerloop;
// ..
}
// ..
} while (myline != null);
Maybe you could use a while loop instead of a do-while loop and read the next line from the file before anything else. Something like this:
String myline = null;
while( (myline = readFile.readLine()) != null ) {
// All your logic...
}
readFile.close();
The condition of while loop does the following: first, read the next line of the file with myline = readFile.readLine(). The previous statement returns the value of myline, so now we check that it is not null with the comparison:
(myline = readFile.readLine()) != null

Java Buffered Reader Text File Parsing

I am really struggling with parsing a text file. I have a text file which is in the following format
ID
Float Float
Float Float
.... // variable number of floats
END
ID
Float Float
Float Float
....
END
etc However the ID can represent one of two values, 0 which means it is a new field, or -1 which means it is related to the last new field. The number of times a related field can repeat it self is unlimited. Which is where the problem is occurring.
As I have a method in a library which takes an ArrayList of the new Floats, then an ArrayList of an ArrayList of the related floats.
When I try and code the logic for this I just keep getting deeper and deeper embedded while loops.
I would really appreciate any suggestions as to how I should go about this. Thanks in advance.
Here is the code I have so far.
BufferedReader br = new BufferedReader(new FileReader(buildingsFile));
String[] line = br.readLine().trim().split(" ");
boolean original = true;
while(true)
{
if(line[0].equals("END"))
break;
startCoordinate = new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1]));
while(true)
{
line = br.readLine().trim().split(" ");
if(!line[0].equals("END") && original == true)
polypoints.add(new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1])));
else if(!line[0].equals("END") && original == false)
cutout.add(new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1])));
else if(line[0].equals("END") && original == false)
{
cutouts.add(cutout);
cutout.clear();
}
else if(line[0].equals("-99999"))
original = false;
else if(line[0].equals("0"))
break;
}
buildingDB.addBuilding(mapName, startCoord, polypoints, cutouts);
}
New Code
int i = 0;
BufferedReader br = new BufferedReader(new FileReader(buildingsFile));
String[] line;
while(true)
{
line = br.readLine().trim().split(" ");
if(line[0].equals("END"))
break;
polygons.add(new Polygon(line));
while(true)
{
line = br.readLine().trim().split(" ");
if(line[0].equals("END"))
break;
polygons.get(i).addCoord(new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1])));
}
i++;
}
System.out.println(polygons.size());
int j = 0;
for(i = 0; i< polygons.size(); i++)
{
Building newBuilding = new Building();
if(polygons.get(i).isNew == true)
{
newBuilding = new Building();
newBuilding.startCoord = new Coordinate(polygons.get(i).x, polygons.get(i).y);
}
while(polygons.get(i).isNew == false)
newBuilding.cutouts.add(polygons.get(i).coords);
buildings.add(newBuilding);
}
for(i = 0; i<buildings.size(); i++)
{
System.out.println(i);
buildingDB.addBuilding(mapName, buildings.get(i).startCoord, buildings.get(i).polypoint, buildings.get(i).cutouts);
}
Maybe you should use map for new floats and related floats..if got your question it should help..example:
HashMap hm = new HashMap();
hm.put("Rohit", new Double(3434.34));
I assume that a "field" means an ID and a variable number of coordinates (pairs of floats), that, judging from your code, represents a polygon in fact.
I would first load all the polygons, each into a separate Polygon object:
class Polygon {
boolean isNew;
List<Coordinate> coordinates;
}
and store the polygons in another list. Then in a 2nd pass go through all the polygons to group them according to their IDs into something like
class Building {
Polygon polygon;
List<Polygon> cutouts;
}
I think this would be fairly simple to code.
OTOH if you have a huge amount of data in the file, and/or you prefer processing the read data little by little, you could simply read a polygon and all its associated cutouts, until you find the next polygon (ID of 0), at which point you could simply pass the stuff read so far to the building DB and start reading the next polygon.
You can try using ANTLR here, The Grammar defines the format of the text you are expecting and then you can wrap the contents in a Java object. The * and + Wildcards will resolve the complexity of while and for. Its very simple and easy to use, you dont have to construct AST you can take the parsed content from java objects directly. But the only overhead is you have to add the ANTLR.jar to your path.

Categories