JTable with file i/o and array list - java

In my program users input words along with their corresponding definition.
An example of this user defined object is [countenance, a person's face].
The user's words are stored in an array list which works with file i/o.
However, each time I call the "prepareTable" method, the program
adds duplicates of the words found in the text file to the array list. If you need to see more code, I can post it but for convenience/readability I only posted the prepareTable method. Why is my program duplicating the words? Is there something wrong with this method?
public void prepareTable ()
{
readFromFile();
for (int i = 0; i <= LibraryWordsList.size() - 1; i++)
{
tableData.setValueAt(LibraryWordsList.get(i).getWord(), i, 0);
tableData.setValueAt(LibraryWordsList.get(i).getDefinition(), i, 1);
}
}

If tableData refers to an instance of DefaultTableModel, you can invoke setRowCount(0) to clear the previous entries before adding new ones. You can get a reference to the table's TableModel by using the table's getModel() method.

Related

Transporting values in arrays within scopes in Swing - java

my goal is to be able to draw graphs and then save its values if required.
In the image above, I choose from the comboBox a specific type of graph to draw, except for Clear, which just clears the graph that is shown. This is already working correctly.
I have an arrayList of UserPattern(I created) objects that contains a string, a double and a double array.
I want to store the values from the graph in some variable (i'm currently using a double array) to use it later on.
With the double array I've had problems with the passing of values, since when I press "Save Pattern" it keeps the latest values of the graph (the last graph shown) and inputs it on every element of the UserPattern List that I have previously saved. So, even if I save multiple patterns, they all keep the value of the last save.
This is the code I use to store the values in the ArrayList:
private void readAndInsertPatternValues(List<UserPattern> patternLi, double[] graphValue) {
UserPattern tempUserPattern = new UserPattern(typePattern);
//extra code
tempUserPattern.setMonthlyConsump(consTemp);
tempUserPattern.setNameID(patternName);
tempUserPattern.setPatternValues(graphValue);
patternLi.add(tempUserPattern);
System.out.println("Inserted: ");
System.out.println(tempUserPattern);
}
}
I call this method within a mouse event on the button "Save Pattern":
JButton btnSaveUserPattern = new JButton("Save Pattern");
btnSaveUserPattern.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(!((comboBoxPattern.getSelectedItem()).equals(UserPattern.PatternType.CLEAR)))
readAndInsertPatternValues(patternList, patternValue);
for(UserPattern upTemp : patternList) {
System.out.println("Inside the Pattern List:");
System.out.println(upTemp.toString());
}
}
});
btnSaveUserPattern.setFont(new Font("Tahoma", Font.PLAIN, 13));
btnSaveUserPattern.setEnabled(false);
Also, I get the values that create the graph in the event from selecting an option of the combobox:
comboBoxPattern = new JComboBox<UserPattern.PatternType>();
comboBoxPattern.setFont(new Font("Tahoma", Font.PLAIN, 13));
comboBoxPattern.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//this method creates the graphs, so I send the array "patternValue" to "get" the values.
printPatternGraph(comboBoxPattern, chartPanel, "User Pattern for Energy Consumption", "Hours", "Energy Consumption(Wh)", true, patternValue);
btnSaveUserPattern.setEnabled(true);
}
});
I initialized the patternValue array as a local variable in the method that calls and uses the above mentioned methods as such:
double[] patternValue = new double[1440];
With all this, happened the problem in transporting values. At the "insertion time", the console showed the correct values, however, when I clicked on the "Save Pattern" button, which shows all the objects in the UserPattern list, the graph values from the previously saved graphs were equal to the one I saved last. (The last one I saved corrupted all the others).
I tried to change the way of passing values and changed the method "printPatternGraph" to return a double[] array, and made like this:
patternValue=printPatternGraph(comboBoxPattern, chartPanel, "User Pattern for Energy Consumption", "Hours", "Energy Consumption(Wh)", true);
This, however, brought me the error,
Local variable patternValue defined in an enclosing scope must be final or effectively final.
Therefore, I tried making "patternValue" a global variable . This actually solved the problem, but I don't think that this is the best solution (I've read multiple times that global variables are "bad coding".
This way, which way do you think I should implement this?
Thanks for your attention and sorry for the long post,
nhekas
SOLUTION:
I understood what was wrong! Sorry to bother you guys.
My problem, was, that when I added the double array to the ArrayList, I did it like this:
patternLi.add(graphValues);
This, instead of storing the values inside the graphValue array, was storing the reference to it. Therefore, when I wanted to create a different graph, the reference to the graph was the same, but changed the values.
I had to do the following:
new double[] arrayTemp= new double[1440];
for ( int i=0; i<1440;i++) {
arrayTemp[i]=graphValues[i];
}
patternLi.add(arrayTemp);
This way, it worked! Because, since arrayTemp is local, is created everytime I call the method and passes the correct values.
Thanks for all your input guys !
nhekas

