How can i change a value in an generic arraylist? - java

It's a code about a 'shopping cart' that can hold items of a class called 'item'. I had to complete the class 'item' and write another class 'discount' that can reduces the price of an item.
import java.util.ArrayList;
public class Shoppingcart extends Item {
// all shopping carts:
private ArrayList<Shoppingcart> allshoppingcart = new ArrayList<Shoppingcart>();
//Items in the shopping cart:
private ArrayList<Item> content = new ArrayList<Item>();
// Counter for shopping carts
private static int number;
/**
* Constructor
*/
public Shoppingcart() {
allshoppingcart .add(this);
this.number = number ;
this.number++;
}
/**
* load something in Shoppingcart
*/
public void load(Item i) {
this.content.add(i);
}
/**
* Sum of all items loaded in the shoppingcart
*
* #return sum of the content in the shopping cart
*/
public double sumShoppingCart() {
double sum = 0.0;
for (Item i : content) {
sum = sum + item.getPrice();
}
return sum;
}
}
The class 'item' so I can store two different types in the arraylist.
public class Item {
// normal price of item
protected double price;
// Name of product
protected String name;
/**
* setter for price and name
*/
public void setPB(String name, double price) {
this.name = name;
this.price = price;
}
/**
* getter for price
*/
public double getPrice() {
return this.price;
}
/**
* getter for the name
*/
public String getName() {
return this.name;
}
}
The class 'discount' to reduce an item for an example like a sale (special-offer).
public class Discount extends Item
{
// instance variables - replace the example below with your own
public Discount()
{
// initialise instance variables
}
public void makeSale(int percent){
percent =(100-percent)/100;
price = w.getPrice()*percent;
}
}
A test class
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Item> content = new ArrayList<>();
Item item = new Item();
Item item1 = new Item();
Item item2 = new Item();
item.setPB("Steak", 100.00);
item1.setPB("Water", 200.00);
item2.setPB("Groceries", 300.00);
content.add(item);
content.add(item1);
content.add(item2);
System.out.println("The item has the value : " + item.getPrice() + " and the name: " + item.getName());
System.out.println("There are : " + content.size() + " Item(s) in the shopping cart.");
}
}
How do I access an item and reduce it for a sale?
Thank you

