How do you add to an ArrayList using generics? - java

I'm struggling with an assignment of mine and I can't figure out how to add another element to my list.
import java.util.ArrayList;
public class Ballot {
private ArrayList<Candidate> ballot;
private String officeName;
public Ballot(String officeName) {
this.officeName = officeName;
ArrayList<Candidate> ballot = new ArrayList<Candidate>();
}
public String getOfficeName() {
return officeName;
}
public void addCandidate(Candidate c) {
ballot.add(c);
}
public ArrayList<Candidate> getCandidates() {
return ballot;
}
public static void main(String[] args) {
Ballot b = new Ballot("Election");
b.addCandidate(new Candidate("Sarah", "President"));
System.out.println(b);
}
}
When I try to run the document, it throws a NullPointerException. What am I doing wrong?

The constructor initializes a local variable named ballot that hides the data member with the same name. Then, when you try to add to it, it fails with a NullPointerException, since it was never initialized. If you initialize it you should be OK:
public Ballot(String officeName) {
this.officeName = officeName;
ballot = new ArrayList<Candidate>(); // Here!
}

You're not initializing your list of candidates properly in the Ballot constructor. You need to do:
this.ballot = new ArrayList<Candidate>();
Right now you're just creating a local variable named ballot in the constructor which shadows the actual class field. Since it has never been initialized, you end up getting a NullPointerException when you eventually try to add an element to it.
Also, as a best practice, use interfaces instead of the concrete type. This makes it easy to change implementations later. So instead of defining the field as private ArrayList<Candidate> ballot;, define it as private List<Candidate> ballot;.

As simple that you are not using this object. You are never initiliazing your object
Correct way
public Ballot(String officeName) {
this.officeName = officeName;
this.ballot = new ArrayList<Candidate>();
}

You're overriding your class variable with a local variable of the same name. Either initialize the list directly
private List<Candidate> ballot = new Arraylist<>();
or initialize it in the constructor with
ballot = new ArrayList<>();
FYI: You shouldn't assign implementation classes for your local variables and return values if you can help it. "ballot" should just be the List interface as should the getter. That way if you ever want to change the implementation, you don't have to change everything. It could be an ArrayList, LinkedList, Stack, Vector, etc and it won't matter because they're all using the List interface.

Related

Accessing Objects from ArrayLists

