I have classes "BaseProduct" - abstract, "Food" - implements BaseProduct and a "Cart" which puts many foods inside.
So how do I put the foods inside the Cart and how do I go about adding their expiration date discount(5 days before their expiration date, they get discounted with 10%)?
I should also Create a class "Cashier" that has a method to print a receipt. The method accepts a "Cart" (collection of products) and the date and time of purchase. It should print all purchased products with their price, quantity, the total sum and the total discount.
Would be greatly thankful if someone helps.
Class BaseProduct looks like this:
public abstract class BaseProduct {
private String name;
private String brand;
private Double price;
protected BaseProduct(String name, String brand, Double price) {
this.name = name;
this.brand = brand;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
Class Food looks like this :
package Products.PerishableProducts;
import Products.BaseProduct;
import java.util.Date;
public class Food extends BaseProduct {
private Date expirationDate;
//sample date - 2020/04/20 -> yyyy-MM-dd
//TODO:CHECK WHETHER OR NOT YOU HAVE EXPIRATION DATE DISCOUNTS WHEN ADDING ITEMS IN CART
public Food(String name, String brand, Double price, Date expirationDate) {
super(name, brand, price);
this.expirationDate = expirationDate;
}
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
}
Class "Cart"(shopping cart) looks like this:
package Cart;
import Products.BaseProduct;
import java.util.List;
public class Cart {
private static List<BaseProduct> products;
//TODO:add products
public List<BaseProduct> add(List<BaseProduct> products){
}
//TODO: remove products
}
There can be multiple approaches to solve this problem. If we think about where would it count to have a discount is obviously when we calculate the price of a product. So I would refactor the Food class as follows:
import java.time.LocalDate;
public class Food extends BaseProduct {
// Use LocalDate instead of the outdated Date class. It is way easier to use and to avoid some common pitfalls
private LocalDate expirationDate;
public Food(String name, String brand, Double price, LocalDate expirationDate) {
super(name, brand, price);
this.expirationDate = expirationDate;
}
public LocalDate getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(LocalDate expirationDate) {
this.expirationDate = expirationDate;
}
// Override the calculation of the price of a Food product and apply the discount
#Override
public Double getPrice() {
return super.getPrice() * (1.0 - getDiscount());
}
// Calculate the discount percentage. If the expiration day is less than 5 days compared to current day, return a 10% discount, otherwise return 0
private Double getDiscount() {
return expirationDate.minusDays(5).isAfter(LocalDate.now()) ? 0.0 : 0.1;
}
}
Now, in case of a Cart we probably care about the total price of how much a client would want to pay. So we can write the following methods:
import java.util.ArrayList;
import java.util.List;
public class Cart {
List<BaseProduct> products = new ArrayList<>();
public void addProduct(BaseProduct product) {
products.add(product);
}
// Returns the total price of the items currently in our cart. Discount is applied to the items which are eligible
public Double getTotalPrice() {
return products.stream().mapToDouble(BaseProduct::getPrice).sum();
}
}
We can use the Cart and in the following way:
public static void main(String[] args) {
BaseProduct cheese = new Food("cheese", "CheeseBrand", 10.0, LocalDate.of(2021, 10, 1));
BaseProduct vine = new Food("vine", "Vine", 50.0, LocalDate.of(2025, 12, 1));
Cart cart = new Cart();
cart.addProduct(cheese);
cart.addProduct(vine);
System.out.println(cart.getTotalPrice());
}
Assuming that the current date is: 2021 31th of October, we would get the following total amount for the example above: 59.0.
Also, we may want to think about what would happen if there is an expired product. For now, we apply a 10% discount to it, we probably would not want to be able to put the item into the cart.
To add products to the cart
Finish writing the Cart::add method.
Initializing the products list will help. Then have a look at the add methods on the list implementation you chose .
To apply a discount.
Overload the getPrice method in Food with a getprice(Date purchaseDate) method. return the price from super.getPrice() less your discount when appropriate.
You may find that having a getDiscount(Date purchaseDate) method is useful, as the Cashier class wants a total discount.
Why is your products list static?
To initialize the list there are two things you can do:
a. Eager initialization:
private List<BaseProduct> products = new ArrayList<>();
public void add(BaseProduct product) {
this.products.add(product);
}
b. Lazy Initialization:
public void add(BaseProduct product) {
if (this.products == null) {
this.products = new ArrayList<>();
}
this.products.add(product);
}
Let me know if this answers your question or you have any other query.
Related
I am trying to get specific value from setter method using java method chaining.
like if we do obj.setId(1).setValue(5).
how we can get value = 5 using obj.setId(1).getValue();
here is the main class
public class MenuDish {
private String name;
private double price;
private String description;
private int category;
private int spiciness;
private boolean healthy;
public MenuDish(){ //constrcutor
}
public MenuDish setPrice(double price){
if(price < 0.0){
this.price = 0.0;
}
else{
this.price = price;
}
return this;
}
public double getPrice() {
return this.price;
}
public MenuDish setDay(int day){
return new MenuDish();//just do nothing
}
}
Sub class
AdjustableMenuDish Class
public class AdjustableMenuDish extends MenuDish {
private int day;
private double price;
public AdjustableMenuDish(){ //constructor
setName(null);
setPrice(0);
setDescription(null);
setCategory(0);
setHealthy(false);
setSpiciness(0);
}
#Override
public MenuDish setDay(int day){
this.day = day;
return this;
}
}
Inside main method I am trying to do something like this.
AdjustableMenuDish dish = new AdjustableMenuDish();
dish.setDay(0).setPrice(3.4);
dish.setDay(3).setPrice(7.4);
System.out.println(dish.setDay(0).getPrice());//--->output 7.4 but how to
get 3.4 instead of 7.4
Basically I am trying to get specific price from day.
Edit
I want to pass Junit test case which is given below
#Test public void test_daily_prices() {
AdjustableMenuDish dish = new AdjustableMenuDish();
for (int i = MenuDish.MONDAY; i <= MenuDish.SUNDAY; i++) {
double p = 1.0+i;
double a = dish.setDay(i).setPrice(p).getPrice();
assertEquals(p, a, 0.0001);
}
for (int i = MenuDish.MONDAY; i <= MenuDish.SUNDAY; i++) {
double p = 1.0+i;
double a = dish.setDay(i).getPrice();
assertEquals(p, a, 0.0001);
}
}
Fail expected 1.0 but was 7.0
You need to pair days and prices together, rather than have them as single attributes of MenuDish. You could try something like:
class AdjustableMenuDish {
private double[] prices = new double[7]; // Assumes day as [0..6]
...
public AdjustableMenuDish setPrice(int day, double price) {
prices[day] = price;
return this;
}
public double getPrice(int day) {
return prices[day];
}
}
If every dish has a different price depending on the day, then this code could be in MenuDish. If it's only some dishes, then it probably belongs on AdjustableMenuDish.
Given that a price is really a price per day, I think you should submit the two together, ie. in one method (as above). If you really want to stick to your MenuDish API as it is now, then you could try something like the following. This tracks the current day.
class MenuDish {
private double[] prices = new double[7]; // Assumes day as [0..6]
private int day;
...
public MenuDish setDay(int day) {
this.day = day;
return this;
}
public MenuDish setPrice(double price) {
prices[day] = price;
return this;
}
public double getPrice() {
return prices[day];
}
}
I have a number of evaluations I'm looking to make to a collection of data and I've been trying to figure out how to accomplish this with streams. I'm looking at streams specifically because the collection sizes can be fairly large and i'd like to take advantage of the parallel processing.
Here is some sample code, which reflects a basic structure -
import java.math.BigDecimal;
import java.util.Map;
import java.util.List;
public class TestApplication {
/***
* Enumerated list of various product types
***/
public enum ProductType {
TOY, BATH, BEDROOM, OUTDOOR
}
/***
* Represents each product we have in inventory.
***/
class Product {
public String name;
public ProductType type;
public int quantity = 0;
public double costPerUnit = 0;
public double productValue = 0;
public float percentOfTotalInventory;
public void setName(String name) { this.name = name; }
public void setProductType(ProductType type) { this.type = type; }
public void setQuantity(int quantity) { this.quantity = quantity; }
public void setCostPerUnit(double unitCost) { this.costPerUnit = unitCost; }
public void calculateProductValue() {
this.productValue = quantity * costPerUnit;
}
public void calculatePercentageOfTotalInventory(double totalInventoryValue) {
this.percentOfTotalInventory = (float) ((costPerUnit * 100) / totalInventoryValue);
}
public String getName() { return name; }
public ProductType getType() { return type; }
public int getQuantity() { return quantity; }
public double getCostPerUnit() { return costPerUnit; }
public float getPercentOfTotalInventory() { return percentOfTotalInventory; }
}
/***
* summary of all the products in our inventory.
*
* in addition to the catalog of products, will keep a running total cost of
* the current inventory and a summary grouping of the products by type
***/
class ProductInventory {
public List<Product> products;
public BigDecimal totalCostOfInventory;
public Map<ProductType, List<ProductSummaryByType>> productsByType;
public void accept(Product p) {
p.calculateProductValue();
products.add(p);
totalCostOfInventory = totalCostOfInventory.add(BigDecimal.valueOf(p.getCostPerUnit()));
}
public void combine(ProductInventory other) {
this.products.addAll(other.products);
this.totalCostOfInventory = totalCostOfInventory.add(other.totalCostOfInventory);
}
}
private class ProductSummaryByType {
//for a type (toy, bath, bed)
public ProductType Type;
//provide total value of inventory for this product type
public double value;
public float percentageOfTotal;
public void calcPercentOfTotal(double total) {
//given the typeValuation, calculate percentage of the total inventory is this type?
this.percentageOfTotal = (float) ((this.value * 100) / total);
}
}
private Map<String, BigDecimal> getProductPrice(String productName) {
//get current price for product
Map<String, BigDecimal> productInfo = new HashMap<String, BigDecimal>();
//simulate the pricing
productInfo.put(productName, BigDecimal.ONE);
return productInfo;
}
public void run(String... args) throws Exception {
//provide product list and process stream
}
}
For a collection of Products, each Product will have a varying purchase price each day, so there is a different routine to set the costPerUnit.
I'm looking to:
iterate over the list of products and capture a collection of the product names
e.g: List<String> productNames = productList.stream().map(Product::getName).collect(Collectors.toList());
Map the names to a function to get the current price
e.g: productNames.stream().map(this::getProductPrice).collect(Collectors.toList());
For each item in the updated price list, set the costPerUnit for each matching instance in the product inventory collection
For each instance of the product, calculate the cost (calculateProductValue) on each instance and add to the ProductInventory, I assume as a custom collector, so it can calculate the total cost of all inventory
with total cost of all inventory, calculate the percentOfTotalInventory for each product by calling the calculatePercentageOfTotalInventory
lastly, group the inventory by ProductType with the total value for the group (adding the productValue for each instance in the group) and calculate the percentageOfTotal for the group in the ProductSummaryByType class
the ProductInventory class should be fully populated at the end of the chain
Again, the reason for trying to do this with nested logic is because I'd like to invoke with parallelism. If you have any suggestions on how best to accomplish, I could use the guidance.
when i trying to do this i got the problem said
Constructor Product in class Product cannot be applied to given types;
required: java.lang.String,int,double; found: java.lang.String;
reason: actual and formal arguments lists differ in length
And i have 2 classes:
import java.text.*
public class Product {
private String name;
private int stock;
private double price;
public Product(String name, int stock, double price) {
this.name = name;
this.stock = stock;
this.price = price;
}
public double sell(int n) {
stock = n;
return stock;
}
public void restock(int n) {
}
#Override
public String toString() {
return stock + name + "at $"+price;
}
}
public class Store {
public static void main(String[] args) {
new Store().use();
}
private Product product;
private Product cashRegister;
public Store() {
product = new Product("Sticky tape");
cashRegister = new Product("Cash register");
}
public void use() {
}
private void sell() {
}
private void restock() {
}
private void viewStock() {
}
private void viewCash() {
}
private void help() {
System.out.println("Menu options");
System.out.println("s = sell");
System.out.println("r = restock");
System.out.println("v = view stock");
System.out.println("c = view cash");
System.out.println("x = exit");
}
}
I understand that i have to declare for Product constructor. But i think i have done it. If anyone know where i got wrong please explain. Thank you!
you do not have constructor with one param, so you can not using this form
product = new Product("Sticky tape");
decare one more constructor with one param or fill all param
product = new Product("Sticky tape", 10, 20.0);
You need to:
overload the constructor
public Product(String name){...}
or create instances of Product using the right and only one constructor uor have:
public Product(String name, int stock, double price)
if you overload then something like this should happen
public Product(String name){
this(name, 0, 0.0);
}
so you call a constructor from the other constructor
This is the time to learn constructor overloading. Overloading comes from OOP.
You can use Overloading to methods and constructors. Overloading means for a same method name you can implement that method
several time with different parameters(number of parameters)
. Actualy not only that,
you can use different data types for parameter.
also can change order of parameter.
keep remember method name must be same.
For the constructor also same thing. If you use for constructor you can add parameters like:
//constructor with one parameter
public Product(String name) {
this.name = name;
this.stock = 0;//or whatever your default value
this.price = 0;//or whatever your default value
}
//constructor with two parameter
public Product(String name, , int stock) {
this.name = name;
this.stock = stock;
this.price = 0;//or whatever your default value
}
public Product(String name, int stock, double price) {
this.name = name;
this.stock = stock;
this.price = price;
}
Like that you can add as many as you want.
Or you can use one constructor and pass argument to match with the implementation of the constructor when creating object. Like below:
product = new Product("Sticky tape", 0, 0);
this is not complete description you can read this to learn more
You have no constructor In Product class that takes single String argument. Create it like so:
public Product(String name) {
this.name = name;
}
In import statement you forgot semicolon:
import java.text.*;
your program is having 3 coding error which include
you forgot the " ; " after " import java.text.* " actually it is not required in your code, you can remove it, nothing will change.
you cannot make class Product as public , because you've made "Store" as your Primary class having main method.So remove public keyword from the Product class.
You didn't create a parameterized constructor
which should be like
public Product(String name){ this.name = name;}
in your product class.
your code will be like after correcting
class Product {
private String name;
private int stock;
private double price;
public Product(String name, int stock, double price) {
this.name = name;
this.stock = stock;
this.price = price;
}
public Product(String name) {
this.name = name;
}
public double sell(int n) {
stock = n;
return stock;
}
public void restock(int n) {
}
#Override
public String toString() {
return stock + name + "at $"+price;
}
}
public class Store {
public static void main(String[] args) {
Store s = new Store();
System.out.println(s.product);
System.out.println(s.cashRegister);
}
private Product product;
private Product cashRegister;
public Store() {
product = new Product("Sticky tape");
cashRegister = new Product("Cash register");
}
}
The errors are in these lines of code:
product = new Product("Sticky tape");
cashRegister = new Product("Cash register");
The Product constructor defined expects:
public Product(String name, int stock, double price)
I have two packages lets give them the name package 1 and package 2.
Class A and Class B is in package1. Class A contains an ArrayList called PTable. Class B contains a function called query() that filters through PTable,in Class A, based on a certain conditions and returns an ArrayList called result that contains all the elements from PTable that meet that condition.
I now have package2 that contains Class C. Class C imports Class B from package 1; Class C is a subclass of HttpServlet. I create an object of Class B in class C and initializer it.
I then call the function query() and assign it to a variable called results. When I try and get the properties of an element at a certain index, I can't see the properties of the original objects stored in the ArrayList PTable.[This is what appears when I try and access the properties of the objects. My aim is to see the second image ][1]
Nice to ask questions but first spend sometime studying Java. Read a book or online and you will learn about casting very quickly. Also about classes, super classes etc
Your storing the objects in a variable of type Element (your results array list).
Cast the object back to the type it belongs too and then you will see the variables.
Code design note : storing different types of classesin the same array list is legal and possible but bug prone. Try to avoid it. If you change the order of storing variables into the list, you need to change all the access code too. Anyway happy learning.
There are free online Java tutorials study them -> https://www.google.co.in/search?q=java+tutorial+beginner
Sample class, in the main method try to get the object at position 1 and cast it to a Person :
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Car {
private String manufacturer;
private String model;
private double price;
private int yearOfMfr;
private Date dateBought;
private String licenceNumber;
public Car() {
super();
}
public Car(String manufacturer, String model, double price, int yearOfMfr, Date dateBought, String licenceNumber) {
super();
this.manufacturer = manufacturer;
this.model = model;
this.price = price;
this.yearOfMfr = yearOfMfr;
this.dateBought = dateBought;
this.licenceNumber = licenceNumber;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getYearOfMfr() {
return yearOfMfr;
}
public void setYearOfMfr(int yearOfMfr) {
this.yearOfMfr = yearOfMfr;
}
public Date getDateBought() {
return dateBought;
}
public void setDateBought(Date dateBought) {
this.dateBought = dateBought;
}
public String getLicenceNumber() {
return licenceNumber;
}
public void setLicenceNumber(String licenceNumber) {
this.licenceNumber = licenceNumber;
}
}
public class DemoApp {
public static void main(String[] args) {
List<Object> results = new ArrayList<>();
DemoApp app = new DemoApp();
app.fillItUp(results);
Car acar = (Car) results.get(0);
acar.setLicenceNumber("Flying Duck");
}
private void fillItUp(List<Object> results) {
Car car = new Car("sel2in", "electric_VTOL", 540923, 2018, new Date(2018, 3, 32), "Skyprog");
results.add(car);
results.add(new Person("tushar", 39));
}
}
I am fairly new to Java and I have exhausted all of my current resources to find an answer. I am wondering if it possible to access an Objects first property to see if it matches a particular integer?
For example, I am trying to obtain a Product that is within my Database by searching for it by it's Product ID. Therefore, if I create two products such as, Product ipad = new Product(12345, "iPad", 125.0, DeptCode.COMPUTER); and Product ipod = new Product(12356, "iPod", 125.0, DeptCode.ELECTRONICS); (I have included this Product class below), and add them to an Arraylist such as, List<Product> products = new ArrayList<Product>(); how can I loop through this ArrayList in order to find that product by its ID?
This is the method I am working on:
List<Product> products = new ArrayList<Product>();
#Override
public Product getProduct(int productId) {
// TODO Auto-generated method stub
for(int i=0; i<products.size(); i++){
//if statement would go here
//I was trying: if (Product.getId() == productId) {
System.out.println(products.get(i));
}
return null;
}`
I know that I can include a conditional statement in the for loop but I cant figure out how to access the getId() method in the Product class to compare it the productId parameter?
package productdb;
public class Product {
private Integer id;
private String name;
private double price;
private DeptCode dept;
public Product(String name, double price, DeptCode code) {
this(null, name, price, code);
}
public Product(Integer id, String name, double price, DeptCode code) {
this.id = id;
this.name = name;
this.price = price;
this.dept = code;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public DeptCode getDept() {
return dept;
}
public void setDept(DeptCode dept) {
this.dept = dept;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
#Override
public String toString() {
String info = String.format("Product [productId:%d, name: %s, dept: %s, price: %.2f",
id, name, dept, price);
return info;
}
}
Please let me know
You have already got the Product out of the List<Product> in the following statement:
System.out.println(products.get(i));
Now, that you have got Product, now to get it's id, you can just call it's getId() method:
if (product.get(i).getId() == productId) {
// Return this product.
}
I would also suggest you to use enhanced for-loop instead of the traditional loop like this:
for (Product product: products) {
// Now you have the product. Just get the Id
if (product.getId() == productId) {
return product;
}
}
Also, you should change the type of productId from Integer to int. You don't need a wrapper type there.
Have you considered using a HashMap (or LinkedHashMap) instead of an Array. This way you can use the productId as the key and the product as the value?
This will let you get the object without having to loop through the entire array.
For comparing the ArrayList Objects make override equal function in your CustomObject Class Like Employee.
ArrayList<Employee> list;
Employee emp;
//suppose you have some number of items in that list and emp object contains some value.
int size=list.size();
for(int i=0;i<size;i++) {
if(list.get(i).equals(emp)) {
//todo perform operation on the basis of result.
}
}
And suppose this is your Employee class and in that class you need to override the equal function.
class Employee{
int age;
String name;
public int getAge() {
return this.age;
}
public String getName() {
return this.name;
}
public void setAge(int emp_age) {
this.age=emp_age;
}
public void setName(String emp_name) {
this.name=emp_name;
}
#Override
public boolean equal(Employee emp) {
boolean isEqual=false;
if(emp!=null && emp instanceof Employee) {
isEqual=(this.age==emp.age);
}
return isEqual;
}
}
I hope this solution will help you to check for equal values and compare the values.
Thanks
According to your commented line //I was trying: if (Product.getId() == productId) I think where you were falling over is using Product (capital P). What you needed was:
if (products.get(i).getId() == productId)
Also, you weren't returning the product you found...
The problem with that form is that a) you have to find the product in the list twice (once in the condition and then again when printing the result - a third time if you returned the product) and b) it will throw a null pointer exception if the product you are looking for is not in the list.
This is a nicer, more compact way of doing it:
#Override
public Product getProduct(int productId)
{
for(Product product : products)
{
if (productId == product.getId())
{
System.out.println(product.toString());
return product;
}
}
return null;
}