I'm trying to make a simple billing system for a restaurant.
This shows the menu to the user and lets them choose, add an Item or quit.
In the end, it prints the bill.
The issue I'm facing is, I want the user to be able to add an item again with the item's number instead of overwriting the value.
Below code is my attempt which doesn't return anything.
public void addOrder(String meal, int quantity,
String[] dish, double[] cost) {
for (int i = 0; i < orderedFood.size(); i++) {
// look if food item already exists, update quantity of it by
// adding the previous value of the item to the new amount
if (orderedFood.get(i).contains(meal)) {
int oldQuantity = orderedQuantity.get(i);
orderedQuantity.set(i, oldQuantity + quantity);
break;
} else {
// if theres no item of this type yet, create a new one
orderedFood.add(meal);
orderedQuantity.add(quantity);
}
}
The code below shows how the food object gets created, and how the program works.
public static void Order() {
String[] dish = {"Sandwich", "Coffee", "Salad"};
double[] cost = {6.5, 3.2, 4.0};
for (int i = 0; i < dish.length; i++) {
System.out.println("\n" + dish[i] + ": " + cost[i] + "€.");
}
System.out.println("\nWhat would you like to order? \n\n");
Scanner myObj = new Scanner(System.in);
List<String> dishList = new ArrayList<>(Arrays.asList(dish));
// check if item exists
String menuItemTemp = myObj.nextLine();
String menuItem = "";
if (dishList.contains(menuItemTemp)) {
System.out.println("\nOkay.\n");
menuItem = menuItemTemp;
} else {
System.out.println("Error 404 Not Found.");
Order();
}
System.out.println("\nHow many? \n");
int userQuant = myObj.nextInt();
Bill myBill = new Bill();
myBill.addOrder(menuItem, userQuant, dish, cost);
System.out.println("\nOrder more? 1 - Yes. 2 - No. \n");
Scanner menuScan = new Scanner(System.in);
int menuScanner = menuScan.nextInt();
switch (menuScanner) {
// if another order is to be made
case 1:
System.out.println("\nOkay.");
Order();
break;
// output and end of program
case 2:
myBill.getOrder();
System.out.println(Math.round(myBill.getTotal() * 100.00) / 100.00 + "€\n");
System.out.println("\nThanks for ordering!\n");
// close scanners
menuScan.close();
myObj.close();
// end
System.exit(1);
}
Any nudge in the right direction would help a lot.
The error is the premature else. When not already present, you need to walk the entire for loop before knowing that there is no match.
If you do return instead of break you can treat the not-found case after the for.
public void addOrder(String meal, int quantity,
String[] dish, double[] cost) {
for (int i = 0; i < orderedFood.size(); i++) {
// look if food item already exists, update quantity of it by
// adding the previous value of the item to the new amount
if (orderedFood.get(i).contains(meal)) {
int oldQuantity = orderedQuantity.get(i);
orderedQuantity.set(i, oldQuantity + quantity);
return;
}
}
// if theres no item of this type yet, create a new one
orderedFood.add(meal);
orderedQuantity.add(quantity);
}
Of course
for
orderedFood.get(i).contains(meal)
int oldQuantity = orderedQuantity.get(i);
orderedQuantity.set(i, oldQuantity + quantity);
hints that an other data structure might be better:
Map<String, Integer> ordered = new HashMap<>(); // Meal to quantity.
public void addOrder(String meal, int quantity,
String[] dish, double[] cost) {
ordered.merge(meal, quantity, Integer::sum);
}
That is map the meal names to the total quantity. Indices are irrelevant.
Map.merge works as follows:
merge(K key, V value, (Value oldv, Value newv) -> resultv)
If newv is null, a remove is done.
Otherwise:
The lambda is called with an (possibly accumulating) old value, and the passed value.
if (oldv == null)
put(key, newv);
else
put(key, oldv + newv); // newv == value
Integer::sum is the same as (x, y) -> x + y.
So I would've left a comment if could've however I don't have enough reputation for that yet. I'm not sure what your myBill.getTotalOrder() function is. My first thought here without seeing more of your source code to understand your design would be to just make a Meal object that tracks its name, how much it is, and how many times it was ordered. Then during your getTotalOrder() you could just loop through each meal and add up the total.
Related
I'm having a little trouble with a fairly simple assignment, but couldn't find an answer here that seemed to work.
I need to have a 2D ArrayList that contains staff data, and then be able to run a separate function that allows the user to input a staff member's name, searches the ArrayList for that name, and if it exists, display the full row of data.
Here's what I've got so far:
The ArrayList
List<List<String>> staffArrayString = new ArrayList<>();
staffArrayString.add(Arrays.asList("Steven George", "12 York Road", "07123456678", "Permanent", "York", "27000/yr"));
staffArrayString.add(Arrays.asList("Rina Veyer", "20 Leeds Road", "08987987765", "Part Time", "Leeds", "10/hr"));
staffArrayString.add(Arrays.asList("Brian Lym", "13 Bradford Road", "07123234345", "Permanent", "Bradford", "27000/yr"));
The search function
public void staffNameSearch() {
System.out.println("Enter name of staff member:");
String staffName = in.next();
boolean found = false;
int row = 0;
for (int i = 0; i < staffArrayString.size(); i++) {
for (int j = 0; j < staffArrayString.get(i).size(); j++) {
if (staffArrayString.get(i).get(j).equals(staffName)) {
row = staffArrayString.get(i).size();
found = true;
}
}
}
if (found = true) {
System.out.print(staffArrayString.get(row) + " ");
}
}
I'm currently getting an output of 'Exception in thread "main" java.lang.IndexOutOfBoundsException' at the print line on the end there, but I can't for the life of me work out why. I'd appreciate any advice on this (especially if it's some obvious and stupid mistake on my part!).
The error is occuring because you are setting row to something unrelated to the row counter. When you discover the row (variable i) which has the name in the jth element, set row=i.
Be careful about if (found = true) - it is incorrect; prefer:
a) if (found)
b) if (found == true)
For efficiency, include && !found in the for loops so they exit as soon as you find something.
You can use for each loop for simpler.
System.out.println("Enter name of staff member:");
String staffName = in.next();
boolean found = false;
String[] foundArray;
for(String[] staffArray: staffArrayString){
for(String str : staffArray){
if(str.equals(staffName)){
foundArray = staffArray;
found = true;
break;
}
}
}
if (found == true) {
System.out.print(foundArray + " ");
}
You might be able to simplify the code a little bit by using a Map and a Staff class.
For example, the Staff class
public class Staff{
String name;
String address;
String id; // ?
boolean permanent; // Or a enum if there are more than 2 values
String city; // ?
int payrate;
boolean hourly;
#Override
public String toString(){ // Easily convert the class to a String
return String.format("%s %s %s %s %s $%d/%s",
name,
address,
id,
permanent ? "Permanent" : "Part-time",
city,
payrate,
hourly ? "hr" : "yr");
}
}
And for the code to read it
private Map<String, Staff> staffDirectory; // String is the name in lowercase
public void staffNameSearch() {
// Code
if(staffDirectory.containsKey(staffName)){ // Make sure staffName is lowercase
System.out.print(staffDirectory.get(staffName) + " ");
} else {
System.out.println("Name not found");
}
}
This way you can avoid using loops and get O(1) efficiency.
I am having a sorted ArrayList like-
List<DD_Details> list = new ArrayList<DD_Details>();
list.add(new DD_Details(26/05/2014,3000.00));
list.add(new DD_Details(26/08/2014,6000.00));
list.add(new DD_Details(26/08/2014,2000.00));
DD_Details Class is -
class DD_Details {
private Date ddSubmissionDate;
private Double amount;
public DD_Details(Date n, Double s) {
this.ddSubmissionDate = n;
this.amount = s;
}
public Date getDdSubmissionDate() {
return ddSubmissionDate;
}
public void setDdSubmissionDate(Date ddSubmissionDate) {
this.ddSubmissionDate = ddSubmissionDate;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public String toString() {
return "ddSubmissionDate: " + this.ddSubmissionDate + "-- amount: "
+ this.amount;
}
}
i just want to add amount values of the same date and store in a new ArrayList.
I tried below code but it is not working properly.
for (int i = 0; i < list.size(); i++) {
Double amt = 0.0;
Date date1 = list.get(i).getDdSubmissionDate();
for (int j = i + 1; j < list.size(); j++) {
if (date1.equals(list.get(j).getDdSubmissionDate())) {
amt = amt + list.get(j).getAmount() + list.get(i).getAmount();
} else {
amt = list.get(i).getAmount();
}
}
list1.add(new DD_Details(date1, amt));
}
Please give me some hint to get it done. Thanks in Advance.
You can use next solution instead:
List<DD_Details> list = new ArrayList<DD_Details>();
List<DD_Details> list1 = new ArrayList<DD_Details>();
list.add(new DD_Details(new Date(2014, 5, 26), 3000.00));
list.add(new DD_Details(new Date(2014, 8, 26), 6000.00));
list.add(new DD_Details(new Date(2014, 8, 26), 2000.00));
for (DD_Details currentEl : list) // iterate over 'list'
{
DD_Details existingElement = null;
for (DD_Details el1 : list1) // find element in 'list1' with the same date
{
if (el1.getDdSubmissionDate().equals(currentEl.getDdSubmissionDate()))
{
existingElement = el1;
break;
}
}
if (existingElement == null) // if element is not found in 'list1' then add current element to list
{
list1.add(currentEl); // or list1.add(new DD_Details(el.getDdSubmissionDate(), el.getAmount()))
}
else // if element is found, then increase amount
{
existingElement.setAmount(existingElement.getAmount() + currentEl.getAmount());
}
}
// 'list1' contains what you need
In the inner for, when you are adding the values for a particular date, there is an error in the else part. You try to iterate through the list for a given date and add all the values until the date is different. Once you reach this condition, you get inside the else and set the sum to be the amount of the first element of this given date, therefore you are overriding the sum you had calculated. Moreover, for every new element with the same date, you are adding the amount of the first date, which means that if there are 4 elements of the same date, you will be adding 3 times the first amount.
What you should do, is get the amount for that given date before entering the second loop. One final consideration, is that you are going to get different amounts for different dates because imagine you have 3 elements with the same date, with the loop you are using, you will start with the first one, get the amount of the 3 elements added, then go to the second and get the amount of the second and third added, and finally move to the last one and create a third element with the amount of only the third element. Therefore, you should create a third variable which I called k, and store the last j value that contained the same date, to then add it to i and avoid iterating through an element with a date you already processed:
for (int i = 0; i < list.size(); i++) {
Double amt = list.get(i).getAmount();
Date date1 = list.get(i).getDdSubmissionDate();
int k = 0;
for (int j = i + 1; j < list.size(); j++) {
if (date1.equals(list.get(j).getDdSubmissionDate())) {
amt = amt + list.get(j).getAmount();
k = j;
}
}
list1.add(new DD_Details(date1, amt));
i += k++;
}
Your dates should be String literals. The way you've written them they will be ints and all equal to 0.
The obvious solution would be to build a Map of dates to amounts (instead of a list) and after adding all the entries iterating the map to build your list. Something like:
Map<Date, Double> amountPerDate = new HashMap<>();
List<Date> dates = ...;
List<Double> amounts = ...; // wherever those may come from
for(int i = 0; i < dates.size(); i++) {
Double currentAmount = amountPerDate.get(dates.get(i));
double amount = currentAmount == null ? 0 : currentAmount;
amountPerDate.put(dates.get(i), amount + amounts.get(i));
}
List<DD_Details> details = new ArrayList<>();
for(Entry<Date, Double> e : amountPerDate) {
details.put(new DD_Details(e.getKey(), e.getValue());
}
// optionally, you may Collections.sort(details); the list
In your DD_Details class, consider using a primitive double instead of a boxed Double.
I guess that your problem is in your second for-loop in the else-part of the if-statement. Even if you have dates which match you will have some dates which will not match. Thus you set back your amount the the amount of i.
You should add:
System.out.println("The dates are equal. New amount is: " + amt);
to your if-statement and:
System.out.println("Dates do not match. " + amt);
Now you should see that you add the amount the correct way but you reset it in the else part several times.
I have a code that atm checks if the array list has reached the size or not, if no I want it to to perform checks before adding anything else to the list. I have attempted it but cannot figure out why it does not work. below is my method.
private static void addToArrayList(String fruit, double no1, int no2, int no3) throws Exception {
try {
if (arraysList.size() <= 5) {
int count = 0;
for (StoringArray item : arraysList)
if (item.equals("Apple")) {
++count;
if (count > 2)
throw new IllegalArgumentException( "You cannot add more than 2 apples." ); //Instead of this I want a Joption pane pop up to give this error if it applies, but at the moment I am not sure but this code with the current code I have is not working.
}
{
if ( arraysList.get( arraysList.size() - 1 ).equals("Banana") )
throw new IllegalArgumentException( "You have just added this please add something else and then add this if you want." ); }
arraysList.add(new StoringArray(fruit, no1, no2, no3));
}else{
JOptionPane.showMessageDialog(contentPane, "You cannot added mroe than 6 elements.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
I want the error messages to appear in a Joption Pane and I want to check the following errors;
Say the list includes Apples, Bananas, Oranges, PineApples, Grapes
1; I want to check whether the user given parameters no1, no2 and no3 meet the conditon I want i.e.
for (StoreCommands item : commandsList)
if (item.equals("Apple")) {
}no1 need to be greater then 0, no2 needs to be less than 10 and no 3 needs to be less than 15.
2; If user tries to add two apples together in any order it should not be allowed, directly after one another.
3; If the user adds 2 Oranges, they should not be allowed and error message saying this should come up in JOption Pane message box.
If all the conditions are the array values get added to the array list. Thanks I hope I explained myself properly, I have been working on this problem for ages and cannot figure it out for some reason. Thanks again.
----------------edited-----------------with class that stores the arrayList.
public class StoreCommands {
public String toString(){
return Name + " " + Number1 + " " + Number2 + " " + Number3;
}
private String Name;
private int Number1;
private int Number2;
private int Number3;
public String getCommand() {
return Name;
}
public double getcommandNOS() {
return Number1;
}
public int getcommandVLW() {
return Number2;
}
public int getcommandVRW() {
return Number3;
}
public StoringArray(String fruitsNames, double fno1, int fno2, int fno3) throws Exception{
Name = fruitsNames;
Number1 = (int) fno1;
Number2 = fno1;
Number3 = fno3;
}
}
There are also some problems in your StoreCommands (?StoringArray) class and it doesn't compile.
1) The constructor is called StoringArray while the class is called StoreCommands.
2) You shouldn't accept a double value as second parameter and cast it to an int.
3) "Number2 = fno1;" inside the constructor should be "Number2 = fno2;" instead
4) You cannot compare your StoreCommands instance to a String value using equals. You need to compare to the String returned from the getCommand() method:
if (item.getCommand().equals("Apple"))
no1 need to be greater then 0, no2 needs to be less than 10 and no 3 needs to be less than 15. 2; If user tries to add two apples together in any order it should not be allowed, directly after one another. 3; If the user adds 2 Oranges, they should not be allowed and error message saying this should come up in JOption Pane message box.
perhaps something like this would do the job:
public static String getErrorMessage(List<StoreCommands> commands, String fruitsName, int no1, int no2, int no3) {
if (no1 <= 0 || no2 >= 10 || no3 >= 15) {
return "Some Error message...";
}
String previous = null;
int orangeCount = 0;
for (StoreCommands c : commands) {
if (fruitsName.equals("Apple") && previous != null && previous.equals("Apple")) {
return "Some Error message...";
} else if (c.getCommand().equals("Orange")) {
orangeCount++;
}
previous = c.getCommand();
}
return fruitsName.equals("Orange") && orangeCount == 1 ? "Some Error message" : null;
}
your class name is StoreCommands
but you have declared constructor named StoringArray
public StoringArray(String fruitsNames, double fno1, int fno2, int fno3) throws Exception
{
Name = fruitsNames;
Number1 = (int) fno1;
Number2 = fno1;
Number3 = fno3;
}
replace this by
public StoreCommands(String fruitsNames, double fno1, int fno2, int fno3) throws Exception
{
Name = fruitsNames;
Number1 = fno1; //you do not need to cast int because both are int
Number2 = fno1;
Number3 = fno3;
}
in for loop change the conditional logic
for (StoringArray item : arraysList)
if (item.getCommand().equals("Apple"))
{
}
.. it should works now if your other logic and code is ok
I am trying to write a program that mimics the actions of a vending machine for my CS class. I have a double array stock that represents the the number of items at a particular "slot" [my vending machine is weird and is kinda like one long vending machine with 1 column of different items]. Here is my code so far:
public class VendingMachine
{
// define fields here
public static double itemPrice[];
public static String[] itemName;
public static int stock[][];
public static int maxPerSlot;
public static double cashAmmount;
public VendingMachine(int numslots, int maxperslot, double cash)
{
final int numSlots = numslots;
maxPerSlot = maxperslot;
cashAmmount = cash;
stock = new int[numSlots][1];
itemPrice = new double[numSlots];
itemName = new String[numSlots];
// complete this method
}
public void setProduct(int slot, String product, double price)
{ int Slot = slot;
itemPrice[Slot] = price;
itemName[Slot] = product;
stock[Slot][0] = 0;
//
}
public void restockProduct(String product, int quantity)
{
String Product = product;
int Quantity = quantity;
for(int i = 0; i < itemName.length;i++){
if (Quantity > (maxPerSlot-stock[i][0])){
return;
}
if (Product.equals(itemName[i])&&Quantity < maxPerSlot){
stock[i][0] += Quantity;
}else if ((maxPerSlot-stock[i][0])==0){
continue;
}
}
//Put # of products in slot that holds it and if that slot is full put the rest in the next
//available slot that holds that product, if all full return error.
}
public double getCashOnHand()
{
return cashAmmount; // replace this line with your code
}
public int getQuantity(int slot)
{
return stock[slot][0]; // replace this line with your code
}
public int getQuantity(String product)
{ int total = 0;
for (int i = 0; i<itemName.length;i++){
if (product == itemName[i]){
total += this.getQuantity(i);
}
}
return total;
}
public boolean buyItem(int slot)
{ int snum = slot;
double price = 0;
if (stock[snum][0] != 0){
stock[snum][0]--;
price= itemPrice[snum];
cashAmmount += price;
return true;
} else {
return false;}
// replace this line with your code
}
}
and the main method that runs it:
public class vmd
{
public static void main(String[] args)
{
boolean success;
// vending machine w/ 20 slots, 10 items maximum per slot, $5 cash on hand
VendingMachine v = new VendingMachine(20, 10, 5.00);
v.setProduct(0, "Cheesy Poofs", 0.75);
v.setProduct(1, "Red Bull", 1.25);
v.setProduct(2, "Cheesy Poofs", 0.75);
v.restockProduct("Cheesy Poofs", 8);
v.restockProduct("Red Bull", 7);
v.restockProduct("Cheesy Poofs", 5); // 2 more go into slot 0, remaining 3 into slot 2
success = v.buyItem(0);
System.out.println(success); // should print "true"
System.out.println(v.getCashOnHand()); // should print "5.75"
System.out.println(v.getQuantity(2));// should print "9"
System.out.println(v.getQuantity("Cheesy Poofs")); // should print "12"
}
}
When I run this thought I consistently get:
true
5.75
8
15
as my out put when I am suppose to get:
true
5.75
9
12
as my output. Why is this? I am assuming it has something to do with the restockProduct() method but I can't seem to narrow it down and its really getting on my nerves. According to my CS teacher the restockProduct() method is suppose to add the given quantity of the specified product to the vending machine and Put as many of the items as possible into the first slot that has been designated to hold that particular kind of product (using setProduct()).
If not all of the items will fit into the first slot, put as many of the rest as possible into the second slot that holds that kind of product, etc. For partial credit, your method should at least be able to find the first slot designated for the specified product and put all of the items there".
You are right, restockProducts doesn't do what you want it to. Here's what you have:
public void restockProduct(String product, int quantity)
{
String Product = product;
int Quantity = quantity;
for(int i = 0; i < itemName.length;i++){
if (Quantity > (maxPerSlot-stock[i][0])){
return;
}
if (Product.equals(itemName[i])&&Quantity < maxPerSlot){
stock[i][0] += Quantity;
}else if ((maxPerSlot-stock[i][0])==0){
continue;
}
}
So when you restock "Cheesy Poofs", the first time, here's what happens:
On loop 0, you are Cheesy Poofs, so you put 8 items in there.
On loop 1, you have the wrong type, so nothing goes there
On loop 2, you have Cheesy Poofs, so you put 8 there.
Somehow, you need to remember that you've put 8 in the first slot. Also, you need to have a mechanism to put some into one slot, and some into another, right now I don't see that being possible in your code.
you have several problems in your restockProduct described by others, anyway you can change you restockProduct function to this one:
public void restockProduct(final String product, int quantity)
{
for (int i = 0; i < itemName.length; i++)
{
if ( (product.equals(itemName[i]) || "".equals(product) ) && (maxPerSlot - stock[i][0]) > 0)
{
stock[i][0] += quantity;
if (stock[i][0] > maxPerSlot)
{
quantity = stock[i][0] - maxPerSlot;
stock[i][0] = maxPerSlot;
}
else
return;
}
}
if (quantity > 0)
throw new IllegalArgumentException("Cannot stock product");
}
NOTE: we're either inserting product to slot where product already is OR where no products at all
NOTE2: after inserting we're checking is there any rest we should insert further or everything is here
Your problem is here:
for(int i = 0; i < itemName.length;i++){
if (Quantity > (maxPerSlot-stock[i][0])){
return;
}
Your first call to restock "Cheesy Poofs"
v.restockProduct("Cheesy Poofs", 8);
puts 8 items into the machine.
Your second call to restock cheesy poofs:
v.restockProduct("Cheesy Poofs", 5);
Fails to do anything. Your if statement says that if the quantity (5) is greater than maxPerSlot - current stock which is (10 - 8) or just 2, then return.
5 is greater than 2 so the method ends and nothing is added to your machine.
Additionally you need to put some sort of control in there to break out of the loop once you've added all 8 items to the machine. As it stands you're adding 8 cheesy poofs to two different slots. Once you add the 8 to the first Cheesy Poof row you should remove 8 from what you have left to stock.
I took the liberty of reconstructing that method and this is what I think you're trying to achieve:
public void restockProduct(String product, int quantity)
{
String Product = product;
int Quantity = quantity;
for(int i = 0; i < itemName.length;i++){
if (Product.equals(itemName[i])){
if (Quantity > (maxPerSlot-stock[i][0])){
Quantity -= maxPerSlot-stock[i][0];
stock[i][0] += maxPerSlot-stock[i][0];
}
if (Quantity <= (maxPerSlot-stock[i][0])){
stock[i][0] += Quantity;
return;
}
}
}
}
I cant figure out how to start a method to delete a specific entry stored in an array...
I used to do this:
public void deleteEntry() {
SName = JOptionPane.showInputDialog("Enter Name to delete: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, "Found!");
entry[i] = null;
}
}
}
but I was advised not to assign the entry[i] to null because it will ruin my entries...
I have no idea how to code it in another way...
What should I need to do is:
I need to delete a specific entry from an array
please help...
also... its output was error it says:
Exception in thread "main" java.lang.NullPointerException
at AddressBook.viewAll(AddressBook.java:62)
at AddressBook.main(AddressBook.java:36)
Java Result: 1
This is my code in my main program:
public class AddressBook {
private AddressBookEntry entry[];
private int counter;
private String SName;
public static void main(String[] args) {
AddressBook a = new AddressBook();
a.entry = new AddressBookEntry[100];
int option = 0;
while (option != 5) {
String content = "Choose an Option\n\n"
+ "[1] Add an Entry\n"
+ "[2] Delete an Entry\n"
+ "[3] Update an Entry\n"
+ "[4] View all Entries\n"
+ "[5] View Specific Entry\n"
+ "[6] Exit";
option = Integer.parseInt(JOptionPane.showInputDialog(content));
switch (option) {
case 1:
a.addEntry();
break;
case 2:
a.deleteEntry();
break;
case 3:
a.editEntry();
break;
case 4:
a.viewAll();
break;
case 5:
a.searchEntry();
break;
case 6:
System.exit(1);
break;
default:
JOptionPane.showMessageDialog(null, "Invalid Choice!");
}
}
}
public void addEntry() {
entry[counter] = new AddressBookEntry();
entry[counter].setName(JOptionPane.showInputDialog("Enter name: "));
entry[counter].setAdd(JOptionPane.showInputDialog("Enter add: "));
entry[counter].setPhoneNo(JOptionPane.showInputDialog("Enter Phone No.: "));
entry[counter].setEmail(JOptionPane.showInputDialog("Enter E-mail: "));
counter++;
}
public void viewAll() {
String addText = " NAME\tADDRESS\tPHONE NO.\tE-MAIL ADD\n\n";
for (int i = 0; i < counter; i++) {
addText = addText + entry[i].getInfo() + "\n";
}
JOptionPane.showMessageDialog(null, new JTextArea(addText));
}
public void searchEntry() {
int notfound = 0;
SName = JOptionPane.showInputDialog("Enter Name to find: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, entry[i].getInfo2());
break;
} else {
notfound++;
}
}
if (notfound != 0) {
JOptionPane.showMessageDialog(null, "Name Not Found!");
}
notfound = 0;
}
public void editEntry() {
int notfound = 0;
SName = JOptionPane.showInputDialog("Enter Name to edit: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
entry[i] = new AddressBookEntry();
entry[i].setName(JOptionPane.showInputDialog("Enter new name: "));
entry[i].setAdd(JOptionPane.showInputDialog("Enter new add: "));
entry[i].setPhoneNo(JOptionPane.showInputDialog("Enter new Phone No.: "));
entry[i].setEmail(JOptionPane.showInputDialog("Enter new E-mail: "));
break;
} else {
notfound++;
}
}
if (notfound != 0) {
JOptionPane.showMessageDialog(null, "Name Not Found!");
}
notfound = 0;
}
public void deleteEntry() {
SName = JOptionPane.showInputDialog("Enter Name to delete: ");
for (int i = 0; i < counter; i++) {
if (entry[i].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, "Found!");
entry[i] = null;
break;
}
}
}
}
Assigning the values to null is going to be the easiest practice. If you're really picky, you could resize the array, but that would be rather pointless. Just keep a separate size counter and decrement it each time you set something to null.
Another reason you're getting a null pointer exception is that you have to consider what's happening when you're replacing values in your array with null but still iterating by counter. You're going to be left with holes in your array upon deletion. The first solution would be to bypass null values altogether, and just shift your array down (somewhat of an expensive operation). The second would be to alter your methods to take those null values into consideration. Example:
public void viewAll() {
String addText = " NAME\tADDRESS\tPHONE NO.\tE-MAIL ADD\n\n";
int nonNull = 0;
for (int i = 0; i < entry.length; i++) {
if (entry[i] != null) {
addText = addText + entry[i].getInfo() + "\n";
nonNull++;
}
if (nonNull == counter) break;
}
JOptionPane.showMessageDialog(null, new JTextArea(addText));
}
I don't have a compiler on this computer, so consider it more of psuedo-code. But the idea is that the counter is only keeping track of how many non-null values you have in your address book, and that these null values could be in random places of your array. I added the nonNull integer as a local counter to keep track of how many values you've encountered that aren't null (so you aren't forced to run through the entire address book). Then, I added the if statement to ensure that the value at entry[i] isn't a null value (trying to invoke getInfo() on a null value is what's giving you that error). Lastly, I added the if statement to break the loop if you've encountered all of the non-null values you have stored. Hope this helps. (Also it may be worth considering a LinkedList to eliminate the null values all together).
Actually, for simplicity's sake, you probably are much better off using a LinkedList, unless you are required to use an array, since you would need to alter all of your methods to take null spaces in your array into account. Assuming you're familiar with LinkedLists of course.
Arrays are immutable. You can change the value for a particular index in the array but you can't change the array size itself. To "delete", you could do:
myArray[index] = null;
And just treat null values as unset/deleted entries.
Assigning to null (currently what you are doing) is the proper thing to do. That will eliminate the reference to the object at that index and allow it to be garbage collected.
Replace entry[i] = null; with this:
System.arraycopy(entry, i + 1, entry, i, counter - i - 1);
--counter;
entry[counter] = null; // optional; helps with garbage collection
--i; // required to not skip the next element
(I'm assuming here that counter is the number of valid entries in entry. This will leave no null entries among the first counter elements of entry (assuming that there weren't any to start with).
Further thought: If you need the array length to always match the number of valid entries, you'll have to re-allocate the array and copy the values over. Just use arraycopy to copy entries from 0 through i-1 and from i+1 to counter-1 into the new array and then assign it to entry. This isn't particularly efficient and is best avoided if possible.
Better to this is List which has remove() method. But if you really want use Array I recommend you change Array to List and then remove all values, after it you can always change List to Array
import javax.swing.JOptionPane;
public class Test {
private static User[] entry = new User[] { new User("Gil"),
new User("Bil"), new User("John") };
public static void main(String... args) {
final Test test = new Test();
test.deleteEntry();
for (int index = 0; index < entry.length; index++) {
User user = entry[index];
if (user != null)
System.out.println(entry[index]);
}
}
public void deleteEntry() {
String SName = JOptionPane.showInputDialog("Enter Name to delete: ");
for (int index = 0; index < entry.length; index++) {
if (entry[index].getName().equals(SName)) {
JOptionPane.showMessageDialog(null, "Found!");
entry[index] = null;
break;
}
}
}
private static class User {
private String name;
public User(String name) {
this.name = name;
}
/**
* #return the name
*/
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
}