Saving an object which contains arraylists in arraylists - java

I have an object of type Restaurant called myRestaurant which contains EmployeesAList, MenuAList and OrdersAList, each of which storing instances of objects Employee, Menu_Item and Order. Each instance of Order stores integers, strings and an arraylist of integers.
When I save myRestaurant, every arraylist is saved except for the arraylist which is within the Orders class.
Any suggestions?
save method in Runner
public boolean SaveToFile(Restaurant myrest)
{
try
{
File outFile = new File("etrest.rest");
//creates object representing file
FileOutputStream outFileStream = new FileOutputStream(outFile);
//connection between program and file
ObjectOutputStream outObjectStream = new ObjectOutputStream(outFileStream);
//class which is used to pass objects which will be saved to file
//Write serializable ArrayList to file
outObjectStream.writeObject(myrest);
//output done, so close the stream
outObjectStream.close();
return true;
}
catch(IOException IOE)
{
System.out.println(IOE.toString()); //debug purpose
return false;
}
}
method in Restaurant to add Order
ArrayList OrdersAList = new ArrayList();
public void AddOrder(Order o)
{
OrdersAList.add(o);
}
part of order class
ArrayList Menu_ItemsIDAList = new ArrayList();
public Order()
{
paid = false;
WaiterNo = 0;
TableNo = 0;
item = 0;
}
public Order(boolean pd, int wN, int tN, int it)
{
paid = pd;
WaiterNo = wN;
TableNo = tN;
item = it;
}
//MENU ITEMS ENTERED PER ORDER
public void AddMenu_ItemID(int item)
{
Menu_ItemsIDAList.add(item);
}
when i create an instance of Order I create a loop to populate the Menu_ItemsIDAList