This is a typical OOP exercise. You want to access two different types in a single collection. To do so they both need to have the same interface or parent.
If you use an Abstract base class you can use the following example.
First lets make an abstract Item class:
abstract class Item {
protected double price;
protected String name;
public Item(double price, String name) {
this.price = price;
this.name = name;
}
public double getPrice() {
return this.price;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setPrice(double price) {
this.price = price;
}
abstract void discount(double amount);
}
and two classes that extend from this base class:
class Food extends Item {
public Food(double price, String name) {
super(price, name);
}
#Override
void discount(double amount) {
this.price -= amount;
}
}
class Bevarage extends Item {
public Bevarage(double price, String name) {
super(price, name);
}
#Override
void discount(double amount) {
this.price -= amount;
}
}
Now lets make a class discount that has a List items that can discount both items.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Discount {
public void printAllContent(List<Item> items) {
items.forEach(item -> System.out.printf("name = %s, price = %.00f \n", item.getName(), item.getPrice()));
}
public static void main(String[] args) {
Discount card = new Discount();
List<Item> items = Arrays.asList(
new Food(3.0, "burgers"), new Food(9.0, "tomato"), new Food(8.0, "fries"),
new Bevarage(9.0, "cola"), new Bevarage(12.0, "water"), new Food(2.0, "beer")
);
card.printAllContent(items);
for (Item item : items) {
item.discount(1.0);
}
card.printAllContent(items);
// if you want to do different discounts for different items
for(Item item: items) {
if (item instanceof Bevarage) {
item.discount(2.0);
} else {
item.discount(1.0);
}
}
card.printAllContent(items);
}
}

java.util.List has these functions get(index) and set(index, object), which you could use:
//1. get your item
int index = 0;
Item item=content.get(index);
//2. create your discount
Discount discount=new Discount();
// Fill/process your discount object with the appropriate data
//3. replace the item with the discount in the list
content.set(index,discount);

Related

Adding to an object ArrayList from another Class

I have a Class named Item.
public class Item {
private int code;
private String name;
private double price;
private int quantity;
public Item(int code, String name, double price, int quantity) {
setCode(code);
setName(name);
setPrice(price);
setQuantity(quantity);
}
//Item getters and setters
And I have a Class named Stock that creates an ArrayList of Items.
public class Stock {
private ArrayList<Item> stock;
public Stock() {
stock = new ArrayList<Item>();
}
public ArrayList<Item> getStock() {
return stock;
}
I also have a Class named ItemRegister that adds an Item to the Stock.
public class ItemRegister extends Stock {
public void registerItem(String name, double price) {
getStock().add(new Item(setItemCode(), name, price, 0));
}
private int setItemCode() {
return getStock().size() + 1;
}
I'm using unit tests to see if I did add an Item to the Stock.
public class ItemRegisterTest {
#Test
public void testIfHasRegisteredItemInStock() {
Stock s = new Stock();
assertTrue(s.getStock().size() == 0);
ItemRegister i = new ItemRegister();
i.registerItem("Oleo", 20.0);
assertTrue(s.getStock().size() == 1);
}
}
When I run these tests it is returning an error.
On the second assertTrue, if I test with the object i it'll return true but what I want is to add to Stock and not ItemRegister because if later on I wanna consult Stock I'll call Stock and not ItemRegister.
From the comments, what you can do is maybe changing the parent-child relationship and having the ItemRegister holding an instance of a Stock object. So, you can modify the ItemRegister class like this:
public class ItemRegister {
Stock s;
public ItemRegister(Stock s) {
this.s = s;
}
public void registerItem(String name, double price) {
s.getStock().add(new Item(setItemCode(), name, price, 0));
}
private int setItemCode() {
return s.getStock().size() + 1;
}
}
Then, the test code you originally wrote will be true with a slight modification ItemRegister i = new ItemRegister(s);, and you can work on one instance of Stock object.
I want is to add to Stock and not ItemRegister because if later on I wanna consult Stock I'll call Stock and not ItemRegister.
Then you need to wrap Stock into ItemRegister.
public class ItemRegister {
Stock stock;
public ItemRegister(Stock stock) {
this.stock = stock;
}
public void registerItem(String name, double price) {
stock.getStock().add(new Item(setItemCode(), name, price, 0));
}
private int setItemCode() {
return stock.getStock().size() + 1;
}
}
Use it in your unit tests like this:
public class ItemRegisterTest {
#Test
public void testIfHasRegisteredItemInStock() {
Stock s = new Stock();
assertTrue(s.getStock().size() == 0);
ItemRegister i = new ItemRegister(s);
i.registerItem("Oleo", 20.0);
assertTrue(s.getStock().size() == 1);
}
}

I dont get the expected output from my java application

I got 5 classes, and 4 of them are working as intended.
I'm an absolut beginer with java and I hope someone can provide me with help.
its a little application to make orders and bundle orders.
my problem is the class bundleItem.
I expect to get the value of all items with a discount added to them, but I allways get negative return values.
Here are my classes
class Order
package testateins;
import java.util.ArrayList;
public class Order {
private ArrayList<Item> allOrders;
public Order(){
this.allOrders = new ArrayList<Item>();
}
public void addItem(Item item) {
this.allOrders.add(item);
}
public void removeItem(Item item) {
this.allOrders.remove(item);
}
public double getTotalprice(){
double totalprice = 0;
for(Item element : allOrders) {
totalprice += element.getPrice();
}
return totalprice;
}
public void printItems() {
for(Item element : allOrders) {
element.print();
}
}
}
Class Item
package testateins;
public abstract class Item{
String description;
double price;
public Item(String description) {
this.description = description;
}
public abstract double getPrice();
public void setItem() {
}
public void print() {
System.out.println("Beschreibung " + description);
}
}
class ProductItem
package testateins;
public class ProductItem extends Item{
public double pricePerUnit;
public double amount;
public double price;
public ProductItem(String description, int pricePerUnit, int amount) {
super(description);
this.pricePerUnit = pricePerUnit;
this.amount = amount;
this.price = amount * pricePerUnit;
}
public void print() {
System.out.println("Beschreibung " + description);
System.out.println("menge " + amount);
System.out.println("Preis pro Einheit " + pricePerUnit);
System.out.println("Gesammtpreis " + price);
}
public double getPrice() {
return this.price;
}
}
class ServiceItem
package testateins;
public class ServiceItem extends Item{
public double price;
public ServiceItem(String description, Integer packageprice) {
super(description);
this.price = packageprice;
}
public void print() {
System.out.println("Beschreibung " + description);
System.out.println("Servicepreis " + price);
}
public double getPrice() {
return this.price;
}
}
class BundleItem(my problemclass)
package testateins;
import java.util.ArrayList;
public class BundleItem extends Item {
private double rabatt;
private ArrayList<Item> allOrders;
public BundleItem(String description, double rabatt) {
super(description);
this.allOrders = new ArrayList<Item>();
setrabatt(rabatt);
}
public void setrabatt(double rabatt) {
this.rabatt = rabatt;
}
public double getrabatt() {
return this.rabatt;
}
public void addItem(Item item) {
if(item instanceof ProductItem || item instanceof ServiceItem) {
this.allOrders.add(item);
}
}
#Override
public double getPrice() {
double result = 0;
double sum = 0;
double discount = (rabatt/100);
for(Item element : allOrders) {
result+=element.getPrice();
}
return sum - (result * discount);
}
public void print() {
super.print();
System.out.println(rabatt);
for(Item element: allOrders) {
element.print();
}
}
}
and my testing class which returns negative discounts, the important part is after "part 2"
package testateins;
public class Testing {
public static void main(String[] args) {
ServiceItem wischen = new ServiceItem("wischen", 20);
System.out.println(wischen.description);
System.out.println(wischen.price);
System.out.println("___________________________");
ProductItem kuchen = new ProductItem("kuchen", 3, 15);
System.out.println(kuchen.description);
System.out.println(kuchen.amount);
System.out.println(kuchen.pricePerUnit);
System.out.println(kuchen.price);
System.out.println("___________________________");
Order simpleOrder = new Order();
simpleOrder.addItem(wischen);
simpleOrder.addItem(kuchen);
simpleOrder.addItem(kuchen);
simpleOrder.printItems();
System.out.println("___________________________");
System.out.println("totalpreis:");
System.out.println(simpleOrder.getTotalprice());
//part 2
System.out.println("--------uebung 2------------.-");
Order BundleOrder = new Order();
ProductItem heft = new ProductItem("Heft", 1, 10);
ProductItem stift = new ProductItem("Stift", 1, 10);
BundleItem Discounteins = new BundleItem("Discounteins(50)", 50);
BundleItem Discountzwei = new BundleItem("Discountzwei(50)", 50);
BundleItem Discountdrei = new BundleItem("Discounteins(10)", 10);
Discounteins.addItem(heft);
Discounteins.addItem(stift);
Discountzwei.addItem(Discounteins);
Discountzwei.addItem(wischen);
Discountzwei.addItem(wischen);
Discountdrei.addItem(wischen);
Discountdrei.addItem(wischen);
BundleOrder.addItem(Discountzwei);
BundleOrder.addItem(Discounteins);
BundleOrder.printItems();
System.out.println(BundleOrder.getTotalprice());
System.out.println("---------------------------.-");
Discounteins.setrabatt(50);
System.out.println(Discounteins.getrabatt());
BundleOrder.printItems();
System.out.println("---------------------------.---");
System.out.println(BundleOrder.getTotalprice());
System.out.println("---------------------------.----");
}
}
Your sum is always zero, that's why you always get negative values.
I suppose you intended to do something like this:
#Override
public double getPrice() {
double sum = 0;
double discount = (rabatt / 100);
for(Item element : allOrders) {
sum += element.getPrice();
}
return sum - (sum * discount);
}
Try replacing
return sum - (result * discount);
with
return result-(result * discount);
and remove the sum variable that is not used. Now
(result * discount)
will give you the total discount. And Subtracting it from result will give you the actual amount after discounts

OO Design pattern for shopping cart

I am trying to learn oo design pattern and developing shopping cart application where different cart items will have different types. Each type is will have some additional attributes.
Option 1: Is it good to create a separate class with every cart item with their own attributes and common attributes in base class. In this option, I will have to create multiple classes and corresponding table hierarchy in the database.
Option 2: Create single cart item with type attribute which will identify the type of the attribute. Irrelevant attributes for the particular cart item will be null in this case.
I know this is very basic question but I want to know about how people follow best practices.
Thanks in advance.
I would use Strategy for this, for example:
public interface CartItem{
String getName();
BigDecimal getPrice();
}
Only work with this interface in your shopping cart. This way, if you want a new cart item, just let it implement this interface, and it will work :)
By using an interface, you still have full freedom in how you design your actual cart items (either having 1 class, or multiple classes)
It seems to me that you do NOT want to write new code when your application has to handle new things for people to buy. Therefore, a new class when there are new items to buy is a poor design.
I was asked a similar question in an interview. The exact requirement was
Design a shopping cart with products and coupons and calculate the net price after applying coupons on products. Coupons can be of different types with certain conditions. I tried to use abstraction among Coupon/Discount processing, Cart and Product implementations classes.
N% off that is 10% off for all the individual.
D% off on next item of Type T.
D% off on next item of Type T.
Sequentially apply all the coupons on the cart and get the Total amount.
I could come up with following solution. I used CoR pattern.
import java.util.ArrayList;
import java.util.List;
interface Cart {
List<CartItem> getItems();
// void setItems(Set<CartItem> cartItems);
}
class ShoppingCart implements Cart {
private List<CartItem> items = new ArrayList<>();
boolean addItem(CartItem item) {
return items.add(item);
}
boolean removeItem(CartItem item) {
items.remove(item);
return true;
}
public List<CartItem> getItems() {
return items;
}
public double totalCartValue() {
double total = 0;
for (CartItem item : items) {
total += item.getPrice();
}
return total;
}
}
interface CartItem {
public String getName();
public double getPrice();
public void setPrice(double price);
}
abstract class Product implements CartItem {
String name;
double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
class Card extends Product {
public Card(String name, double price) {
this.name = name;
this.price = price;
}
}
class Tshirt extends Product {
public Tshirt(String name, double price) {
this.name = name;
this.price = price;
}
}
class BackPack extends Product {
public BackPack(String name, double price) {
this.name = name;
this.price = price;
}
}
interface Coupon {
void apply(Cart cart);
void setSuccessor(Coupon successor);
}
class CouponAll implements Coupon {
private static final float DISCOUNT = 0.25f;
Coupon successor;
public void setSuccessor(Coupon successor) {
this.successor = successor;
}
public void apply(Cart cart) {
for (CartItem item : cart.getItems()) {
item.setPrice(item.getPrice() - item.getPrice() * DISCOUNT);
}
if (successor != null) {
successor.apply(cart);
}
}
}
class CouponNext implements Coupon {
private static final float DISCOUNT = 0.10f;
private int discountItemIndex;
Coupon successor;
CouponNext(int discountItemIndex) {
this.discountItemIndex = discountItemIndex;
}
public void setSuccessor(Coupon successor) {
this.successor = successor;
}
public void apply(Cart cart) {
if(discountItemIndex < cart.getItems().size()) {
CartItem cartItem = cart.getItems().get(discountItemIndex);
cartItem.setPrice(cartItem.getPrice() - cartItem.getPrice() * DISCOUNT);
}
if (successor != null) {
successor.apply(cart);
}
}
}
class CouponNextBackPack implements Coupon {
private static final float DISCOUNT = 0.15f;
private int discountItemStartIndex;
Coupon successor;
Class<?> productType;
CouponNextBackPack(int discountItemStartIndex ,Class<?> productType) {
this.discountItemStartIndex = discountItemStartIndex;
this.productType = productType;
}
public void setSuccessor(Coupon successor) {
this.successor = successor;
}
public void apply(Cart cart) {
if (discountItemStartIndex < cart.getItems().size()) {
for (int i = discountItemStartIndex; i < cart.getItems().size(); ++i) {
CartItem cartItem = cart.getItems().get(i);
if(productType.isInstance(cartItem)) {
cartItem.setPrice(cartItem.getPrice() - cartItem.getPrice() * DISCOUNT);
break;
}
}
}
if (successor != null) {
successor.apply(cart);
}
}
}
public class DriverClassCoR {
public static void main(String[] args) {
Product card1 = new Card("Card", 12.99);
Product card2 = new Card("Card", 12.99);
Product card3 = new Card("Card", 12.99);
Product tshirt1 = new Tshirt("Tshirt", 24.99);
Product tshirt2 = new Tshirt("Tshirt", 24.99);
Product backPack1 = new BackPack("BackPack", 34.99);
ShoppingCart cart = new ShoppingCart();
cart.addItem(card1); cart.addItem(card2); cart.addItem(card3);
Coupon couponAll = new CouponAll();
cart.addItem(tshirt1);
Coupon couponNext = new CouponNext(cart.getItems().size());
couponAll.setSuccessor(couponNext);
Coupon couponNextBackPack =null;
couponNextBackPack = new CouponNextBackPack(cart.getItems().size(), BackPack.class);
couponNext.setSuccessor(couponNextBackPack);
cart.addItem(tshirt2);
cart.addItem(backPack1);
System.out.println("Total car value before discounts \t" +cart.totalCartValue());
couponAll.apply(cart);
//System.out.println(backPack1.getClass().isInstance(backPack1));
System.out.println("Total car value after discounts \t" +cart.totalCartValue());
}
}
Hope this helps.

How can I search through a scanner and divide a String by spaces?

I am trying to construct a store by reading items from a given Scanner. The constructor must repeatedly (until item name is *) read items from the given scanner object and add it to its inventory.
BreadLoaf 2.75 25
I need to divide a string like this into "Breadloaf" "2.75", and "25". And then go to the next line and do the same thing until it reads "*"
public class Store {
private ArrayList<Item> inventory;
// CONSTRUCTORS
/*
* Constructs a store without any items in its inventory.
*/
public Store() {
}
/*
* Constructs a store by reading items from a given Scanner. The constructor
* must repeatedly (until item name is *) read items from the given scanner
* object and add it to its inventory. Here is an example of the data (that
* has three items) that could be entered for reading from the supplied
* scanner:
*/
public Store(Scanner keyboard) {
while(keyboard != null){
}
}
Try below code. it works I have recently checked.
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class MyClient {
public static void main(String args[]) {
List<Item> inventory = new ArrayList<Item>();
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s1 = sc.nextLine();
if (s1.equals("*")) {
break;
} else {
Scanner ls = new Scanner(s1);
while (ls.hasNext()) {
Item item = new Item(ls.next(), ls.nextFloat(), ls.nextInt());
inventory.add(item);
}
}
}
System.out.println(inventory);
}
}
Now you need to create an Item.java below is Item .java
public class Item {
private String name;
private int quanity;
private float price;
public Item(String name, float price, int quanity) {
this.name = name;
this.price = price;
this.quanity = quanity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQuanity() {
return quanity;
}
public void setQuanity(int quanity) {
this.quanity = quanity;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
#Override
public String toString() {
return "Item [name=" + name + ", quanity=" + quanity + ", price="
+ price + "]";
}
}
After typing all the inventory type "*"(star) at the end it will list all the entered Items .

How do I override a method in a subclass?

I have an inventory program written to include an array and a method to calculate total cost for all inventory items entered. I now have to include a subclass that overrides the original to include "one unique feature". I created a new file named ItemDetails to set up for the subclasses of the original Item. I need to include one unique feature and calculate the value of the inventory and calculate a 5% restocking fee in this subclass. Do I just transfer some of the relevant lines into the other class? Or do I write some code twice? I don't know what to do next. Any help is useful. Thanks. This is what I have so far:
package inventory3;
public class ItemDetails extends Items
{
public static void override()
{
private String Name;
private double pNumber, Units, Price;
public ItemDetails()
{
}
}
}
This is the Item class file that it is supposed to override:
package inventory3;
import java.lang.Comparable;
public class Items implements Comparable
{
private String Name;
private double pNumber, Units, Price;
public Items()
{
Name = "";
pNumber = 0.0;
Units = 0.0;
Price = 0.0;
}
public int compareTo(Object item)
{
Items tmp = (Items) item;
return this.getName().compareTo(tmp.getName());
}
public Items(String productName, double productNumber, double unitsInStock, double unitPrice)
{
Name = productName;
pNumber = productNumber;
Units = unitsInStock;
Price = unitPrice;
}
//setter methods
public void setName(String n)
{
Name = n;
}
public void setpNumber(double no)
{
pNumber = no;
}
public void setUnits(double u)
{
Units = u;
}
public void setPrice(double p)
{
Price = p;
}
//getter methods
public String getName()
{
return Name;
}
public double getpNumber()
{
return pNumber;
}
public double getUnits()
{
return Units;
}
public double getPrice()
{
return Price;
}
public double calculateTotalPrice()
{
return (Units * Price);
}
public static double getCombinedCost(Items[] item)
{
double combined = 0;
for(int i =0; i < item.length; ++i)
{
combined = combined + item[i].calculateTotalPrice();
}
return combined;
}
}
You simply declare a method with the same signature as the method in the parent class. So yours would look like:
package inventory3;
public class ItemDetails extends Items {
private String Name;
private double pNumber, Units, Price;
public ItemDetails(String Name, double pNumber, double Units, double Price) {
this.Name = Name;
this.pNumber = pNumber;
this.Units = Units;
this.Price = Price;
}
// getters and setters....
// The #Override is optional, but recommended.
#Override
public double calculateTotalPrice() {
return Units * Price * 1.05; // From my understanding this is what you want to do
}
}

Categories

Resources