Adding objects to array list [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
Hello i am trying to add my Class's objects into an ArrayList with the objects attributes but i keep getting null pointers
I am reading values from a txt file assigning them to the attributes and then put the object into the array list
here is my code
public class Users {
Scanner scan;
BufferedReader reader;
MainGui gui;
Login login;
String name;
String surname;
String dob;
String address;
String town;
String number;
String position;
ArrayList<Users> allUsers = new ArrayList<Users>();
public Users(Login login){
this.login = login;
open();
}
public void open(){
try {
URL path = Users.class.getResource("records.txt");
File f = new File(path.getFile());
reader = new BufferedReader(new FileReader(f));
scan = new Scanner(reader);
} catch (FileNotFoundException e) {
System.out.println("File not found");
}
}
public void readRecords(){
open();
while(scan.hasNext()){
Users user = new Users(login);
user.name = scan.next();
user.surname = scan.next();
user.dob = scan.next();
user.address = scan.next();
user.address = addSpace(user.address);
user.town = scan.next();
user.number = scan.next();
user.position = scan.next();
allUsers.add(user);
}
scan.close();
}
public void printUsers(){
readRecords();
for(Users user : allUsers){
System.out.println("" + user );
}
}
}
I have included all the methods playing part in this in order for you to help me better.

Change this part of code, you need to set the values in the user object you are creating.
Users user = new Users(login);
user.name = scan.next();
..
allUsers.add(user);
And it is better to create getter and setters for attributes.
And you don't need to set the values to null in constructor, java does that for you.

You're setting attributes in the instance that's executing the method, but you're adding the new (empty) object to your array list. Thus the list is full of empty Users instances.

This code is a bit of a mess - it's doing too much stuff in one class. You have a class called Users, which has a list of Users and the attributes of a user. Each of the users inside the list will also have a list of users.
It seems like you should have two classes, one called Users, and one called User (or similarly named classes)
The Users class has the list of s and is responsible for populating that list (by reading in the file). Then the User class just holds onto information for a particular user, and any operation pertaining to a single user.
Then, when you read in the records, you can get the scanner (as you currently are doing), pass it to the User, then that particular user object will populate it's own fields (similar to what awesome said)

First I suggest you to put "System.out.print" statements while creating the USERS instance in read function to check if you are reading those values properly from the file. Second, Override toString() in Users class to display the values i.e.
public String toString() {
System.out.println("Name: "+name+", surname: "+surname+", DOB: "+dob+", Address: "+address+", Town: "+town+", Number: "+number+", and Position: "+position);
}
Now your System.out.println("" + user );
should display values read from the file.

Related

Simple employee records java program GUI remove button

I have a program GUI that the user enters ID#, First Name, Last Name, Salary, Start Date. After the user enters this information into a text area for each information need, the users clicks the add button which stores the information into an arrayList. After clicking add, the user presses a "list" button to output all the information entered into a Panel.
Array list to store users data:
public class EmploymentRecords extends javax.swing.JFrame {
ArrayList <Data> Output = new ArrayList <Data>();
Remove Button code:
private void btnRemoveActionPerformed(java.awt.event.ActionEvent evt) {
int index;
String id = txtID.getText();
boolean idCheck = Output.contains(id);
if (idCheck = true){
index = Output.indexOf(id);
Output.remove(index);
lblError.setText("Employee found and has been removed.");
}
else {
lblError.setText("Employee not found. Please try again.");
}
class Data:
class Data {
String id, firstName, lastName, salary, startDate;
Data (String _id, String _firstName, String _lastName, String _salary, String _startDate) {
id = _id;
firstName = _firstName;
lastName = _lastName;
salary = _salary;
startDate = _startDate;
Heres my problem: I want the user to be able to enter an id in the text area of the GUI where the program checks if that ID is entered before and totally removes all the data from the output screen and arraylist using just the ID. The code I entered above is not working for me and when I press the remove button nothing happens.
Please help as i would appreciate this... Thanks!
You are missing some code to share. But lets suppose your "add" functionality is working.
Lets also suppose that "String id = txtID.getText();" will be able to get the id for you as a string.
An obvious mistake is "if (idCheck = true)", as in java you compare with "=="
So maybe you can try to fix it that way and report the answer.
What you have done works alright for single entity objects within an ArrayList (like ArrayList<String> or ArrayList<Integer> for example) but not so good for multi-entity objects like what you have in your Data class. In other words, each element within your ArrayList is holding an instance of a class and all members related to it, not just a simple String or an Integer.
You will need to go a wee bit deeper in order to actually acquire the ID of any particular Data object instance for comparison to what someone has supplied within a GUI, for example:
private void btnRemoveActionPerformed(java.awt.event.ActionEvent evt) {
String id = txtID.getText();
boolean found = false;
for (Data data : Output) {
if (data.id.equals(id) {
found = true;
Output.remove(data);
clearFieldsInForm();
break;
}
}
if (found) {
lblError.setText("Employee was successfully removed.");
}
else {
lblError.setText("Invalid ID! Employee not found! Please try again.");
}
}
You will notice the clearFieldsInForm(); method use in the above code. This method would just set all pertinent form fields to Null String ("") which is essentially nothing:
private void clearFieldsInForm() {
txtID.setText("");
txtFirstName.setText("");
txtLastName.setText("");
txtsalary.setText("");
txtStartDate.setText("");
}

Iterator over TreeSet causes infinite loop

For this assignment, I'm required to save instances of a custom data class (called User) each containing 2 strings into a TreeSet. I must then search the TreeSet I created for a string taken from each line of another file. The first file is a .csv file in which each line contains an email address and a name, the .txt file contains only addresses. I have to search for every line in the .txt file, and I also have to repeat the entire operation 4000 times.
I can't use .contains to search the TreeSet because I can't search by User, since the .txt file only contains one of the two pieces of information that User does. According to information I've found in various places, I can take the iterator from my TreeSet and use that to retrieve each User in it, and then get the User's username and compare that directly to the string from the second file. I wrote my code exactly as every site I found suggested, but my program still gets stuck at an infinite loop. Here's the search code I have so far:
for (int i = 0; i < 4000; i++)//repeats search operation 4000 times
{
try
{
BufferedReader fromPasswords = new BufferedReader(new FileReader("passwordInput.txt"));
while ((line = fromPasswords.readLine()) != null)
{
Iterator it = a.iterator();
while (it.hasNext())
{
//the infinite loop happens about here, if I put a println statement here it prints over and over
if(it.next().userName.compareTo(line) == 0)
matches++; //this is an int that is supposed to go up by 1 every time a match is found
}
}
}
catch (Exception e)
{
System.out.println("Error while searching TreeSet: " + e);
System.exit(0);
}
}
For some additional info, here's my User class.
class User implements Comparable<User>
{
String userName;
String password;
public User() { userName = "none"; password = "none"; }
public User(String un, String ps) { userName = un; password = ps; }
public int compareTo(User u)
{
return userName.compareToIgnoreCase(u.userName);
}
} //User
I've done everything seemingly correctly but it looks to me like iterator doesn't move its pointer even when I call next(). Does anyone see something I'm missing?
Edit: Thanks to KevinO for pointing this out- a is the name of the TreeSet.
Edit: Here's the declaration of TreeSet.
TreeSet<User> a = new TreeSet<User>();
Are you certain there's an infinite loop? You're opening a file 4000 times and iterating through a collection for every line in the file. Depending on size of the file and the collection this could take a very long time.
Some other things to be aware of:
Later versions of Java have a more succinct way of opening a file and iterating through all the lines: Files.lines
You don't need an Iterator to iterate through a collection. A normal for-each loop will do or convert it to a stream
If all you want to do is count the matches then a stream is just as good
Putting all that together:
Path path = Paths.get("passwordInput.txt");
Set<User> users = new TreeSet<>();
long matches = Paths.lines(path)
.mapToLong(l -> users.stream()
.map(User::getName).filter(l::equals).count())
.sum();

Don't know how to add string to arraylist and make it stick

I'm new to java and I was trying to test what I've learned by creating a TestAddRemove program. Essentially it's supposed to make you choose one of two arrays and allows you to add a company name, remove a company name and read whether a company you're looking for is in one of the arrays.
My main problem is with the adding to the arrays part. Each time I add a company using the Add class it works, but then when I check the arrays again the arrays are empty.
Main Question: How do I add a companyName to an array in the main program and have it stick?
Here's my code:
public class TestAddRemove
{
static Scanner sc = new Scanner(System.in);
static ArrayList<String> fileOne = new ArrayList<String>();
static ArrayList<String> fileTwo = new ArrayList<String>();
:
: //Some other stuff
:
String tryAgain = "Y";
String answer;
String fileAnswer;
System.out.println("Welcome to the company tester; this program tests whether the company"
+ "you input is a company we already received donations from or a company we have"
+ "spoken to already, but declined to donate.");
while (tryAgain.equalsIgnoreCase("Y"))
{
System.out.println("Do you want to test, add or remove a company name? ");
answer = sc.next();
String companyName;
if (answer.equalsIgnoreCase("add"))
{
System.out.println("Which file do you want to add to?");
fileAnswer = sc.next();
if (fileAnswer.equalsIgnoreCase("fileOne"))
{
Add file = new Add(fileOne);
System.out.println("Enter the company name you want to add. ");
companyName = sc.next();
file.addCompany(companyName);
}
else
{
Add file = new Add(fileTwo);
System.out.println("Enter the company name you want to add. ");
companyName = sc.next();
file.addCompany(companyName);
}
The rest of the code is for the remove and test methods which I think I could understand once I understand how to add the companyName.
Here's the Add Class:
public class Add
{
Scanner sc = new Scanner(System.in);
ArrayList<String> file;
public Add(ArrayList<String> fileOne)
{
this.file = fileOne;
}
public void addCompany (String companyName)
{
file.add(companyName);
}
public ArrayList<String> getFile()
{
return file;
}
}
Any help on this would be awesome, thanks and cheers!
Running a Java application spawns a new JVM container. Such a container has its own memory in which it stores state for your program. When an application terminates, the JVM shuts down and discards all existing state. When you run the program a second time it runs in a different JVM totally unaware of any previous runs.
Regarding your problem, to access the list of companies created in a previous run, you need to add some sort of a persistence layer to your application like a database or a file in which you're able to store the companies.
The simplest solution would be to store the list in a text file, where each line represents one company, before the application shuts down and then load the file again when the application starts.

Why isn't my Arraylist class working? What am I doing wrong? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a task to create a tracking System of incoming phone calls with an option menu. Each phone call should belong to an ArrayList that displays the user's name and phone number. My first struggle was storing both a name (string) and number (double) in an ArrayList together. After playing around, this is what I came up with- BUT my third class remove and add method doesn't work? What is it I am doing wrong? I have looked online and at examples and I don't understand why remove and add methods do not work.
My third class: Where my problem is
public class Incoming {
Scanner input = new Scanner(System.in);
ArrayList<Person> arr = new ArrayList<Person>();
Person p1 = new Person("Alex", "01010101");
Person p2 = new Person("Emily", "0123812"); // I will have 10 people
void AddCall() {
System.out.println("Who would you like to add to the call? Enter p+number");
String add = input.nextLine();
Person.add(input);
}
void RemoveCall() {
System.out.println("Which call would you like to answer? Enter p+ caller position"); //NOTE following will be removed from queue
String remove = input.nextLine();
Person.remove(input);
}
void ViewCallerList() {
System.out.println("The queue has the following callers: " + Person);
}
}
Your Person class does not have any methods named add or remove, so you can't ever call Person.add or Person.remove. Instead, you should add and remove items to/from the list itself.
Since you're reading the caller data from the command prompt, you have to figure out which person is being referred to by the text that your user types in. Assuming they type in something like "John,555-5555", you can construct a new Person object for John based on that. Using String#split, split the text based on the position of the comma, and then create a new Person instance to add to your list of callers:
public class Incoming {
Scanner input = new Scanner(System.in);
List<Person> callers = new ArrayList<Person>();
Person p1 = new Person("Alex", "01010101");
Person p2 = new Person("Emily", "0123812"); // I will have 10 people
private static Person readPerson(Scanner sc) {
String callerText = sc.nextLine();
String[] callerData = callerText.split(",");
return new Person(callerData[0], callerData[1]);
}
void addCall() {
System.out.println("Who would you like to add to the call? Enter p+number");
callers.add(readPerson(input));
}
void removeCall() {
// Complete this based on the add method above
}
// This should output the list (callers), not a single person
void viewCallerList() {
System.out.println("The queue has the following callers: " + callers);
}
}

Loading information from file in different ways

My program currently has this working:
Bank bank = new Bank();
bank.openAccount(new CheckingAccount(10100, new Customer("First", "Last"),500.00,false));
bank.openAccount(new CheckingAccount(10101, new Customer("First", "Last"),2000.00,true));
bank.openAccount(new SavingsAccount(2010, new Customer("First", "Last"),5000.00,0.02));
Now I am trying to load this information from a file instead, but I ran into a bit of a wall. I want the new Customer information to include both the first and last name which are stored in separate index positions as separate variables, but while this will work:
new Customer[FIRST_INDEX],
I can't seem to get it to accept two index positions without creating a new Customer again. This is turn is causing issue with the method in Accounts where I'd like to keep the same format. How can I go about doing this?
public CheckingAccount(int accountNumber, Customer owner, double currentBalance, boolean freeChecks)
{
super(accountNumber, owner, currentBalance);
this.freeChecks = freeChecks;
}
Another problem I am running into is that the last index position can be one of two variables depending on if I am dealing with a checking account or a savings account:
private final static int FREE_CHECKS_INDEX = 4; // This loads a boolean
private final static int INTEREST_INDEX = 4; // This loads a double
Given this, I'm not entirely sure if my above approach would even work at all. The program is supposed to load either a Checking Account or Savings Account object, but since both types of accounts are stored in the same file I am wondering if I could read the last index position of each line of the text file before creating the object, but I'm not really sure how to go about doing that.
To be clear, I have this problem working perfectly without loading the data from the file, I am just unsure about the best approach for adapting it without having to rewrite all my other classes. Here's the new thing I am trying to do which I know isn't right:
protected static void loadAccountInformationFromFile() throws Exception
{
try ( Scanner fin = new Scanner(new File(INPUT_CUSTOMER_FILE)) )
{
String record;
String[] fields;
while ( fin.hasNext() )
{
record = fin.nextLine();
fields = record.split(",");
Bank bank = new Bank();
bank.openAccount
(
new CheckingAccount(Integer.parseInt(accountNumber[ACCOUNT_NUMBER_INDEX]),
new Customer[FIRST_INDEX, LAST_INDEX],
currentBalance[BALANCE_INDEX],
freeChecks[FREE_CHECKS_INDEX]
)
);
}
} catch (Exception e)
{
throw e;
} // end try
}

Categories

Resources