I can't exactly reconstruct your problem...
You/we should have a better overview where your lists will be saved exactly, and where is your "add"-method? In which class...
So I recommend to you, making a diagram. In your case a UML class diagram (http://en.wikipedia.org/wiki/Class_diagram).
Once you understand the classes, attributes and relations then you can draw such a diagram and can use the code in a proper way.
Of course we could give you a quick solution that "something is missing"... but for future development you should understand basics of object oriented programming. UML class and UML use case diagrams are a good start too...

Related

Creating a Mutable ArrayList to save Input Text in Android Studio

I am a true beginner to programming, so forgive me.
I have a String Array filled with a set of quotes that I have a method randomly picking one to display on the screen. This all works perfectly, I'd like to take the next step now. I would like to have the ability to add text to this array that a user inputs on an Activity that I have created. I understand that Arrays are Immutable, but I am failing to figure out how to create an ArrayList, pre-fill it with my 50ish quotes and then have the ability to add more through the app later.
Here is the code I currently have...
public class FactBook {
public String[] mFacts = {
"Quote 1.",
"Quote 2.", };
public String getFact() {
String fact = "";
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(mFacts.length);
fact = mFacts[randomNumber];
return fact;
}
References
ArrayList
Arrays
import java.util.ArrayList;
import java.util.Arrays;
public class FactBook {
// Public data members are not recommended.
// Make it at least protected and arrange controlled access to it
// by specific methods
public ArrayList<String> mFacts =
new ArrayList<String>(
Arrays.asList("Quote 1.", "Quote 2.")
)
};
public String getFact() {
String fact = "";
// Do you need to create a new Random every time?
// Perhaps creating it only once and storing it in a static
// (class wide) data member will be just as good: create it once,
// reuse it later.
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(mFacts.size());
fact = mFacts.get(randomNumber);
return fact;
}
// how to add
public void add(String newQuip) {
// Don't accept null or "all-white character" quotes
if(null!=newQuip && newQuip.trim().length()>0) {
this.mFacts.add(newQuip);
}
}
}
Look at Arrays class.
It has a helper method exactly for those cases:
List<String> facts = Arrays.asList("string1", "string2", ...);
Here's a simple method that pre-populates an ArrayList with your values, and then allows you to add more values to it later on
private ArrayList<String> createPrePopulatedList() {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Quote 1.");
///Add any more you want to prepopulate like this
return arrayList;
}
You can call this method like so.
private ArrayList<String> myArrayList = createPrepopulatedList();
Now you can simply add whatever you want to it dynamically with add().
You should probably do some reading on Java data structures before you jump into Android programming. Here's some help with ArrayList https://www.tutorialspoint.com/java/java_arraylist_class.htm

How to store data in an index in an ArrayList into Arrays in Java

I am new to Java and I am trying to do a calculation using values within a txt file. I have read the txt file, which has 3 tabs, each with three values
I have been able to read the file and get the columns as indices but cannot add the separate values into array. So I want three separate arrays
Read file method
public void read()
{
try
{
FileReader read = new FileReader(file);
String line = null;
while((line = FileReader.readLine()) != null)
{
a.add(line);
}
}
catch (FileNotFoundException e) {}
catch(IOException e) {}
}
Processing method
private void processor () {
for (String li : a)
{
String[] data = li.split("\\s");
Index = Double.parseDouble(data[0]);
Customers = Double.parseDouble(data[1]);
rateOfBuy = Double.parseDouble(data[2]);
}
}
I dont think you are thinking about your data structures correctly. If I were you I would think about this a little differently. To me it makes the most sense just to use a simple array. To handle the complexity of the three columns, I would create a new class called CustomerRate or something to that effect. I would then make the data into instance variables belonging to instances of that class. That way you could just have a simple array of CustomerRate objects and then access the data stored by each of those objects. This will probably be a lot simpler to deal with overall too.
I am not sure exactly what you are trying to accomplish but I'll do my best to help
You would create your new class to be something like this:
your new class:
//This is your new class
public class CustomerRate {
private int person;
private double rate;
//constructor
public CustomerRate(int person, double rate) {
this.person = person;
this.rate = rate;
}
//add appropriate getters and setters and whatever else you need
public double getRate() {
return rate;
}
}
Use the data your parse from your file to create new CustomerRate Objects. Create an array of your objects. Note that this is just an example with one entry with random numbers I'm going to use so you will have to get the loop and parse working:
//creating an example customer
CustomerRate customer1 = new CustomerRate(100, 0.5);
//create your collection to store your customer data that you will add/parse
List<CustomerRate> myList = new ArrayList<CustomerRate>();
//adds to list
myList.add(customer1);
//gets element at index and then grabs the rate
double exampleCustomerRate;
exampleCustomerRate = myList.get(0).getRate();
I coded this quickly so I may have made some mistake but I hope that gives you the general idea of what you should do.
You just need another ArrayList to store your rateOfBusiness. Something like this:
String file = "test.txt";
ArrayList<String> a = new ArrayList<String>();
ArrayList<Double> rateOfBusiness = new ArrayList<>(); //Define with your other fields
Then loop through your data and do the math while adding to the array
private void process () {
for (String li : a)
{
String[] data = li.split("\\t");
Index = Double.parseDouble(data[0]);
Customers = Double.parseDouble(data[1]);; //per year
rateOfBuy = Double.parseDouble(data[2]); //per year
rateOfBusiness.add(Customers*rateOfBuy); //Do math and store for that customer
}
}
Edit: Even though this solves your problem, I would look into learning some Object Oriented principles. IsaacShiffman (or Lvl 9 Oddish, or whatever his name is) has a start on how you would solve this going that direction. Makes your code a lot easier to follow and debug.

Java - Add an object to an arraylist, then adding another to the arraylist causes the first element to be overwritten

I'm currently doing my third year programming project and its a folio tracker. :/ I have crated Stock_API and Portfolio_API interfaces (and implementations of them) and a GUI class which when instantiated takes two parameters as so:
public GUI(Portfolio_API p, Stock s){
tempPort = p;
tempStock = s;
}
I use this constructor as a way of getting implementations of these interfaces into the GUI without exposing the implementation to the GUI (which is one of the main objectives of this project). A portfolio object has a name(string) and an ArrayList. A stock object has a ticker symbol(string), a stock name(string), a share value(float), a number of shares(int) and a value of holding(float).
In the GUI i have a portCollection array list which holds objects of type portfolio_API and this is so the system can keep track of multiple portfolios. Also as mentioned in the block of code above has a tempStock and tempPort object.
Sorry to give u so much detail about the program but i thought it best so i could get the context across. Anyway, the problem at hand. I have a method which uses the GUI to get a ticker symbol, a stock name and a number of shares and adds the stock to the current portfolio open(each portfolio has its own tab). The method looks like this:
public void addStock() {
int num_shares = 0;
float dailyChange = 0.0f;
float stockValue = 0.0f;
boolean succeed = true;
// GUI gets information of stock from user
String ticker = JOptionPane.showInputDialog(frame,
"Enter the ticker symbol:");
String stockName = JOptionPane.showInputDialog(frame,
"Enter the Stock name:");
try {
num_shares = Integer.parseInt(JOptionPane.showInputDialog(frame,
"Enter the number of shares:"));
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(frame,
"Number of shares was not an integer. Try again");
succeed = false;
}
// If parsing was successful...
if (succeed) {
tempStock.setTicker(ticker);
tempStock.setNumberOfShares(num_shares);
tempStock.setStockName(stockName);
// Fetches newest value using the current ticker symbol
boolean succeedUpdate = tempStock.updateShareValue();
if (succeedUpdate) {
tempStock.calculateValueOfHolding();
// Adds to the current portfolio...
String tabName = tabbedPane.getTitleAt(tabbedPane
.getSelectedIndex());
System.out.println(tabName);
findPortfolio(tabName).addStock(tempStock);
findPortfolio(tabName).sort();
// ...Then adds it to the table
JPanel j = (JPanel) tabbedPane.getSelectedComponent()
.getComponentAt(0, 0);
JViewport v = ((JScrollPane) j.getComponent(0)).getViewport();
JTable table = (JTable) v.getComponent(0);
float currentTotal = findPortfolio(tabName).getTotal();
// Updates the total label
((JLabel) j.getComponent(1)).setText("Total: " + currentTotal);
Object[] newStock = { tempStock.getTicker(),
tempStock.getStockName(),
tempStock.getNumberOfShares(),
tempStock.getShareValue(),
tempStock.getValueOfHolding() };
((DefaultTableModel) table.getModel()).addRow(newStock);
}
}
}
When I add more than one stock, the new stock takes place of the old one an effectively overwrites it. I think its the reuse of tempStock that is doing it. Not sure why though as surely if i add the variable to an arraylist it becomes part of that arraylist and needs no association with the tempStock variable?
Methods that are used with the mentioned arraylists :
private Portfolio_API findPortfolio(String name) {
Portfolio_API p = null;
for (int i = 0; i < portCollection.size(); i++) {
if (portCollection.get(i).getName() == name) {
p = portCollection.get(i);
}
}
These two are in the Portfolio class:
#Override
public boolean addStock(Stock_API s) {
if (!doesExist(s)) {
portfolio.add(s);
return true;
} else {
return false;
}
}
#Override
public boolean doesExist(Stock_API s) {
boolean found = false;
for (int i = 0; i < portfolio.size(); i++) {
if (portfolio.get(i).getTicker() == s.getTicker()) {
found = true;
}
}
return found;
}
I've only come here for help because i have hit a brick wall and I really need help. If anyone could give me any suggestions, i'd be eternally in your debt.
Thanks,
Chris
Yes, I think you are right when you say you think it's because you're reusing the tempStock variable. This variable still references the original object so calling setTicker() etc on tempStock also changes the object referenced by your ArrayList because it's the same object. Try reinitialising your tempStock and see if it makes a difference:
// If parsing was successful...
if (succeed) {
tempStock = new Stock(); // or however you instantiate this object
tempStock.setTicker(ticker);
tempStock.setNumberOfShares(num_shares);
tempStock.setStockName(stockName);
Thanks guys for all your input. #oracle certified professor helped with the stock problems after adding an overloaded method for addStock but turned out the same problems plagued portfolio.
What I did was create a makePortfolio method in Portfolio_API to create a new portfolio and return it. That way it avoids any nasty overwrite, gonna add it to stock too just now.
Thanks again guys. Good night! :)

Deserializing Data in Java

I'm trying to read in player data from an array list, but after 2 hours of searching and experimenting, I'm lost.
Here's the deserializing code. It's commented, but basically there should be a file with a Serialized ArrayList of Player objects. I want to deserialize that data and store it in savedPlayers, and then use savedPlayers for a few things.
What did I do wrong?
import java.io.*;
import java.util.*;
public class RoofRunnerApp {
private Scanner in; // Scanner to take playerName input.
private RoofRunnerGame gameTime;
private String filename = "gameData.txt";
public static void main (String[] args) {
System.out.println("WELCOME TO *ROOF RUNNER* \n"); // Welcomes user with game title.
RoofRunnerApp myGame = new RoofRunnerApp();
}
public RoofRunnerApp() {
// 1) Read in name from user.
in = new Scanner(System.in);
System.out.print("Please enter your name: ");
String playerName = in.next();
// 2) Create Player arrayList.
ArrayList<Player> savedPlayers = new ArrayList<Player>();
// 3) Read in Serialized Data from file.
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename)); // Add file name.
savedPlayers = (ArrayList<Player>)input.readObject();
input.close();
} catch( Exception e ) {
e.printStackTrace();
return;
}
Player thisPlayer; //thisPlayer is passed to Game class.
// 4) if arraylist != empty -> Check for playerName and inputName match.
////// If there's a match -> Set thisPlayer equal to the savedPlayer, using the Player constructor.
if(savedPlayers.length() != 0)
for(int i = 0; i < savedPlayers.length(); i++)
if(playerName.equals(savedPlayers.getName())){
thisPlayer = new Player(savedPlayers[i]);
break;
}
}
else
thisPlayer = new Player(playerName); // If no match -> Set thisPlayer to new player with playerName.
RoofRunnerGame gameTime = new RoofRunnerGame(thisPlayer);
}
I know I'm not supposed to answer, but it's not letting me edit.
UPDATE/QUESTIONS
I haven't serialized any data, yet. Right now I'm just trying to set up the deserialization (and I was going to add in serialization after). But, in Eclipse, when I try the above I get several error messages saying that savedPlayers is not an arrayList and that length() doesn't work on it.
Here's the class code. (The code near the bottom is still in the works. My errors happen in lines 33-37:
import java.io.*;
import java.util.*;
public class RoofRunnerApp {
private Scanner in; // Scanner to take playerName input.
private RoofRunnerGame gameTime;
private String filename = "gameData.txt"; // File to hold Serialized Player data.
public static void main (String[] args) {
System.out.println("WELCOME TO *ROOF RUNNER* \n"); // Welcomes user with game title.
RoofRunnerApp myGame = new RoofRunnerApp();
}
public RoofRunnerApp() {
// 1) Read in name from user.
in = new Scanner(System.in);
System.out.print("Please enter your name: ");
String playerName = in.next();
// 2) Create Player arrayList.
ArrayList<Player> savedPlayers = new ArrayList<Player>();
// 3) Read in Serialized Data from file.
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename)); // Add file name.
savedPlayers = (ArrayList<Player>)input.readObject();
input.close();
} catch( Exception e ) {
e.printStackTrace();
return;
}
Player thisPlayer; //thisPlayer is passed to Game class.
// 4) if arraylist != empty -> Check for playerName and inputName match.
////// If there's a match -> Set thisPlayer equal to the savedPlayer, using the Player constructor.
if(savedPlayers.length() != 0)
for(int i = 0; i < savedPlayers.length(); i++)
if(playerName.equals(savedPlayers[i].getName())){
thisPlayer = new Player(savedPlayers[i]);
break;
}
}
else
thisPlayer = new Player(playerName); // If no match -> Set thisPlayer to new player with playerName.
RoofRunnerGame gameTime = new RoofRunnerGame(thisPlayer);
// After:
// Exit code in RRG
// 1) Add current Player to current ArrayList.
/*
// Create/Return player objects.
Player p = new Player(playerObject)
savedPlayers.add(p);
///// Save data to file.
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream( new FileOutputStream( "myfile") ); // Add filename.
out.writeObject( savedPlayer ); //write the entire ArrayList
out.close();
} catch( IOException e ) {
e.printStackTrace();
return;
}
*/
}
}
You have to serialize out the object first before you can read it. The format used by ObjectInputStream/ObjectOutputStream is not something you can type out. As such you should with the saving of the objects first into a file, then read them in. So write a class that does the writing and reading of the List first in a class of its own and test that out to get a feel for object serialisation and some of the problems. Test things like no file present, empty file, file with corrupt data, files with a valid list with zero entries etc.
As to your current implementation where you are catching the IOException for the reading you should not printStackTrace and return, its a normal valid case as the file does not currently contain a valid list. So instead you should do nothing in the catch so that the program continues on.
You may also find that the ObjectInputStream is returning null for the savedPlayers variable and you'll want to check that case before you assign the value to the savePlayers variable in that same reading code.
I fixed the code formatting. I assume you're a bit new to java. The error you get about savedPlayers is not that it is not an ArrayList but that it is not an array. You can't index it like savedPlayers[i] but must use savedPlayers.get(i), where i is the index. Your main problem seems to be the difference between an ArrayList and an array. An array is a primitive construct, while an ArrayList is a type built on top of an array. An actual array would have a length property (note: not a method!), while ArrayList has a size() method. Look up arrays in the java tutorial.
It's considered best practice to refer to types using the most general interface that still supports what you do, in this case that would be List. If you're new to java it really helps to have the API documentation handy. Look up List and ArrayList in there. You might even use Collection if you don't really care that order is preserved here, i.e. when you output a list to disk initialise it as:
Collection<Player> players = new ArrayList<Player>();
Collection doesn't have positional access though, so stick to List if you need that.
Another tip, you're using a for-loop to iterate over all the players, but collections such as List have iterators for this. It's generally more efficient when not using an ArrayList. There is a for-loop construct that you can use to iterate over all objects in a collection:
for (Player player : players) {
// do something with each Player
}
Sorry for not editing again. I'm changing computers constantly. Anyways...
Why do you say you have to serialize the objects first? I'm trying to do this:
Have user enter his playername.
Check the gameData file to see if any data with that player's name has been saved.
If player name matches one in file -> create a Player object (thisPlayer) with that data.
If player name has no matches || file is empty -> create a Player object (this Player) with just that name and new data.
Then it would run the game.
THEENNN it would serialize the data and save it to the file.
It seems to me you have to deserialize the input at the beginning when loading data, and then serialize at the end when saving data, yeah?
Here's the code now. There's one error in the whole file. It says that thisPlayer may not have been initialized in line 46. Any ideas?
import java.io.*;
import java.util.*;
public class RoofRunnerApp {
private Scanner in; // Scanner to take playerName input.
private RoofRunnerGame gameTime;
private String filename = "gameData.txt"; // File to hold Serialized Player data.
public static void main (String[] args) {
System.out.println("WELCOME TO *ROOF RUNNER* \n"); // Welcomes user with game title.
RoofRunnerApp myGame = new RoofRunnerApp();
}
public RoofRunnerApp() {
// 1) Read in name from user.
in = new Scanner(System.in);
System.out.print("Please enter your name: ");
String playerName = in.next();
// 2) Create Player arrayList.
ArrayList<Player> savedPlayers = new ArrayList<Player>();
// 3) Read in Serialized Data from file.
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(filename)); // Add file name.
savedPlayers = (ArrayList<Player>)input.readObject();
input.close();
} catch( Exception e ) {
e.printStackTrace();
return;
}
boolean notFound = true;
Player thisPlayer; //thisPlayer is passed to Game class.
// 4) if arraylist != empty -> Check for playerName and inputName match.
////// If there's a match -> Set thisPlayer equal to the savedPlayer, using the Player constructor.
if(savedPlayers.size() != 0){
for(int i = 0; i < savedPlayers.size(); i++){
if(playerName.equals(savedPlayers.get(i).getName())){
thisPlayer = new Player(savedPlayers.get(i));
notFound = false;
break;
}
}
}
if(savedPlayers.size() == 0 || notFound)
thisPlayer = new Player(playerName); // If no match -> Set thisPlayer to new player with playerName.
RoofRunnerGame gameTime = new RoofRunnerGame(thisPlayer);
}