How to search an array of objects and then update a part of the object in java?

I have an Array of objects. Each object is a customer record, which is the customer ID (int), first name (String), last name(String), and balance (double).
My problem is that i am not supposed to have duplicate customer records, so if they appear in the file twice, I have to just update their balance. I cannot figure out how to search the array to find out if i need to just update the balance or make a new record in the array.
I feel like i should do this in the get/setters, but i am not exactly sure.
edit: to clarify on "if they appear in the file twice, I have to just update their balance." I have a file i made in notepad which is supposed to be a customer list, which has all of their information. if the same customer shows up twice, say the following day to buy more stuff, i am not supposed to create a new object for them since they already have an object and a place in the array. instead, i am supposed to take the amount they spent, and add it to their already existing balance within their existing object.
edit2: i thought i would give you the bit of code i have already where i read in the values into the array. i based this off of the example we did in class, but we didn't have to update anything, just store information into an array and print it if needed.
public CustomerList(){
data = new CustomerRecord[100]; //i'm only allowed 100 unique customers
try {
Scanner input = new Scanner(new File("Records.txt"));
for(int i = 0; i < 100; ++i){
data[i] = new CustomerRecord();
data[i].setcustomerNumber(input.nextInt());
data[i].setfirstName(input.next());
data[i].setlastName(input.next());
data[i].setTransactionAmount(input.nextDouble());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
You shouldn't be using arrays in that case. A Set would be much more suitable as it, by definition, does not have duplicate entries.
What you need to do is to implement the equals() and hashCode() methods in your Customer class so they only use id (or id and name fields) but not balance.
If for some reason you need to use arrays you have two options:
sort the array and use binary search to find if the customer is there, this is nice if the array doesn't change much but you're doing a lot of updates
simply do a linear scan of the array, checking each entry to see if a given customer is already there, if so then update the balance, otherwise add it as a new entry
It would be something like:
public void updateOrAdd(Customer cst) {
boolean exists = false;
for(Customer existing : array) {
// !!! You need to implement your own equals method in the
// customer so it doesn't take into account the balance !!!
if(existing.equals(cst)) {
exists = true;
existing.updateBalance(cst.getBalance());
break;
}
}
if(!exists) {
// add the cst to the array
}
}
The difference is in runtime, the set solution will be constant O(1) on average (unless you incorrectly implement your hashCode() method).
Suppose you have a Customer array:
Customer[] customers = new Customer[size];
... // fill the array with data
Then you get a new customer object called newCustomer. You need to search for newCustomer in your array and, update it if it is already there, or add it if it's not. So you can do something like this:
// Return, if it exists, a customer with id equal to newCustomer.getId()
Optional<Customer> existingCustomer =
Arrays.stream(customers)
.filter(c -> newCustomer.getId().equals(c.getId()))
.findFirst();
if (existingCustomer.isPresent()) {
// update the customer object with newCustomer information as appropriate
Customer customer = existingCustomer.get();
// assuming you have an updateBalance() method
customer.updateBalance(newCustomer.amountSpent());
} else {
// if the customer is not in the array already, add them to the current position
customers[currentIndex] = newCustomer;
}

Runtime errors when attempting to delete and shift array of object in GUI interface

My project consists of 2 class files and a test application GUI interface to use the data. The two class files, both created by me, are ToolItem (defines a hardware tool with get() and set() methods, display() method, etc) and HardWareStore, which is used to manipulate the data and place it into an array using methods like insert(), delete(), searchArray() ect.
The GUI interface, which includes the same relative buttons (insert, delete) calls HardWareStore when the corresponding button is pressed.
So far everything works perfectly EXCEPT the delete button/delete() method. My methods are as follows, including the searchArray() method I created which is used inside delete() to evaluate a unique ID and determine if the ID already exists or not:
searchArray:
public int searchArray(int id)
{
for (index = 0; index < toolArray.length; index++)
{
if (toolArray[index].getToolID() == id)
{
System.out.println("ID found at location " + index);
return index;
}
}
return -1;
}//end searchArray
delete:
public int delete(int ID)
{
testArray = searchArray(ID);
if (testArray != -1)
{
toolArray[testArray].setQuality(0);
toolArray[testArray].setToolName("");
toolArray[testArray].setID(0);
toolArray[testArray].setNumberInStock(0);
toolArray[testArray].setPrice(0.0);
//counter for number of items in array. Array holds 10 objects
numberOfItems--;
//shifting cells
for (index = testArray + 1; index < toolArray.length; index++)
{
toolArray[index - 1] = toolArray[index];
}
toolArray[toolArray.length - 1] = null;
System.out.println("Successful deletion");
return 1;
}
else
System.out.println("ID not found");
return -1;
}//end delete
And here is the corresponding GUI button used to delete the data in my test application:
else if (ev.getSource() == deleteBtn)
{
input = idFld.getText();
idInput = Integer.parseInt(input);
responseCode = store.delete(idInput);
if (responseCode == 1)
{
messageFld.setText(idInput + " - Successful deletion");
}
else if (responseCode == -1)
{
messageFld.setText(idInput + " - ID not found");
}
}//end delete button
Now, everything inserts fine, detects duplicate ID's, and so on. The delete method also works, letting me know that the user passed ID has been deleted at toolArray[index] as well as all of it's related data members.
The error occurs when I go to display the items in the array. The first 9 items display fine using JOptionPane, but when I reach item 10(my delete method is supposed to shift all cells to the left after deletion) I get several runtime errors starting with:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException.
I'm pretty sure my error starts with the delete() method in HardWareStore, specifically my loop to delete and shift the items to left. I've messed with it for a few hours but I cannot seem to find why, and my attempts to change the loop either result in another runtime error, or the method doesn't behave like it should.
I have only one general remark, and that's not to use Java primitive Arrays. Save yourself a lot of trouble and use ArrayList. That way you can simply remove an element at an index, there's no need then to manually manage elements in a primitive array.
Without a clear exception trace and a code snippet that shows how things are displayed I'm just speculating, but when you delete an item you shift everything manually and append a null value at the end of the array. When your array is then displayed you are most likely hitting a NullPointerException when dereferencing a null object.
In general you should only rarely have the need for primitive arrays. Use an ArrayList instead and delete items using its remove method.

Why the Item deleted from an array but isn't deleted from my table?

I've put together a few methods that are suppose to delete a searched item from an array and the data from the array is also being put into a JTable through a method called createLoginTable().
When my delete button actionListener Method is carried out the element or login is successfully deleted from the array: 'listOfLogins' but the element does not appear to be deleted from the JTable as it is still there.
Here are the methods starting with the actionListener:
if(e.getSource()==deleteLoginButton)
{
int loopNo = list.nextLogin; ///Variables used in the 'removeLogin' Method
String foundLogin = list.listOfLogins[foundLocation].toString();
Login[] loginList = list.listOfLogins;
LoginList list = new LoginList(); //The 'list' is wiped
list.removeLogin(loginList, foundLogin, loopNo);
list.writeLoginsToFile(); //Writes logins to file (not integral to the array)
String[][] loginTableLogins = new String[50][2]; //Wipes the JTable Array
createLoginsTable(); //Creates the JTable
searchLoginButton.setEnabled(true);
editLoginButton.setEnabled(false);
deleteLoginButton.setEnabled(false);
addLoginButton.setEnabled(true);
}
This is the 'removeLogin' Method (This is in a seperate 'list' class):
public void removeLogin(Login[] array, String unwantedLogin, int loop)
{
for(int i=0;i<loop;i++)
{
String currentLogin = array[i].toString();
if(!currentLogin.equals(unwantedLogin))
{
Login login = new Login();
addLogin(array[i]);
}
}
}
plus 'addLogin' Method (although i am assured this is not the source of my issue):
public void addLogin(Login tempLogin)
{
listOfLogins[nextLogin] = tempLogin;
System.out.println(listOfLogins[nextLogin]);
nextLogin++;
System.out.println(nextLogin);
}
And the 'createLoginsTable' method:
public void createLoginsTable()
{
for(int i=0;list.nextLogin>i;i++)
{
loginTableLogins[i] = list.listOfLogins[i].toArray();
System.out.println(list.listOfLogins[i].toString());
}
JTable loginsTable = new JTable(loginTableLogins, loginTableTitles);
JScrollPane loginsScrollPane = new JScrollPane(loginsTable);
loginsScrollPane.setBounds(400, 200, 200, 250);
testPanel.add(loginsScrollPane);
}
I have used 'System.out.println's so I am 99% certain that the element has been removed from the array (it is also apparent through my writeLoginsToFile Method) So I hope this information helps.
Your code is a little bit hard to decipher, next time maybe put in also the enclosing class, or some details about that class. What does the following line do:
LoginList list = new LoginList(); //The 'list' is wiped
You say the list is wiped, I think what is does is: it declares a list local variable and assigns a new object to it (and it masks the other list variable which you used a few lines earlier). Now, in the createLoginsTable() method you don't have this local variable, you have the "list" which I guess is a public field in your class. Now what you can do, is or pass the local list variable to the above function as a parameter createLoginsTable(list) or try the wiping line without the declaration so only:
list = new LoginList(); //The 'list' is wiped
Anyway, your code seams a little bit troubled it, maybe you should refactor it a little bit. Hope it helps.
You're not returning the table after you delete the item.
When you call the method to delete it and write out the table, that table is not returned after you remake the table.
Take this:
JScrollPane loginsScrollPane = new JScrollPane(loginsTable);
Bring it outside of your method. What I think might be happening is when you create your loginsScrollPane locally inside the method, it's not being added properly to your testPanel.
I think what might be happening is when you add it, and the method ends it's loosing that data that is contained. Declare your scrollpane, and your jtable where you declare your frame.

Java: linked list of items problem

I have used linked lists before with Strings, doubles, etc., and they always worked exactly as expected. But now I am forming a linked list of items, and whenever I add a new element to the list, all objects in the list apparently become equal to the last object.
The essential code is as below:
import java.util.*;
public class Global
{
static public LinkedList<StockInfo> DiaryStocks = new LinkedList<StockInfo>();
static public class StockInfo //info related to each stock in diary
{
String recordDate;
String ticker;
int status;
String buyDate;
String sellDate;
double buyPrice;
double sellPrice;
double nmbrShares;
}//StockInfo
//The following function places the Diary data for a stock in the arraylist
static public void AddDiaryData(StockInfo thisdata)
{
String tckr;
int i;
DiaryStocks.add(thisdata);
for (i = 0; i < DiaryStocks.size(); i++) //this is debug code
{
tckr = DiaryStocks.get(i).ticker;
}
}
}
As I said, when single stepping through the debug code near the bottom, each time I add a new item to the list, the list size grows as it should, but the tckr item only corresponds to the last item added.
Any insights into this puzzle would be greatly appreciated.
John Doner
The problem is outside the code your provide. It is most likely that you are adding the same instance of StockInfo. Perhaps you have something like:
StockInfo info = new StockInfo();
for (...) {
info.setFoo(..);
info.setBar(..);
AddDiaryData(info);
}
You should not reuse instances like that. You should create a new instance each time.
As a sidenote - method names in Java should start with lowercase letter.
From the symptoms you are describing, it seems as if you are always adding a reference to the same StockInfo object instance to your list, rather than a reference to a new copy each time.
When that object is updated with the contents of the new entry, all list entries appear to change to reflect that latest entry.
This problem lies outside the code snippet that you posted, perhaps in the caller of the AddDiaryData method.
Ooops.
Deep Copy please search it
DiaryStocks.add(thisdata);
you should create new StockInfo() then add to the list otherwise you add the reference and it equalize all the reference of items to the last one

Categories