This might be a dumb question but its frustrating me. I am adding into my array list a object during a loop but outside of the loop, all of the array list is overwritten with the last element in the array. It goes something like this.
while(fin.hasNextLine())
{
String line = fin.nextLine();
String[] user = line.split(",");
r.add(new User(user[0], user[1]));
System.out.println(r.get(count).getName());
count++;
}
This gives me an output of something like this (USER1, USER2, USER3, etc.) during the loop.
However, right after the loop I now have an output of something like this (USER500, USER500, USER500).
while(fin.hasNextLine())
{
String line = fin.nextLine();
String[] user = line.split(",");
r.add(new User(user[0], user[1]));
System.out.println(r.get(count).getName());
count++;
}
for (int i =0; i < r.size(); i++)
{
System.out.println(r.get(i).getName());
}
I managed to verify that this is the class where I'm having the problem and only one other method uses the array list in this class which i commented out.
I'm going to have to put on my psychic debugging goggles, but I predict tht your User class looks like this:
public class User {
private static String name;
public User(String x, String somethingElse) {
name = x;
}
public String getName() {
return name;
}
}
Note that name is static. Therefore that's one variable - not one per instance of User. You want it to be an instance field, so that each User object has a different name variable.
Related
working on a movie project but ran into some trouble.
If the file have many lines that look something like this:
Title: Avatar
Director: James Cameron
How do I make the method work?
The code is not running right now.
I created a helper method to find startswith what string first, so if the user puts in Title: or Director:, the method would return the name of either the tile or director. But java is saying that the i is not working here, it is strange, it said i can not be resolved to a variable. Also I realized if I do this, it would not work since the user is inputting a string but the line would contain both the info for title: name. How should I go about to make it work?
/**
* Lines in the file.
*/
private List<String> lines;
//helper method
String getNextStringStartsWith(String str) {
String[] lineArray;
//iterate over list of lines
for(i = 0; i < this.lines.size(); i++) {
//if the specific line has that string
if(this.lines.get(i).equals(str)) {
lineArray = this.lines.get(i).split(":");
info = lineArray[1].trim());
//gets the line afterwards
return info;
}
}
}
//Have to iterate over each line and look for lines starting with "Title:" and "Director:"
// Set the value of this.title and this.director
private void setTitleAndDirector() {
this.title = getNextStringStartsWith("Title:");
this.director = getNextStringStartsWith("Director:");
}
The problem with the for loop is that you didn't tell Java which type your variable i is. Therefore Java couldn't create a variable for it.
There were also some other small things wrong with your code.
You were missing a return value when nothing was returned from your loop.
You didn't tell Java which type the variable info is.
You had a ) too much on the line on the line with lineArray[1].trim().
Here is a way you can fix these things.
//helper method
String getNextStringStartsWith(String str) {
String[] lineArray;
//iterate over list of lines
for(int i = 0; i < this.lines.size(); i++) {
//if the specific line has that string
if(this.lines.get(i).equals(str)) {
lineArray = this.lines.get(i).split(":");
String info = lineArray[1].trim();
//gets the line afterwards
return info;
}
}
return null;
}
I have an assingment for school and I am having trouble with some ArrayLists. I have an input file which has one entry at every line. This entry has an integer and up to four strings. This input file is about locations that a film is filmed. The integer is the movieID in my case and the strings are the locations. However not every film has 4 locations which means that when my program tries to load the file it returns an error because it expects 5 fields at every row and this never happens because I have movies with 1 or 2 or the locations. I use a data loader class because I have to load several different files. My other files have a specific number of entries and fields at each row so loading those isn't a problem. The load process is done by adding the file into an array list and then creating the objects needed. I know that I need the program somehow to understand the empty fields and maybe handle them dynamically, for example a movie has 3 locations so the 4th field is empty, but I haven't figured it out yet. Any suggestions? Thank you!
This is my LocationsLoader class.
package dataLoader;
import java.util.ArrayList;
import dataModel.Locations;
public class LocationsLoader extends AbstractFileLoader<Locations>{
public int constructObjectFromRow(String[] tokens, ArrayList<Locations> locations) {
int movieID;
List<String> loc = new List();
movieID = Integer.parseInt(tokens[0]);
loc = tokens[]; // What goes here?
Locations l;
l = new Locations(movieID, loc);
locations.add(l);
System.out.println(l);
//System.out.println(locations.toString());
return 0;
}
}
And this is my Locations class:
package dataModel;
public class Locations {
private int movieID;
private List<String> loc;
public Locations(int otherMovieID, List<String> otherLocations) {
this.movieID = otherMovieID;
this.loc = otherLocations;
}
public int getMovieID() {
return movieID;
}
public void setMovieID(int id) {
this.movieID = id;
}
public String getLocations(int index) {
return loc.get(index);
}
}
}
You fill an array here
String[] tokens = new String[numFields];
for (int i = 0; i < numFields; i++) {
tokens[i] = tokenizer.nextToken();
}
but arrays are fixed length, there's really no reason to use them if you can have fewer values. Fill a list instead.
List<String> tokens = new ArrayList<>();
while (tokenizer.hasNextToken()) {
String token = tokenizer.nextToken().trim();
if (!token.isEmpty()) {
tokens.add(tokenizer.nextToken());
}
}
In fact, I'm not sure why you would need to give the reader the number of expected tokens at all.
But as Dodgy pointed out, you might as well use String#split:
String[] tokens = line.split(delimiter);
which will yield empty Strings as well, but you can just ignore those in your constructObjectFromRow function.
I am having issues with objects and classes.
I had to define two classes:
Course: a course has a code, an name and a number of credits
Teacher: a teacher has a first name and last name. He can be asked his full name.
So far so good, I got no issue with them, but I have to do next assignment which I was trying to do in the last 2 days and I could not find a proper answer:
Extend the code of the class teacher. A teacher also has a list of courses he can teach. Add an array of Courses to the code. Also add a function addCourse(Course aCourse) to the code. Courses can also be removed from teachers.
I could do everyting in my way but no clue on how to create the addCourse(Course aCourse) method.
Find below my coding, but it must be according to the method described:
public class Course {
private String courseCode;
private String courseName;
private String numberOfCredits;
public Course(String courseCode, String courseName, String numberOfCredits) {
super();
this.courseCode = courseCode;
this.courseName = courseName;
this.numberOfCredits = numberOfCredits;
}
public void print() {
System.out.println(courseCode + "\t" + courseName + "\t" + numberOfCredits);
}
public static void main(String[] args) {
Course[] courseArray = new Course[4];
System.out.println("Code" + "\t" + "Name" + "\t" + "Credits");
courseArray[0] = new Course("001", "Hist", "3");
courseArray[1] = new Course("002", "Phy", "3");
courseArray[2] = new Course("003", "Math", "3");
courseArray[3] = new Course("004", "Log", "3");
for (int i = 0; i < courseArray.length; i++) {
courseArray[i].print();
}
}
}
Arrays are fixed length collections of objects, so you'll need to decide how big your array should be. Let's call the length of your array MAX_COURSES. A more advanced solution might resize the array when required, but I get the impression this is beyond the scope of your course.
So you need to define the Course[] array as a field of your Teacher class. The syntax of array declarations is quite easy to research, so I won't put that in here. Just make sure your array length is equal to MAX_COURSES.
Now, to add courses to the array, you need to know where to put them. To keep track of the next free position of the array, the easiest thing to do is to declare a field in your class:
private int numCourses = 0;
Now, when you add a new course, insert the course into the index specified by numCourses. Make sure you increment numCourses after you've added the course.
Finally, you ought to test to see if your array is full before you agree to insert a new course into the array, i.e. check if numCourses is smaller than MAX_COURSES. If it's not, you need to throw an exception.
I would recommend using a collection (such as a List) rather than an array. The code would look something like:
public class Teacher {
private final String firstName;
private final String lastName;
private final List<Course> courses = new ArrayList<Course>();
public Teacher(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void addCourse(Course course) {
courses.add(course);
}
}
Based on that example, you should be able to add the removeCourse method yourself, and any other method you need to operate on the list of courses.
If you want to return the list as an array, you could always convert it, e.g:
public Course[] getCourses() {
return courses.toArray(new Course[courses.size()]);
}
If you really need to use an array for the data structure based on your assignment, something you can try when adding and removing courses, is to construct a list from the array of courses, add or remove a course from that list, the convert the list back to an array of courses.
There's really 3 options here.
Option 1
If you're allowed to use List constructs:
private List<Course> courses = new ArrayList<Course>();
public void addCourse(Course aCourse)
{
if (aCourse == null)
{
return;
}
courses.add(aCourse);
}
Option 2
The uses arrays, but it doesn't scale. Assume that a teacher can only have a maximum of X courses, in my example 10:
// Yes, I stole Duncan's variable names
private final int MAX_COURSES = 10;
private int numCourses = 0;
private Course[] courses = new Course[MAX_COURSES];
public void addCourse(Course aCourse) {
if (aCourse == null)
{
return;
}
if (numCourses >= courses.length)
{
return;
}
courses[numCourses] = aCourse;
numCourses++;
}
Option 3
This is identical to the previous item, but is a bit smarter in that it can resize the array... by creating a new one using the static method Arrays.copyOf
// Yes, I stole Duncan's variable names
private final int MAX_COURSES = 10;
private int numCourses = 0;
private Course[] courses = new Course[MAX_COURSES];
public void addCourse(Course aCourse) {
if (aCourse == null)
{
return;
}
if (numCourses >= courses.length)
{
int size = courses.length * 2;
courses = Arrays.copyOf(courses, size);
}
courses[numCourses] = aCourse;
numCourses++;
}
How do you return an array object in Java? I have an object that has an array in it and I want to work with it in my main class:
// code that does not work
class obj()
{
String[] name;
public obj()
{
name = new string[3];
for (int i = 0; i < 3; i++)
{
name[i] = scan.nextLine();
}
}
public String[] getName()
{
return name;
}
}
public class maincl
{
public static void main (String[] args)
{
obj one = new obj();
system.out.println(one.getName());
}
I am sorry if the answer is simple but I am teaching myself to code and I have no idea how you would do this.
You have to use the toString method.
System.out.println(Arrays.toString(one.getName()));
toString is a built-in function in Java (it might need library import; if you are using Netbeans, it will suggest it).
If the problem is to print it use
System.out.println(Arrays.toString(one.getName()));
//note System, not system
When you do getName() you are returning a reference to an array of strings, not the strings themselves. In order to access the individual strings entered, you can use the array index
String enteredName = name[index] format.
From your program, it looks like you want to print each item entered. For that, you could use a method like the following
public void printName() {
// for each item in the list of time
for(String enteredName : name) {
// print that entry
System.out.println(enteredName);
}
}
I'm creating a utility class that will make it easier for people to parse a csv string and return an array of array of strings.
My code almost works, but for some reason, when I do a get on my result in my first row, I'm expecting to see 1 row and seeing several rows concatenated on the first row.
Quick example:
a,b,c,d
e,f,g,h
Expecting: {a,b,c,d}, {e,f,g,h}
Result: {a,b,c,d,e,f,g}
public class csvParse
{
protected String originalCSV;
protected int skipToLine;
protected ArrayList<ArrayList<String>> parsedList;
public ArrayList<ArrayList<String>> getParsedList()
{
return parsedList;
}
public void setParsedList(ArrayList<ArrayList<String>> parsedList)
{
this.parsedList = parsedList;
}
public csvParse(String incomingCSV, int skipToLine)
{
super();
this.originalCSV = incomingCSV;
this.skipToLine = skipToLine;
this.parsedList = new ArrayList<ArrayList<String>>();
execute();
}
protected void execute()
{
// breaking this so there's an error. read below
//TODO: Make sure you have data out to X. May use a try/catch?
String row;
String lines[] = this.originalCSV.split("\\n?\\r");
ArrayList<String> temp = new ArrayList<String>();
try{
for (int i = this.skipToLine; i < lines.length; i++)
{
row = lines[i];
//split on commas
String[] RowData = row.split(",");
for (int x = 0; x < RowData.length; x++)
{
temp.add(RowData[x]);
}
this.parsedList.add(temp);
}
}
finally{
}
}
}
In your execute() method you don't reset the temp variable, so it gets the data from all rows. Just move your initialization within the outer for-loop.
You create "temp" outside the loop that goes through the lines. Thus, you are continually adding fields to the same temp object. You want to move the creation of this inside the loop, so you create a new object for each line.
Also, note that you are not handling embedded commas within a field. Maybe this doesn't occur in your data. But the CSV standard is that a field may be enclosed in quotes, in which case the quotes should be stripped off. If it is enclosed in quotes, it can then contain commas. If a field includes quotes, they should be doubled. For example:
a,"b,c","He said, ""Hello"""
contains three fields:
a
b,c
He said, "Hello"