I need to insert different result into the row of my JTable. I search my record by using purchaseID which is the pID, it will find 2 result for that particular purchaseID. The problem is when I insert it into row, it just duplicate the result of the first one. EG : P0001 have 2 purchase details and when I insert it into row, I have 2 same row. Is there any way for me to insert into row one by one ?
PS. I've been coding since morning, brain is not functioning well.
UI:
else if(e.getSource() == jbtRetrieve)
{
String pID = jTF3.getText();
Purchase purchase = purcControl.selectRecord(pID);
if (purchase != null) {
String pdCountStr = purchase.getPurchaseDetailsID();
String pdCountStr2 = pdCountStr.substring(2,5);
int pdCount = Integer.parseInt(pdCountStr2);
for(int g = 0; g<pdCount;g++){ //g =1
tableModel.addRow(new Object[]{ purchase.getPurchaseDetailsID(),purchase.getStockID(),purchase.getPrice(),purchase.getQuantity()});
}}
DA :
public Purchase getRecord(String pID){
String queryStr = "SELECT PD.PURCHASEDETAILID,PD.PURCHASEID,PD.STOCKID,PD.ORDERQTY,S.STOCKPRICE FROM "+tableName+" PD, STOCKS S WHERE PD.STOCKID = S.STOCKID AND PurchaseID = ?";
Purchase purchase = null;
System.out.println("asd");
try{
stmt = conn.prepareStatement(queryStr);
stmt.setString(1,pID);
ResultSet rs = stmt.executeQuery();
if(rs.next()){
purchase = new Purchase(pID, rs.getString("purchaseID"),rs.getString("stockID"),rs.getDouble("stockprice"),rs.getInt("orderqty"));
}
}
catch (SQLException ex){
JOptionPane.showMessageDialog(null,ex.getMessage(),"ERROR",JOptionPane.ERROR_MESSAGE);
}
return purchase;
}
Domain:
public Purchase(String purchaseDetailsID,String purchaseID,String stockID,double price,int quantity)
{
this.purchaseDetailsID = purchaseDetailsID;
this.purchaseID = purchaseID;
this.stockID = stockID;
this.price = price;
this.quantity = quantity;
}
public void setPurchaseID(String u){
this.purchaseID = u;
}
public String getPurchaseID(){
return purchaseID;
}
public String getPurchaseDetailsID(){
return purchaseDetailsID ;
}
public double getPrice(){
return price;
}
public String getStockID(){
return stockID;
}
public int getQuantity(){
return quantity;
}
public void setPurchaseDetailsID(String r){
this.purchaseDetailsID = r ;
}
public void setPrice(double p){
this.price = p;
}
public void setStockID(String s){
this.stockID = s;
}
public void setQuantity(int q){
this.quantity = q;
}
Control :
public Purchase selectRecord(String pID){
return purcDA.getRecord(pID);
}
Edit: Set Purchase to ArrayList<> to accept the List and I get this Exception.
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:635) at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
at ui.MainPurchasingFrame$ListenerClass.actionPerformed(MainPurchasingFrame.java:183)
code:
ArrayList<Purchase> purchase = purcControl.selectRecord(pID);
if (purchase != null) {
String pdCountStr = purchase.get(0).getPurchaseDetailsID();
String pdCountStr2 = pdCountStr.substring(2,5);
int pdCount = Integer.parseInt(pdCountStr2);
System.out.print(pdCount);
for(int g = 0; g<pdCount;g++){
tableModel.addRow(new Object[]{ purchase.get(g).getPurchaseDetailsID(),purchase.get(g).getStockID(),purchase.get(g).getPrice(),purchase.get(g).getQuantity()}); //This is where the exception occurs.
}
If you want to return multiple objects from a query, your return type should be either an array or a collection of that type.
So instead of defining
public Purchase getRecord(String pID){…}
You should define the DA method as:
public List<Purchase> getRecords(String pID) {…}
Inside the method, define a list object such as:
List<Purchase> foundPurchases = new ArrayList<>();
And then after issuing the query and getting the result set, you use a while loop to fill it:
while ( rs.next() ) {
purchase = new Purchase(pID, rs.getString("purchaseID"),rs.getString("stockID"),rs.getDouble("stockprice"),rs.getInt("orderqty"));
foundPurchases.add( purchase );
}
Then, after you finish and close your statement, you should return the foundPurchases:
return foundPurchases;
The calling code should, of course, expect to receive a List of purchases rather than a purchase, and then iterate and display it.
Now regarding your edited part. You are doing several things improperly.
First of all, you don't have to go inside the purchase records to see how many records there were. If there were none, the list will be empty. If there was 1, it's size is going to be 1, and if there are two, its size is going to be two.
Second, you actually don't need to know how many elements there are, because you can traverse a list by using its iterator, in a simple for loop:
ArrayList<Purchase> purchaseList = purcControl.selectRecord(pID);
for ( Purchase purchase : purchaseList ) {
…
}
You don't actually have to use get. You have the current individual purchase in the variable purchase (Note that I changed the name of your original variable to something that shows it's a list and not a purchase), and you can use it directly.
Note also that you don't need to check for nulls. The way I've written it, the DA method always returns a reference to a List, even if it's an empty list. And the loop always adds an actual new Purchase(…) to the list so the list's items are also never null.
One thing, though: from the way the error looks, it seems that you have only one row when the details ID says there should be two. Check your query directly with the database to be sure there are actually two records.
If you want to display an error when nothing was found, you should check with an if statement if the list is empty. This means that no records have been returned at all.
if ( purchasedList.isEmpty() ) {
// Display error dialog
} else {
// Do the for loop to fill the rows
}
Related
I am trying to create a list of objects from a database but whenever I add another element to the end of the list it changes the values of the previous elements. I have seen similar questions on here but none seem to help my problem.
Here is the code for the class Deck
public static class Deck {
private static int deckid;
private static String deckName;
private static int deckCreatorID;
private static boolean isDeckPublic;
private static String deckDescription;
public Deck(int id, String name, int creator, boolean isPublic, String description){
deckid = id;
deckName = name;
deckCreatorID = creator;
isDeckPublic = isPublic;
deckDescription = description;
}
public String getDeckName(){
return deckName;
}
public String getDeckDescription(){
return deckDescription;
}
public int getDeckCreator(){
return deckCreatorID;
}
public int getDeckid() { return deckid; }
public boolean getDeckPublic() { return isDeckPublic; }
}
Here is the code to create and add the objects to the list:
public static List<marketplaceController.Deck> getAllCards(){
List<marketplaceController.Deck> deckList = new ArrayList<>();
List<Integer> idList = new ArrayList<>();
List<String> nameList = new ArrayList<>();
List<Integer> cIdList = new ArrayList<>();
List<Boolean> publicList = new ArrayList<>();
List<String> descList = new ArrayList<>();
try{ // This try-catch block is mainly from https://www.javatpoint.com/example-to-connect-to-the-mysql-database
Class.forName("com.mysql.cj.jdbc.Driver"); // Define the driver to use
Connection con=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/users","root","UnlockDB.123"); // Connect to the local db
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select * from decks"); // Execute the query on the db
while(rs.next()) { // Runs while columns are to be store
idList.add(rs.getInt(1));
nameList.add(rs.getString(2));
cIdList.add(rs.getInt(3));
publicList.add(rs.getBoolean(4));
descList.add(rs.getString(5));
}
con.close();
}
catch(Exception e){
loginController.popup("An error occurred connecting to the database", "An error occurred");
}
for(int i = 0; i < idList.size(); ++i){ // This loop outputs the correct data
deckList.add(new marketplaceController.Deck(idList.get(i), nameList.get(i), cIdList.get(i), publicList.get(i), descList.get(i)));
System.out.println(deckList.get(i).getDeckid());
System.out.println(deckList.get(i).getDeckName());
System.out.println(deckList.get(i).getDeckCreator());
System.out.println(deckList.get(i).getDeckPublic());
System.out.println(deckList.get(i).getDeckDescription());
}
for(int i = 0; i < deckList.size(); ++i){ // This outputs the overwitten data
System.out.println(deckList.get(i).getDeckid());
System.out.println(deckList.get(i).getDeckName());
System.out.println(deckList.get(i).getDeckCreator());
System.out.println(deckList.get(i).getDeckPublic());
System.out.println(deckList.get(i).getDeckDescription());
}
return deckList;
}
When the elements of deckList are printed straight after they are created they show the correct elements e.g.
1
TESTDECK
1
true
""
2
TESTDECK2
1
true
""
However, when I iterate through the completed list and print the contents the following is printed:
2
TESTDECK2
1
true
""
2
TESTDECK2
1
true
""
This is probably a very stupiud question but I'm reltively new to Java and so any help is greatly appreciated
As #jhamon pointed out using static variables can be a very bad idea when you don't know what this means. Simply put a static field is shared among all instances of a class because it is a property of the class and not the instance. So when you have 10 instances of Deck all of them will return the same value for e.g. deckid.
Here is the HW problem:
At this point, you decide to implement a Hash structure for the contributor data to prepare for searches. You will read the contributor information from a file provided; it is a comma delimited (CSV) file. As each record is read, create a Hash table for the ID field. The limitation for the Hash table is that it has a size of 5, so you need to be able to handle collisions. Collisions should be resolved through the use of a linked list for the ID values (implement this using a stack). Your design should include the following:
A Hash table pointing to a structure for a linked list that contains only the following information:
Each Hash Bucket Collision Item will have the following Information:
ID: Integer; //identifier key for future needs
Hash Bucket Functions/Methods:
Input constructor: //to accept a string for the name and additional information for each contributor (you will only need the ID portion of the input data)
Hash Function constructor: (Hint: You only have 5 Hash buckets, so the function can be a very simple calculation.)
Pop constructor
Push constructor
Print constructor: //to show the contents of a Hash bucket
Deliverables:
A fully documented program to load the Hash table with collisions being handled as a linked list, implemented as a Stack
A test plan to show how the program runs and can be executed
A screenshot showing that the program loaded the data, and after all data is loaded, shows the contents of the first Hash bucket (ideally this is Bucket 0)
I believe I've gotten really close, but I'm used to Python so the Java syntax is something I'm trying to learn. Either way, check the code below to see what I've done.
I believe the problem has to do with the way I am declaring the hash table size. In python, I can just index the array and add a given object to that position in the array. Seems I can't do that in java though. I considered trying a for loop, but it didn't work
I feel like I'm pretty close. Most of the code was given from the professor, but I developed the Stack() class and methods on my own. When I run them they do work, and I got a 100% on that portion.
Through the debugging I've done, I can see that I am initializing an array of size 'size' (in this case 5). However, I can't figure out how to assign a key value pair to a given Stack() index.
Again, I'm used to Python and don't know much java, so I really think it's me not understanding Java syntax.
In python I would just do something along the lines of array[index].append[node]. Then, I could pop the array[index] and display the node one at a time.
import java.util.Scanner;
import java.io.File;
import java.util.regex.Pattern;
public class ContributorManager {
public static void main(String [] args) {
Scanner inputFile = null;
String name = null;
String city = null;
String country = null;
String phone = null;
double contribution = 0;
int id = 0;
Contributor c = null;
Node node = null;
HashTable h = new HashTable(5);
//open contributors file
try {
inputFile = new Scanner(new File("/Users/Dan/Desktop/contributors.csv"));
System.out.println("AsdasdfaDSF");
inputFile.useDelimiter(Pattern.compile("(\\n)|(\\r)|,"));
}
catch (Exception e) {
System.err.println("Error opening file.");
}
//create contributors object for each row, and add to the stack
while (inputFile.hasNext()) {
name = inputFile.next();
city = inputFile.next();
country = inputFile.next();
phone = inputFile.next();
contribution = inputFile.nextDouble();
id = inputFile.nextInt();
inputFile.nextLine(); //advance to the next line
c = new Contributor(name, city, country, phone, contribution, id);
node = new Node(c);
//System.out.println(c.hashFunction());
h.insert(node); //insert node into the hash table
}
h.print(); //print the entire hash table
}
}
public class Contributor {
private String name;
private String city;
private String country;
private String phone;
private double contribution;
private int id;
public Contributor(String name, String city, String country, String phone, double contribution, int id) {
this.name = name;
this.city = city;
this.country = country;
this.phone = phone;
this.contribution = contribution;
this.id = id;
}
public int hashFunction() {
//calculate the hash key value using the id member variable in this object
//the key must always return a value between 0 and 4
int key = this.id % 5;
return key;
//return the hash key value
}
public void printContributor() {
System.out.println("Name: " + name);
System.out.println("City: " + city);
System.out.println("Country: " + country);
System.out.println("Phone: " + phone);
System.out.println("Contribution: " + contribution);
System.out.println("ID: " + id);
System.out.println();
}
}
import java.util.LinkedList;
public class HashTable {
Stack[] table;
private int size;
private int top;
//declaring array
public HashTable(int size) {
//initialize the table array with empty Stack objects
table = new Stack[size];
System.out.println(table.length);
}
public void insert(Node n) {
//determine the hash key of Node n
System.out.println(n);
int key = n.c.hashFunction();
System.out.println(key);
//using the key to determine the table location,
//push Node n onto the stack
System.out.println(table.length);
table[key].push(n);
}
public void print() {
//display the contents of the entire table in order
for (int i=0; i < table.length; i++) {
System.out.println("===== Position " + i + " ======\n");
table[i].print();
System.out.println("========= End ==========");
System.out.println();
}
}
}
public class Node {
Contributor c;
Node next;
public Node(Contributor data){
//initialize member variables
c=data;
next=null;
}
public void displayNode() {
//display the contents of this node
c.printContributor();
}
}
public class Stack {
Node first;
public Stack(){
//initialize the empty stack
first = null;
}
public void push(Node newNode){
//if the stack is empty, make first point to new Node.
if(first==null)
first=newNode;
//if the stack is not empty, loop until we get to the end of the list,
//then make the last Node point to new Node
else
{
first=newNode;
newNode = newNode.next;
}
}
public Node pop() {
//if the stack is empty, return null
if(first==null)
return null;
//Handle the case where there is only one Node in the stack
else if(first.next==null)
{
Node t=first;
return t;
}
//Handle the case where there are at Least two (or more) elements in the stack
else
{
Node t=first;
return t;
}
}
public void print() {
//display the entire stack
Node tempDisplay = first; // start at the beginning of linkedList
while (tempDisplay != null){ // Executes until we don't find end of list.
tempDisplay.displayNode();
tempDisplay = tempDisplay.next;
}
System.out.println();
}
}
contributor.csv
Tim,Murphy,USA,8285557865,200,25
Gordon,Miner,USA,8285551008,150,32
Jean,Bell,USA,8285557503,225,33
Mike,Prather,USA,8285558497,155,34
George ,Pipps,USA,8285557777,100,35
However, I can't figure out how to assign a key value pair to a given Stack() index.
A stack is not an array. Index assignment is not a supported operation, only push and pop from one end of the structure.
It looks like you're having problems with the push and pop operations? Your code comments indicate what needs to be done. if stack is not empty, then loop to the end
You have no loop, and you seem to be inserting into the stack backwards.
Instead you'd probably want something like the following, very similar to the print method
Node n = first;
while (n.next != null) n = n.next;
n.next = newNode;
Similarly for popping, you'd stop the loop when n.next != null && n.next.next == null so that you can set n.next = null and pop it off the list
//TODO: loop logic
Node toPop = n.next;
n.next = null;
return toPop;
I am a Java beginner, I have been trying to read a csv file from my computer by using Java and insert the data into a ArrayList.
public class DataRepository {
public void loadFile(){
ArrayList<String> binsGrade = new ArrayList<String>();
try {
Scanner fileScanner = new Scanner(new File("C:\\Users\\Max\\Desktop\\Grade_SampleData.csv"));
while(fileScanner.hasNextLine()){
binsGrade.add(fileScanner.nextLine());
}
fileScanner.close();
System.out.println(binsGrade);
} catch (FileNotFoundException e){
e.printStackTrace();
}
}
}
And below is the result I got:
[name,literature,math,physics,chemistry,biology,history,geology,art,sports, Michael,80,90,82,79,75,70,72,68,95, Amy,85,88,73,79,88,93,90,92,75, Johnson,72,89,81,84,83,72,89,90,82, Bob,80,81,84,89,87,90,71,65,89, Tommy,70,89,79,90,88,73,75,89,91, Rachel,90,91,80,92,87,92,95,97,87, Evonne,78,91,87,88,91,76,74,86,91]
All the records are in one row, but I actually want it to be in separated rows and columns, and for example, when I call name, I can get the value: Michael, Amy, Johson and etc. When I call literature, I can get 80, 85, 72, 80 and etc.Then I can probably use these data to do some calculation, like calculate the average, or get the maximum score and etc.
Although I have been searching online for a while, I still have not figured out the best way to achieve this. Can you please share your ideas if you have one minute? Your help will be really appreciated. Thanks!
If you want to have something implemented quickly, you can follow Srivenu comment and use a Map<String, List<String>>. Each entry of the Map will have the name as the key, and a list of string for all the results. For example to add Michael :
myMap.add("Michael", Arrays.asList({"20", "12", "8", "80"}));
Then create the different methods that will go through this map to compute the average, or find the max, etc
If you want a more oriented object approach I suggest you to create objects that will represent your data. First a result object that will contain two attributes, a string that will be the subject and an int that will be the score.
public class Result {
private String subject;
private int score;
public Result(String s, int i) {
subject = s;
score = i;
}
//Add Setters and Getters
//Add additional method if required
}
Secondly Have a Person object that wil represent someone. It will have two attributes, a String representing the name and a list of Results objects.
public class Person {
private String name;
private List<Result> results;
public Person(String s, List<Result> r) {
name = s;
results = r;
}
//Add getters and setters
//Add additional methods if required
/**
* Example of additional method
* This one will return the score for a given subject
**/
public int getScore(String subject) {
Result r = results.get(subject);
return r.getScore();
}
}
Thirdly, create a GroupOfPerson Class that will contain one attribute, a list of person. Then This class will have methods that will return the average, the max, etc...
public class GroupOfPerson {
private List<Person> persons;
public GroupOfPErson(List<Person> p) {
persons = p;
}
/**
* Example of method.
* This one will return the average score for the given subject
**/
public int getAverageForSubject(String subject) {
int average = 0;
for(Person p : persons) {
average += p.getScore(subject);
}
average /= persons.size();
return average;
}
//Add other methods
}
Finally when reading your CSV file, create the corresponding objects.
I have a JTable where several columns contain a number from an enums like the following:
public static enum IMPORT_CONF_OPERATION_RESULT {
OK(0, "OK"),
ERROR(1, "ERROR"),
WAITING(2, "WAITING");
/* ... */
}
So, I needed to override method getValueAt() of table model looping through enum values in order to decode and return the correspondent String for each row as, in the database from which data come from, the numeric values are stored.
Now, if the user clicks on the correspondent header column, row are sorted according to numeric values but I would like to order them in alphabetical order. Shall I override sort() method of table model? Isn't looping so many times through enum values to get the description inefficient? Would it slow down table rendering?
UPDATE
This could be a solution following to what STaefi suggested, inside my extended DefaultTableModelField:
#Override
public void sort(int col, boolean ascendest) {
ColumnProperties columnProperties = this.mapColumn.get(col);
if (COLUMN_NAME_ENTITY.equals(columnProperties.getInfo()) ||
COLUMN_OPERATION_TYPE.equals(columnProperties.getInfo()) ||
COLUMN_OPERATION_RESULT.equals(columnProperties.getInfo()) ||
COLUMN_ELABORATION_TYPE.equals(columnProperties.getInfo()) ||
COLUMN_EVENT_STATE.equals(columnProperties.getInfo())) {
Collections.sort((List<TableImportConfEvent>)this.value, new EnumColumnSorter(ascendest, columnProperties.getInfo()));
this.fireTableDataChanged();
}
else {
super.sort(col, ascendest);
}
}
private class EnumColumnSorter implements Comparator<TableImportConfEvent> {
private int ascending;
private String columnName;
public EnumColumnSorter(boolean ascendest, String columnName) {
this.ascending = ascendest ? 1 : -1;
this.columnName = columnName;
}
#Override
public int compare(TableImportConfEvent o1, TableImportConfEvent o2) {
String decodedString1 = "";
String decodedString2 = "";
if (COLUMN_NAME_ENTITY.equals(this.columnName)) {
decodedString1 = getEntityName(o1.getEntityType());
decodedString2 = getEntityName(o2.getEntityType());
}
else if (COLUMN_OPERATION_TYPE.equals(this.columnName)) {
decodedString1 = getOperationName(o1.getOperationType());
decodedString2 = getOperationName(o2.getOperationType());
}
else if (COLUMN_OPERATION_RESULT.equals(this.columnName)) {
decodedString1 = getResultName(o1.getOperationResult());
decodedString2 = getResultName(o2.getOperationResult());
}
else if (COLUMN_ELABORATION_TYPE.equals(this.columnName)) {
decodedString1 = getResultName(o1.getOperationResult());
decodedString2 = getResultName(o2.getOperationResult());
}
else if (COLUMN_EVENT_STATE.equals(this.columnName)) {
decodedString1 = getStateName(o1.getEventState());
decodedString2 = getStateName(o2.getEventState());
}
return (decodedString1.compareTo(decodedString2)) * this.ascending;
}
}
To avoid looping over the enum values for each row, you may want to create a static final HashMap<Integer,IMPORT_CONF_OPERATION_RESULT> to cache the map of values to corresponding labels and initialize it in a static block inside of your enum. Then you can have a public static String getLabelByValue(int value) to use cache and avoid O(n) for looking up the label each time.
For controlling the sort orders and sort actions you may want to go after TableRowSorter but when you have overriden the getValueAt for your model the default sorting should be sufficient. Other way is use a custom Comparator in your table model to manage the logic of sorting.
i am looking for a way to check if an array contains more than 1 instances of the same object. I've been looking around but can't seem to find anything in the javadoc nor stackoverflow.
I am creating a monopoly board game (or in danish, matador) where the fee from landing on one of the fields differs depending on how many of that type of field the player owns.
I have a list in my player class in which i put all the fields that the player buys:
public List<OwnableField> ownsList = new ArrayList<>();
public void buy(OwnableField ownable) {
pay(ownable.getPrice());
ownsList.add(ownable);
}
And then i have this method in the specific field class, in which i am working on an if statement to set the fee:
public int fee;
public int feeCalc(int diceScore) {
if(this.getOwner().ownsList.(whatever checks for duplicate object in array)){
fee = 200 * diceScore;
} else {
fee = 100 * diceScore;
}
return fee;
}
If you have a proper equals and hash code defined then you can use sets to achive that
List list = ...
if(new HashSet(list).size().equals(list.size()){
//same size
} else {
//there was a duplicated element
}
If you want to check for one specific object only you could do it with:
final Object someObject = ...
List list = ...
int size = FluentIterable.from(list).filter(new Predicate<Object>() {
#Override
public boolean apply(Object input) {
return input == someObject;
}
}).size();
if(size > 1) {
//there is a duplicated element
}
Or, if you are looking for an instance of a class, then try:
List list = ...
int size = FluentIterable.from(list).filter(Predicates.instanceOf(YourClass.class)).size();
if(size > 1) {
//there is a duplicated element
}