incorrect Vector.size() returned

I'm implementing a Graph which holds "Book" objects as its nodes. The nodes are connected if the books share a keyword. The keywords for each book are held in a Vector within the Book class. To do this, I've created 3 classes.
1) Books 2) Vertex 3) Graph
The Vertex class holds the Book object and also has a Vector containing all the other Vertex objects (other books which share a keyword). In the Driver, I create the book, pass it to a Graph which then inserts it into a Vertex and finally the Vertex into a Vector named "bookGraph".
public final class Graph {
private Vector<Vertex> bookGraph = new Vector<Vertex>();
private int bookCounter = 0;
public Graph() {
}
public void addBook(Book bk) {
Vertex vtx = new Vertex(bk);
bookGraph.add(vtx);
bookCounter++;
System.out.println("Book #1 has " + bookGraph.get(0).getBook().getKeywords().size() + " keywords");
// addAdjVertices();
}
public void showKeywords() {
System.out.println("Book #1 is " + bookGraph.get(0).getBook().getKeywords().size() + " keywords");
}
The information from the books are read from a file in the Driver and inserted into a book object. I'm trying to make sure that this information is read in correctly and properly inserted into the Graph. My problem occurs when trying to get the size of the keyword Vector within the "showKeywords()" method in the Graph class. bookGraph.get(0).getBook().getKeywords().size() returns 0 when the exact same command in the addBook() method returns the correct size. I've implemented accessor methods such as getTitle() or getAuthor() in the Book class and those work correctly within the showKeywords() method. The keyword vector seems to be the only issue within the showKeywords() method. What am I doing wrong here?
Here is my Driver class....
boolean fileopen = false;
String title, author, keys;
long isbn_number;
Vector<String> keywords = new Vector<String>();
String filename = "books.txt";
String[] keywordTokens;
Scanner fin = null;
Scanner input = new Scanner (System.in);
Graph books = new Graph();
try {
fin = new Scanner (new FileReader(filename));
String fline;
fileopen = true;
System.out.println("Reading books.txt...");
while (fin.hasNextLine()) {
fline = fin.nextLine();
title = fline;
fline = fin.nextLine();
author = fline;
fline = fin.nextLine();
isbn_number = Long.parseLong(fline);
fline = fin.nextLine();
keywordTokens = fline.split(",");
for (int x = 0; x < keywordTokens.length; x++) {
keywords.add(keywordTokens[x]);
}
Book tempBook = new Book(title,author,isbn_number,keywords);
books.addBook(tempBook);
keywords.clear();
if (fin.hasNextLine()) fline = fin.nextLine();
}
books.showKeywords();
System.out.println("Ready.");
}
catch (FileNotFoundException e) {
System.out.println("FILE NOT FOUND!");
}
Looks to me like it should work - there's nothing obviously wrong (like accidentally using static variables). Can you provide a short but complete program which demonstrates the problem? The error is likely to be somewhere else - are you calling setKeywords(new Vector<String>()) somewhere, for example?
Any reason for using Vector rather than the more common ArrayList by the way? I would also suggest that setKeywords(String key) should probably be called addKeyword instead...
EDIT: Okay, now that you've posted the code it's obvious: you're only ever creating a single instance of Vector. You're then reusing that instance for every line, and clearing it at the end.
Just declare your keywords variable inside the loop, create a new instance on every iteration, and don't clear it afterwards.
To make your code as readable as possible (and avoid this sort of thing) I would suggest you declare every variable at the point of first use wherever possible, with the narrowest possible scope.
Could you try this snippet and check whether the error is still there:
public void test() {
Vector<String> keywords = new Vector<String>();
keywords.add("keyword");
Book bk = new Book("Author", "Title", 12345, keywords);
Graph bookGraph = new Graph();
bookGraph.addBook(bk);
bookGraph.showKeywords();
}
I think you got lost in your graph of objects :) I suggest to use unit tests to determine how your code should behave and to make sure it actually does behave the way you expect. The tests can build small examples and then check the various getters to see whether they return the correct results.
For what do you need the copy constructor Book(Book)? Perhaps you put copies of the books instead of the books itself into your collection?

Categories

Resources