I have an arraylist of objects that I am sending from class "Testing" to class "Subjects", but can't access some of the methods in the Subjects class.
I would like to be able to simply send an arraylist of "Subject" objects (from the Testing class) to a method in the Subject class and be able to use other methods within the Subject class.
public class Subject {
private String subjectName;
private String courseCode;
//getters and setters for subjectName and courseCode
I can access the following method if I just call it from the Subject class, but not from the Testing class.
public String getDiscipline(){
int a = courseCode.length()-3;
String discipline = courseCode.substring(0, a);
return discipline;
}
In the method below, I can return and print objects and call the method I want, but only for one object...
public List<?> allDisciplines(ArrayList<?> inputSubjects){
for (int i = 0; i<inputSubjects.size(); i++){
System.out.println(inputSubjects.get(i)); //this returns all the
//objects, but why won't this work instead?: inputSubjects.get(i).getDiscipline();
}
//initialise new arraylist
List<String> dis = new ArrayList<>();
dis.add(getDiscipline()); //This works, but only for whatever single
//object I used to call the allDisciplines
//method with
//
return dis;
}
In another class , I pass the object array "subjects" into the allDisciplines method of the Subject class.
public class Testing {
public static void main(String[] args) {
// TODO code application logic here
Testing program = new Testing();
program.start();
}
public void start(){
//gets the data from a file, converts it into "Subject" objects with
//subjectName and courseCode
The following works because it's only sending one object through and I only get one result.
subjects.get(3).allDisciplines(subjects);
But if I try to access the allDisciplines method from the Testing class, I can't because it's not static and if I make the class static, it needs the private ints to be static which then don't change between iterations of my loops and I end up with the same value for fields.
allDisciplines(subjects); //does not work - can't see the allDisciplines
//method
I am not sure whether the problem is because I can't access the method outside of its class or because I am not properly referencing the objects in the arraylist.
Thanks for any help you can give me - I am quite confused!
I think the problem is the allDisciplines method. It should be static. You seem to not quite understand generics. I rewrote it for you:
public static List<String> allDisciplines(ArrayList<Subject> inputSubjects){
//initialise new arraylist
List<String> dis = new ArrayList<>();
for (Subject subject : inputSubjects) {
dis.add(subject.getDiscipline());
}
return dis;
}
I looped through the subjects passed in and added the discipline of each to a new array list and returned it. I also changed List<?> to List<Subject> because we are expecting the client code to pass a list of subjects.
Another shorter way to implement this:
public static List<String> allDisciplines(ArrayList<Subject> inputSubjects){
return inputSubjects.stream().map(Subject::getDiscipline).collect(Collectors.toList());
}
Now you can call allDisciplines by
Subject.allDisplines(subjects)
in Testing.

Cannot find Symbol error in Java - why?

I am having a hard time understanding the object oriented world. I am working on a homework assignment and I can't understand why I am getting an error here. The issue I am having is in the add method. I am using the Netbeans IDE (per professor requirement) and the problem I am getting is in the add method. There are two errors that both say "Cannot find Symbol"; one is in reference to the variable customers while the other is in reference to the variable numCustomer. I am trying to understand what I am doing wrong, not just how to fix it.
What I have so far:
package homework6;
/**
*
* #author christian
*/
public class Homework6 {
// Declare variables
private int numCustomers = 0;
private Customer customer;
// Constructor
public Homework6() {
Customer[] customers = new Customer[50];
}
/**
* #param args the command line arguments
*/
public void main(String[] args) {
System.out.println("Christian Beckman N00963294");
System.out.println("Homework 6");
System.out.println(); // Prints a blank line
// Create and instance of Homework6
Homework6 homework6 = new Homework6();
homework6.execute(args);
}
private void add(Customer customer) {
int i = 0;
customers[i] = customer;
i++;
numCustomer++;
}
private void displayCustomers() {
}
private void execute(String[] args) {
}
private int getTotal() {
}
private void readFile(String filename) {
}
}
Your variable is numCustomers with an 's' but your method refers to numCustomer++; without an 's'.
It should be:
numCustomers++;
For
private Customer customer;
it should probably be:
private Customer[] customers;
Be very careful in your code where you refer to customer and customers. It looks like you are using the convention "customer" for just one and "customers" for the array. If that is too subtle for you then consider changing to something like oneCustomer and allCustomers.
You create an array of Customer objects in the constructor, then the array is immediately destroyed. Try declaring it like this:
public class Homework6 {
// Declare variables
private int numCustomers = 0;
private int i = 0;
private Customer customer;
private Customer[] customers;
// Constructor
public Homework6() {
customers = new Customer[50];
}
...
The reason for this, is any variables declared inside a method (in this case, the constructor) has something called local scope which means it can ONLY be accessed inside that method. The variables you declare outside the methods have something called global scope, which means that variable can be accessed across all the methods in a class.
For the same reason as above, i will keep resetting to 0 each time you call the add function. To fix that, declare private int i = 0 above the constructor with the other variables. Then write the method like so:
private void add(Customer customer) {
customers[i] = customer;
i++;
numCustomers++;
}
Also, whenever you do numCustomer++ in the add method, you should put numCustomers++ like above because you declared numCustomers with an 's' at the end. Has to match EXACTLY.

adding and retrieving objects from a list

My goal is to have a list of cars as an Object so that, I can retrieve a Car from that list. As well as get details of the cars. Can someone point me to the right direction
What I have done so far.
Create a class called Car and have the variables CarNum, carName, carPlate;
generated getters and setters for the variables and a toString as the carName
Create a class called CarCollection as follows
.
public class CarCollection {
private List<CarItem> mCarList;
public void addVan(CarItem v) {
mCarList.add(v);
}
public List<CarItem> getCarList() {
return mCarList;
}
The following test doesn't work. Why?
public class TestCarCollectionprocess {
public static void main(String[] args) {
CarItem car1 = new CarItem();
car1.setmCarName("Pedro");
car1.setmCarNum(1);
CarItem car2 = new CarItem();
car2.setmCarName("Rene");
car2.setmCarNum(2);
CarCollection carList = new CarCollection();
carList.addCar(car1);
carList.addCar(car2);
System.out.println(carList.getCarList());
}
}
What I see from your code, you should get NullPointerException in addVan method since you didn't initialize List, so change it like this:
private List<CarItem> mCarList = new ArrayList<>();
You are trying to add a CarItem to the CarCollection's mCarList without ever instantiating the list so you should be getting a null reference exception. In your carCollection class, create a constructor that sets
mCarList = new List<CarItem>();

Best way to set an erray to empty within the parameters of another class

This class is where I want to call the arrays and set the arrays to empty within the parameters
public class ElectronicsEquipmentSupplier {
private int currentMonth;
private int currentYear;
private String rangeOfProducts;
private CustomerDetailsList details; //Contains the customer details array
private PurchaseOrderList pal; //Contains the purchase array
public ElectronicsEquipmentSupplier(int currentMonth, int currentYear,
String rangeOfProducts ) {
this.currentMonth = currentMonth;
this.currentYear = currentYear;
this.rangeOfProducts = rangeOfProducts;
}
}
This is the class where the array is created. It pulls information from a separate class called PurchaseOrder and then sets the list.
public class PurchaseOrderList {
private ArrayList<PurchaseOrder> purchaseCollection;
public PurchaseOrderList() {
purchaseCollection = new ArrayList<PurchaseOrder>();
}
The CustomerDetailsList class is essentially the same. Just not sure as to the best way to set the array to empty when called in the ElectronicsEquipmentSupplier.
Simply wrap the collection's own clear() method with a publicly-accessible method in your PurchaseOrderClass:
public class PurchaseOrderList {
private ArrayList<PurchaseOrder> purchaseCollection;
public PurchaseOrderList() {
purchaseCollection = new ArrayList<PurchaseOrder>();
}
//THIS IS THE IMPORTANT PART
public void clearPurchaseCollection() {
purchaseCollection.clear();
//You could also accomplish the same thing by reinitializing the list:
//purchaseCollection = new ArrayList<PurchaseOrder>();
}
}
Note however, that calling new PurchaseOrderList() already guarantees an empty purchaseCollection list, since you initialize it in the constructor that way.
So the only time you would need to call clearPurchaseCollection() is if you are reusing this object and want to clean it out first. Depending on the rest of your application, that may be necessary, but it may also just be simpler to throw away that instance and create a new PurchaseOrderList(). Totally depends on the situation.

Is there a difference between these two initialisation modes?

Let's say I have this:
public class Whatever {
private ArrayList<String> myList = new ArrayList<String>();
// more code goes here
}
or let's say I have this:
public class Whatever {
private ArrayList<String> myList = null;
public Whatever() {
myList = new ArrayList<String>();
}
}
What's the difference between these two initialisations of myList? Would it be wrong to preffer the first variant?
The first variant will always instantiate the array list, the second one only when calling the default constructor. Meaning for the second solution you will have to call the default constructor for any additional constructor you add e.g.
public class Whatever {
private final List<String> myList;
public Whatever() {
myList = new ArrayList<String>();
}
public Whatever(String name) {
this();
// Other stuff done
}
public Whatever(List<String> myList) {
this.myList = myList;
}
}
The (second) "lazy" initialization method might be better if you don't always use the list (e.g. if you set the list in another constructor directly like in my example) and want to avoid creating unnecessary objects. (EDIT: I changed the ArrayList to an interface and set it final. It wasn't part of the question but it is - as mentioned in the comments - the best way to use List collections).
The JVM first executes code such as this (outside the constructor):
public class Whatever {
private ArrayList<String> myList = new ArrayList<String>();
// more code goes here
}
And only then code such as this (inside the constructor):
public class Whatever {
private ArrayList<String> myList = null;
public Whatever() {
myList = new ArrayList<String>();
}
}
So unless the order of execution is somehow important to you i guess #Daff's answer is the right one.
In this particular example, there is no difference except that the first form is shorter.
However, if the attribute initialization expression (potentially) throws exceptions, the second form allows you to catch the exceptions, or declare them as thrown in the constructor signature.
And of course, if you have multiple constructors, the second form allows you to initialize the attribute differently in each constructor ... or use constructor chaining to initialize the attribute the same ... or mix the two styles of initialization.

Categories

Resources