I just try to understand streams in Java and I stuck at sorting phase.
My purpose is to get most expensive vege pizza with one stream. At this point I get pizza price but I can't sort it. Can anyone tell me how I should do it ?
I try with this :
pizzas.stream()
.flatMap(pizza -> Stream.of(pizza.getIngredients())
.filter(list -> list.stream().noneMatch(Ingredient::isMeat))
.map(list -> list.stream().map(Ingredient::getPrice).reduce(0,(a, b) -> a + b))
.sorted((o1, o2) -> o1.intValue() - o2.intValue())
)
.forEach(System.out::println);
This code returns me unsorted values of pizza.
import java.util.Collection;
import java.util.Comparator;
interface Pizza {
interface Ingredient {
boolean isMeat();
int getPrice();
}
Collection<Ingredient> getIngredients();
static boolean isVegetarian(Pizza pizza) {
return pizza.getIngredients().stream().noneMatch(Ingredient::isMeat);
}
static int price(Pizza pizza) {
return pizza.getIngredients().stream().mapToInt(Ingredient::getPrice).sum();
}
static Pizza mostExpensiveVegetarianPizza(Collection<Pizza> pizzas) {
return pizzas.stream()
.filter(Pizza::isVegetarian)
.max(Comparator.comparingInt(Pizza::price))
.orElseThrow(() -> new IllegalArgumentException("no veggie pizzas"));
}
}
If you want Ingredient.getPrice() to return a double, you would use Stream.mapToDouble() in Pizza.price() and Comparator.comparingDouble() in Pizza.mostExpensiveVegetarianPizza().
To find the pizza with the highest price you need to either compute the price of each pizza every time the prices are compared or have an object that stores both the pizza and the price.
Here's a solution that uses an anonymous object to hold the temporary state where we need both the pizza and its price:
Optional<Pizza> pizza = pizzas.stream()
.filter(p -> p.getIngredients().stream()
.noneMatch(Ingredient::isMeat)) // filter
.map(p -> new Object() { // anonymous object to hold (pizza, price)
Pizza pizza = p; // store pizza
int price = p.getIngredients().stream()
.mapToInt(Ingredient::getPrice).sum(); // store price
})
.max(Comparator.comparingInt(o -> o.price)) // find the highest price
.map(o -> o.pizza); // get the corresponding pizza
I've made a short functional example. I have encapsulated some streams inside Pizza class to improve legibility.
INGREDIENT
public class Ingredient {
private String name;
private double price;
private boolean meat;
public Ingredient(String name, double price, boolean meat) {
this.name = name;
this.price = price;
this.meat = meat;
}
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;
}
public boolean isMeat() {
return meat;
}
public void setMeat(boolean meat) {
this.meat = meat;
}
}
PIZZA
public class Pizza {
private String name;
private List<Ingredient> ingredients;
public Pizza(String name, List<Ingredient> ingredients) {
this.name = name;
this.ingredients = ingredients;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Ingredient> getIngredients() {
return ingredients;
}
public void setIngredients(List<Ingredient> ingredients) {
this.ingredients = ingredients;
}
public boolean isVegan() {
return (ingredients != null) ? ingredients.stream().noneMatch(Ingredient::isMeat)
: false;
}
public double getTotalCost() {
return (ingredients != null) ? ingredients.stream().map(Ingredient::getPrice)
.reduce(0.0, Double::sum)
: 0;
}
#Override
public String toString() {
return "Pizza [name=" + name + "; cost=" + getTotalCost() +"$]";
}
}
MAIN
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class VeganPizzaPlace {
public static void checkMostExpensiveVeganPizza(List<Pizza> pizzas) {
if (pizzas != null) {
Optional<Pizza> maxVegan =
pizzas.stream()
.filter(Pizza::isVegan)
.max(Comparator.comparingDouble(Pizza::getTotalCost));
if (maxVegan.isPresent()) {
System.out.println(maxVegan.get().toString());
} else {
System.out.println("No vegan pizzas in the menu today");
}
}
}
public static void main (String[] args) {
List<Pizza> pizzas = new ArrayList<Pizza>();
Ingredient tomato = new Ingredient("tomato", 0.50, false);
Ingredient cheese = new Ingredient("cheese", 0.75, false);
Ingredient broccoli = new Ingredient("broccoli", 50.00, false);
Ingredient ham = new Ingredient("ham", 10.00, true);
List<Ingredient> ingredientsMargherita = new ArrayList<Ingredient>();
ingredientsMargherita.add(tomato);
ingredientsMargherita.add(cheese);
Pizza margherita = new Pizza("margherita", ingredientsMargherita);
List<Ingredient> ingredientsSpecial = new ArrayList<Ingredient>();
ingredientsSpecial.add(tomato);
ingredientsSpecial.add(cheese);
ingredientsSpecial.add(broccoli);
Pizza special = new Pizza("special", ingredientsSpecial);
List<Ingredient> ingredientsProsciutto = new ArrayList<Ingredient>();
ingredientsProsciutto.add(tomato);
ingredientsProsciutto.add(cheese);
ingredientsProsciutto.add(ham);
Pizza prosciutto = new Pizza("prosciutto", ingredientsProsciutto);
pizzas.add(margherita);
pizzas.add(special);
pizzas.add(prosciutto);
checkMostExpensiveVeganPizza(pizzas);
}
}
OUTPUT
Pizza [name=special; cost=51.25$]
If you do not like clean code, you can use instead
Optional<Pizza> maxVegan =
pizzas.stream()
.filter(p -> p.getIngredients().stream().noneMatch(Ingredient::isMeat))
.reduce((p1, p2) -> p1.getIngredients().stream().map(Ingredient::getPrice).reduce(0.0, Double::sum)
< p2.getIngredients().stream().map(Ingredient::getPrice).reduce(0.0, Double::sum) ? p1 : p2);
EDIT: Expression for selecting max valued pizza using a reduce is based on listing 5.8 (page 110) from the book "Java 8 in action" by Urma, Fusco and Mycroft. A great book! :-)
Related
If i have 2 classes the first one is BasicHamburger
public class BasicHamburger {
private String breadRollType;
private String meat;
private boolean lettuce;
private boolean tomato;
private boolean carrot;
private boolean cheese;
private int numberOfAdditions;
private int price;
public BasicHamburger(String breadRollType , String meat ,int price){
this.breadRollType = breadRollType;
this.meat = meat;
this.price = price;
lettuce = false;
tomato = false;
carrot = false;
cheese = false;
numberOfAdditions = 0;
}
public void addLettuce(){
lettuce = true;
incrementNumberOfAdditions();
}
public void addTomato(){
tomato = true;
incrementNumberOfAdditions();
}
public void addCarrot(){
carrot = true;
incrementNumberOfAdditions();
}
public void addCheese(){
cheese = true;
incrementNumberOfAdditions();
}
public int getNumberOfAdditions(){
return numberOfAdditions;
}
protected int incrementNumberOfAdditions(){
return ++numberOfAdditions;
}
public boolean isLettuce() {
return lettuce;
}
public boolean isTomato() {
return tomato;
}
public boolean isCarrot() {
return carrot;
}
public boolean isCheese() {
return cheese;
}
public int getBasicHamburgerPrice(){
return price;
}
public int getLettucePrice(){
return 20;
}
public int getTomatoPrice(){
return 15;
}
public int getCheesePrice(){
return 40;
}
public int getCarrotPrice(){
return 10;
}
public int getTotalBasicHamburgerPrice(){
if(isCarrot()){
price = price + 10;
}
if(isCheese()){
price = price + 40;
}
if(isTomato()){
price = price + 15;
}
if(isLettuce()){
price = price + 20;
}
return price;
}
public void displayBurgerDetailsWithPrices(){
if(isCarrot()){
System.out.println("Carrot addition = "+getCarrotPrice());
}
if(isCheese()){
System.out.println("Cheese addition = "+getCheesePrice());
}
if(isTomato()){
System.out.println("Tomato addition = "+getTomatoPrice());
}
if(isLettuce()){
System.out.println("Lettuce addition = "+getLettucePrice());
}
System.out.println("Basic Hamburger Total Price Without Additions = "+getBasicHamburgerPrice());
System.out.println("Basic Hamburger Total Price After Additions= "+getTotalBasicHamburgerPrice());
}
}
the second class is HealthyBurger
public class HealthyBurger extends BasicHamburger{
private boolean onion;
private boolean bacon;
public HealthyBurger(){
super("Brown Rye ","Mutton",30);
onion = false;
bacon = false;
}
public boolean isOnion() {
return onion;
}
public boolean isBacon() {
return bacon;
}
public void addOnion(){
onion = true;
incrementNumberOfAdditions();
}
public void addBacon(){
bacon = true;
incrementNumberOfAdditions();
}
public int getOnionPrice(){
return 15;
}
public int getBaconPrice(){
return 20;
}
#Override
public int getTotalBasicHamburgerPrice() {
int newPrice = super.getTotalBasicHamburgerPrice();
if(isBacon()){
newPrice += 20;
}
if(isOnion()){
newPrice +=15;
}
return newPrice;
}
#Override
public void displayBurgerDetailsWithPrices() {
if(isCarrot()){
System.out.println("Carrot addition = "+getCarrotPrice());
}
if(isCheese()){
System.out.println("Cheese addition = "+getCheesePrice());
}
if(isTomato()){
System.out.println("Tomato addition = "+getTomatoPrice());
}
if(isLettuce()){
System.out.println("Lettuce addition = "+getLettucePrice());
}
if(isOnion()){
System.out.println("Onion addition = "+getOnionPrice());
}
if(isBacon()){
System.out.println("Bacon addition = "+getBaconPrice());
}
System.out.println("Healthy Hamburger Total Price Without Additions = "+getBasicHamburgerPrice());
System.out.println("Healthy Hamburger Total Price After Additions= "+getTotalBasicHamburgerPrice());
}
}
in the main i have written this code
public class Main {
public static void DisplayBurger(BasicHamburger burger){
burger.displayBurgerDetailsWithPrices();
}
public static void main(String[] args) {
BasicHamburger ham1 = new BasicHamburger("x","beef",20);
ham1.addCarrot();
ham1.addCheese();
ham1.addLettuce();
ham1.addTomato();
HealthyBurger ham2 = new HealthyBurger();
ham2.addOnion();
ham2.addBacon();
BasicHamburger test = ham2;
DisplayBurger(test);
}
}
My confusion is the test variable can access displayBurgerDetailsWithPrices() function inside HealthyBurger class and can call the isOnion which is inside that function. Whereas if i decided to write that code inside the main i can not access the isOnion() function.
BasicHamburger newBurger = new HealthyBurger();
newBurger.isOnion();
To make the question clear and right to the point , why accessing a function inside a subclass through a overriden function is possible whereas accessing that function directly is not possible when using a variable of the superclass?
BasicHamburger newBurger = new HealthyBurger();
boolean onion = false;
if(newBurger instanceof HealthyBurger)
onion = ((HealthyBurger).isOnion());
To make the question clear and right to the point, why accessing a function inside a subclass through an overridden function is possible whereas accessing that function directly is not possible when using a variable of the superclass?
It calles Polymophism. The object reference BasicHamburger newBurger refers to the instance of class BasicHamburger or any of its children. It means that by default you have access only to the methods declared in BasicHamburger or any of its parent. If you want to call the children's method, you have to cast this reference to the required type.
I would redesign your code, because in general case if you use casting, then it looks like a design problem (repeat: in general; sometimes it really needed).
public abstract class Burger {
protected final String breadRollType;
protected final String meat;
protected final int basePrice;
protected final Set<Ingredient> ingredients;
protected Burger(String breadRollType, String meat, int basePrice, Set<Ingredient> ingredients) {
this.breadRollType = breadRollType;
this.meat = meat;
this.basePrice = basePrice;
this.ingredients = ingredients == null || ingredients.isEmpty() ? Set.of() : Set.copyOf(ingredients);
}
public final int getBasePrice() {
return basePrice;
}
protected int getIngredientsPrice() {
return ingredients.stream()
.map(Ingredient::getPrice)
.mapToInt(i -> i)
.sum();
}
public int getTotalPrice() {
return basePrice + getIngredientsPrice();
}
public final int getTotalIngredients() {
return ingredients.size();
}
public final boolean hasIngredient(Ingredient ingredient) {
return ingredient != null && ingredients.contains(ingredient);
}
public void printDetailsWithPrices() {
System.out.println(breadRollType + ' ' + meat);
System.out.println("----");
System.out.println("Basic price: " + basePrice);
System.out.println("Ingredients price: " + getIngredientsPrice());
ingredients.forEach(ingredient -> System.out.format("-> %s price: %d\n",
ingredient.getTitle(), ingredient.getPrice()));
System.out.println("Total price: " + getTotalPrice());
}
protected interface Ingredient {
String getTitle();
int getPrice();
}
}
public class HealthyBurger extends Burger {
public HealthyBurger(String breadRollType, String meat, int basePrice, Set<Burger.Ingredient> ingredients) {
super(breadRollType, meat, basePrice, ingredients);
}
public enum Ingredient implements Burger.Ingredient {
ONION("Onion", 15),
BACON("Bacon", 20);
private final String title;
private final int price;
Ingredient(String title, int price) {
this.title = title;
this.price = price;
}
#Override
public String getTitle() {
return title;
}
#Override
public int getPrice() {
return price;
}
}
}
public class PopularBurger extends Burger {
protected PopularBurger(String breadRollType, String meat, int basePrice, Set<Burger.Ingredient> ingredients) {
super(breadRollType, meat, basePrice, ingredients);
}
public enum Ingredient implements Burger.Ingredient {
LETTUCE("Lettuce", 20),
TOMATO("Tomato", 25),
CARROT("Carrot", 10),
CHEESE("Cheese", 40);
private final String title;
private final int price;
Ingredient(String title, int price) {
this.title = title;
this.price = price;
}
#Override
public String getTitle() {
return title;
}
#Override
public int getPrice() {
return price;
}
}
}
public static void main(String... args) {
PopularBurger popularBurger = new PopularBurger("x", "beef", 20,
Set.of(PopularBurger.Ingredient.CARROT,
PopularBurger.Ingredient.CHEESE,
PopularBurger.Ingredient.LETTUCE,
PopularBurger.Ingredient.TOMATO));
HealthyBurger healthyBurger = new HealthyBurger("Brown Rye", "Mutton", 30,
Set.of(HealthyBurger.Ingredient.ONION,
HealthyBurger.Ingredient.BACON));
PopularBurger one = popularBurger;
one.printDetailsWithPrices();
System.out.println();
HealthyBurger two = healthyBurger;
two.printDetailsWithPrices();
System.out.println();
boolean withOnion = two.hasIngredient(HealthyBurger.Ingredient.ONION);
System.out.println(withOnion);
}
x beef
----
Basic price: 20
Ingredients price: 95
-> Cheese price: 40
-> Carrot price: 10
-> Lettuce price: 20
-> Tomato price: 25
Total price: 115
Brown Rye Mutton
----
Basic price: 30
Ingredients price: 35
-> Onion price: 15
-> Bacon price: 20
Total price: 65
true
I'm trying to add static methods largest and smallest to the Measurable interface.
The methods should return the object with the largest or smallest measure (double) from an array of Measurable Country objects. I tried doing so in the interface, but someone recommended me using the Comparator interface. How can this be done by using the Measurable interface instead?
class Main {
public static void main(String args[]) {
Measurable[] countries = new Measurable[3];
countries[0] = new Country("Uruguay", 176220);
countries[1] = new Country("Thailand", 514000);
countries[2] = new Country("Belgium", 30510);
Measurable maximum = Measurable.largest(countries);
Measurable smallest = Measurable.smallest(countries);
}
}
class Country implements Measurable {
private String name;
private double area;
public Country(String name, double area) {
this.name = name;
this.area = area;
}
}
interface Measurable {
static Measurable largest(Measurable[] countries) {
public static Measurable largest(Measurable[]objects){
if (objects == null || objects.length == 0) {
return new Country("", 0);
}
Measurable max = new Country("", 0);
for (Measurable obj : objects) {
if (obj.getMeasure() > max.getMeasure()) {
max = obj;
}
}
return max;
}
}
static Measurable smallest(Measurable[] objects) {
if (objects == null || objects.length == 0) {
return new Country("", 0);
}
Measurable max = new Country("", 0);
for (Measurable obj : objects) {
if (obj.getMeasure() < min.getMeasure()) {
min = obj;
}
}
return min;
}
}
double getMeasure();
}
You don't need to create the Measurable interface if you want to use Comparator/Comparable.
Just implement Comparable in Country and then loop through the array to find min and max.
class Main {
public static void main(String args[]) {
Country[] countries = new Country[3];
countries[0] = new Country("Uruguay", 176220);
countries[1] = new Country("Thailand", 514000);
countries[2] = new Country("Belgium", 30510);
Country max = null;
Country min = null;
for (Country c : countries) {
if (max == null || max.compareTo(c) < 0) {
max = c;
}
if (min == null || min.compareTo(c) > 0) {
min = c;
}
}
System.out.printf("max: %s (%s)%n", max.name, max.area);
System.out.printf("min: %s (%s)%n", min.name, min.area);
}
}
class Country implements Comparable<Country> {
String name;
double area;
public Country(String name, double area) {
this.name = name;
this.area = area;
}
#Override
public int compareTo(Country other) {
// Returns int <0 if this is smaller than other
// 0 if they are equal
// int >0 if this is greater than other
return Double.compare(this.area, other.area);
}
}
If you put your countries in a collection you can use the Collections.min() and Collections.max() functions together with the Comparable interface. Your main method would then look like this:
public static void main(String args[]) {
List<Country> countries = new ArrayList<>();
countries.add(new Country("Uruguay", 176220));
countries.add(new Country("Thailand", 514000));
countries.add(new Country("Belgium", 30510));
Country max = Collections.max(countries);
Country min = Collections.min(countries);
System.out.printf("max: %s (%s)%n", max.name, max.area);
System.out.printf("min: %s (%s)%n", min.name, min.area);
}
If you still want to use the Measurable interface you can extend ArrayList and have that class implement it like this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Main {
public static void main(String args[]) {
CountryList countries = new CountryList();
countries.add(new Country("Uruguay", 176220));
countries.add(new Country("Thailand", 514000));
countries.add(new Country("Belgium", 30510));
Country max = countries.getLargest();
Country min = countries.getSmallest();
System.out.printf("max: %s (%s)%n", max.name, max.area);
System.out.printf("min: %s (%s)%n", min.name, min.area);
}
}
class CountryList extends ArrayList<Country> implements Measurable{
#Override
public Country getSmallest() {
return Collections.min(this);
}
#Override
public Country getLargest() {
return Collections.max(this);
}
}
interface Measurable{
Country getSmallest();
Country getLargest();
}
class Country implements Comparable<Country> {
String name;
double area;
public Country(String name, double area) {
this.name = name;
this.area = area;
}
#Override
public int compareTo(Country o) {
return Double.compare(this.area, o.area);
}
}
I'm trying to compare a bunch of Objects of the same class to search for matching ID's?
This is the GroupClass, when a new entry is entered it will test against the idNumber to see if there is a match.
Public GroupClass {
private int idNumber;
private String name;
private double income;
public GroupClass(int id, String name, double income){
this.idNumber = id;
this.name = name;
this.income = income;
}
public int getIdNumber() {
return idNumber;
}
public void setIdNumber(int idNumber) {
this.idNumber = idNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
}
This is the Main Method
import static java.lang.reflect.Array.set;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
public class ListTester {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Set<GroupClass> groupArray = new LinkedHashSet<>();
System.out.println("Enter a ID Number");
int id = input.nextInt();
System.out.println("Enter a First Name");
String name = input.next();
System.out.println("Enter a an Income");
double income = input.nextDouble();
groupArray.add(new GroupClass(1111, "Billy", 178000));
groupArray.add(new GroupClass(1112, "Sam", 78000));
groupArray.add(new GroupClass(1113, "Mark", 79000));
groupArray.add(new GroupClass(id, name, income));
printTheClass(groupArray);
}
public static void printTheClass(Set group){
for(Object theArray: group){
System.out.println(theArray + " ");
}
}
}
Ive seen a few questions like it but just cant get it to work for my particular case, thanks in advance.
As per the above comment you override the equals method, but this may not be suitable for the long term growth of the class.
But using your existing code try
public static void printTheClass(Set<GroupClass> group){
for(GroupClass theArray: group){
System.out.println(theArray + " ");
}
}
and
public static GroupClass findTheClass(Set<GroupClass> group, int id){
for(GroupClass obj: group){
if(obj.getIdNumber == id) return obj;
}
return null;
}
This can be used as
if (findTheClass (groupArray, id) == null) {
groupArray.add (new GroupClass(id, name, income));
}
Not quite sure what is your goal. If you want to reject any new entry if the id already exist, you need to override the hashCode and equals methods of the GroupClass so that LinkedHashSet knows if two GroupClass objects are different:
#Override
public int hashCode() {
return this.idNumber;
}
#Override
public boolean equals(Object obj) {
return obj instanceof GroupClass && ((GroupClass) obj).getIdNumber() == this.idNumber;
}
However, in most cases, you might want to retrieve an entry using its id number. Then it might be better to use a map with id as key, and the GroupoClass object itself as value
Map<Integer, GroupClass> groupmap = new HashMap<>()
groupmap.put(id, new GroupClass(id, name, income));
and you will have to use groupmap.keySet() to iterate the map.
Basically I have multiple classes and I'm trying to get an array of LineItem for each Item that a customer purchases. LineItem includes the UPC, Description, Price, Quantity, SubTotal and Discount which is all stored in a seperate class. I'm trying to get it that when you use the method addItemToSaleList it will add to the array. I need to use an array and not an array list, so I have to copy over the array to a temp array, and then recreate a new array adding to the number the array can store and then recopying it over. I'm stuck getting the array to generate. Below is the code I have
public class Product {
private double price;
private String description;
private String ProductCode;
private DiscountStrategy discoutStrategy;
public Product(double price, String description, String ProductCode, DiscountStrategy discoutStrategy) {
this.price = price;
this.description = description;
this.ProductCode = ProductCode;
this.discoutStrategy = discoutStrategy;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getProductCode() {
return ProductCode;
}
public void setProductCode(String ProductCode) {
this.ProductCode = ProductCode;
}
public DiscountStrategy getDiscountStrategy() {
return discoutStrategy;
}
public void setDiscoutStrategy(DiscountStrategy discoutStrategy) {
this.discoutStrategy = discoutStrategy;
}
}
public class LineItem {
private Product product;
private double quantity;
public LineItem(Product product, double quantity) {
this.product = product;
this.quantity = quantity;
}
//Calculates the Discount Amount whether or not it's a percentage or dollar
//off
public double getDiscountAmount () {
return product.getDiscountStrategy().getDiscount(product.getPrice(), quantity);
}
//Calculates the Subtotal, gets the quantity from the DiscountStrategy and then
//the price from the product
public double getSubTotal() {
return quantity * product.getPrice();
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public double getQuantity() {
return quantity;
}
public void setQuantity(double quantity) {
this.quantity = quantity;
}
public class Receipt {
private LineItem[] lineItem = new LineItem[0];
public Receipt(LineItem[] lineItem) {
this.lineItem = lineItem;
}
public void addProductToTotalSale(LineItem li) {
addItemToSaleList();
}
public void addItemToSaleList() {
LineItem[] tempItemList = new LineItem[lineItem.length + 1];
for (int i = 0; i < tempItemList.length; i++) {
tempItemList[i] = lineItem[i];
}
lineItem = new LineItem[tempItemList.length];
for (int j = 0; j < lineItem.length; j++) {
lineItem[j] = tempItemList[j];
}
}
public LineItem[] getLineItem() {
return lineItem;
}
I would remove addItemToSaleList() and implement addProductToTotalSale(LineItem) like so
public void addProductToTotalSale(LineItem li) {
// Allocate the memory.
LineItem[] tempLineItem = new LineItem[1 + lineItem.length];
// Copy the array.
if (lineItem.length > 0) {
System.arraycopy(lineItem, 0, tempLineItem, 0, lineItem.length);
}
// add the new item to the new slot.
tempLineItem[lineItem.length] = li;
// update the internal array reference.
lineItem = tempLineItem;
}
Next, you should protect your constructor from null;
public Receipt(LineItem[] lineItem) {
// Try and protect from bad calls, removes need to check for nulls in
// add (addProductToTotalSale) routine.
if (lineItem != null) {
this.lineItem = lineItem;
}
}
Because you provide a default 0 sized array your code appears to be safe to continue to include the default constructor. But, you might consider making your Receipt class immutable.
I'm not sure why you are making two new arrays. You only need one...
public void addProductToTotalSale(LineItem li) {
addItemToSaleList();
lineItem[lineItem.length-1] = li;
}
public void addItemToSaleList() {
LineItem[] tempItemList = new LineItem[lineItem.length + 1];
for (int i = 0; i < tempItemList.length; i++) {
tempItemList[i] = lineItem[i];
}
lineItem = tempItemList;
}
What would be the simplest method to print this array broken down into each mobile phone as a product number, name department etc, and then re print the same information sorted by product name. I have tried a couple different methods and am already passed the turn in date for the assignment but still need to figure it out for upcoming assignment this weekend. When I try to implement the comparator on MobilePhone class it forces me to make it abstract or use #override but I can't figure out where or what to override to make it work because the abstract class causes a multitude of other problems.
package InventoryPro2;
import java.util.*;
class MobilePhone {
private double productNumber; // Variables
private String name;
private String department;
private double unitsInStock;
private double unitPrice;
public MobilePhone() {
this(0.0, "", "", 0.0, 0.0);
}
public MobilePhone(double productNumber, String name, String department,
double unitsInStock, double unitPrice) { //assign variables
this.productNumber = productNumber;
this.name = name;
this.department = department;
this.unitsInStock = unitsInStock;
this.unitPrice = unitPrice;
}
public double getproductNumber() { // retrieve values
return productNumber;
}
public String getname() {
return name;
}
public String getdepartment() {
return department;
}
public double getunitPrice() {
return unitPrice;
}
public double getunitsInStock() {
return unitsInStock;
}
public void setproductNumber(double productNumber) {
this.productNumber = productNumber;
}
public void setname(String name) {
this.name = name;
}
public void setdepartment(String department) {
this.department = department;
}
public void setunitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
public void setunitsInStock(double unitsInStock) {
this.unitsInStock = unitsInStock;
}
public double gettotalInv() {
return getunitPrice() * getunitsInStock();
}
}
public class InventoryPro2 {
MobilePhone mobilephone = new MobilePhone();
public static void main(String args[]) {
System.out.println("Mobile Phone Inventory Program");
System.out.println();//skips a line
MobilePhone[] phones = new MobilePhone[5];
phones[0] = new MobilePhone();
phones[0].setproductNumber(1);
phones[0].setname("Motorola");
phones[0].setdepartment("Electronics");
phones[0].setunitPrice(150.10);
phones[0].setunitsInStock(98);
phones[1] = new MobilePhone();
phones[1].setproductNumber(2);
phones[1].setname("Samsung");
phones[1].setdepartment("Electronics");
phones[1].setunitPrice(199.99);
phones[1].setunitsInStock(650);
phones[2] = new MobilePhone();
phones[2].setproductNumber(3);
phones[2].setname("Nokia");
phones[2].setdepartment("Electronics");
phones[2].setunitPrice(200.25);
phones[2].setunitsInStock(125);
phones[3] = new MobilePhone();
phones[3].setproductNumber(4);
phones[3].setname("LG");
phones[3].setdepartment("Electronics");
phones[3].setunitPrice(100.05);
phones[3].setunitsInStock(200);
phones[4] = new MobilePhone();
phones[4].setproductNumber(5);
phones[4].setname("IPhone");
phones[4].setdepartment("Electronics");
phones[4].setunitPrice(299.99);
phones[4].setunitsInStock(150);
System.out.println("Order of inventory before sorting:");
System.out.println();
}
}
(Also, what is the best way to take just one piece of information out of each part of the array such as the totalInv and total all of those numbers to print?) Do I have unnecessary code here or have I done everything right thus far? I have to say that learning this coding language in an online format has not been a very enjoyable experience thus far..
Here is how to sort by name
import java.util.Arrays;
import java.util.Comparator;
public class AppInventoryPro2 {
public static void main(String... args) {
System.out.println("Mobile Phone Inventory Program");
System.out.println();// skips a line
MobilePhone[] phones = new MobilePhone[5];
phones[0] = new MobilePhone();
phones[0].setproductNumber(1);
phones[0].setname("Motorola");
phones[0].setdepartment("Electronics");
phones[0].setunitPrice(150.10);
phones[0].setunitsInStock(98);
phones[1] = new MobilePhone();
phones[1].setproductNumber(2);
phones[1].setname("Samsung");
phones[1].setdepartment("Electronics");
phones[1].setunitPrice(199.99);
phones[1].setunitsInStock(650);
phones[2] = new MobilePhone();
phones[2].setproductNumber(3);
phones[2].setname("Nokia");
phones[2].setdepartment("Electronics");
phones[2].setunitPrice(200.25);
phones[2].setunitsInStock(125);
phones[3] = new MobilePhone();
phones[3].setproductNumber(4);
phones[3].setname("LG");
phones[3].setdepartment("Electronics");
phones[3].setunitPrice(100.05);
phones[3].setunitsInStock(200);
phones[4] = new MobilePhone();
phones[4].setproductNumber(5);
phones[4].setname("IPhone");
phones[4].setdepartment("Electronics");
phones[4].setunitPrice(299.99);
phones[4].setunitsInStock(150);
System.out.println("Order of inventory before sorting:");
System.out.println(Arrays.toString(phones));
Arrays.sort(phones, new Comparator<MobilePhone>() {
#Override
public int compare(MobilePhone mp1, MobilePhone mp2) {
return mp1.getname().compareTo(mp2.getname());
}
});
System.out.println("Order of inventory after sorting by name:");
System.out.println(Arrays.toString(phones));
}
}
class MobilePhone {
private double productNumber; // Variables
private String name;
private String department;
private double unitsInStock;
private double unitPrice;
public MobilePhone() {
this(0.0, "", "", 0.0, 0.0);
}
public MobilePhone(double productNumber, String name, String department,
double unitsInStock, double unitPrice) { // assign variables
this.productNumber = productNumber;
this.name = name;
this.department = department;
this.unitsInStock = unitsInStock;
this.unitPrice = unitPrice;
}
public double getproductNumber() { // retrieve values
return productNumber;
}
public String getname() {
return name;
}
public String getdepartment() {
return department;
}
public double getunitPrice() {
return unitPrice;
}
public double getunitsInStock() {
return unitsInStock;
}
public void setproductNumber(double productNumber) {
this.productNumber = productNumber;
}
public void setname(String name) {
this.name = name;
}
public void setdepartment(String department) {
this.department = department;
}
public void setunitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
public void setunitsInStock(double unitsInStock) {
this.unitsInStock = unitsInStock;
}
public double gettotalInv() {
return getunitPrice() * getunitsInStock();
}
#Override
public String toString() {
return "MobilePhone [productNumber=" + productNumber + ", name=" + name
+ ", department=" + department + ", unitsInStock="
+ unitsInStock + ", unitPrice=" + unitPrice + "]";
}
}
1 - To print content of MobilePhone class: Override default toString method like this:
#Override
public String toString() {
return "MobilePhone [productNumber=" + productNumber +
", name=" + name + ']'; // add more info if needed
}
2 - To allow sorting by name: Have MobilePhone class implement Comparable interface like
this:
class MobilePhone implements Comparable {
...
#Override
public int compareTo(Object o) {
MobilePhone m = (MobilePhone) o;
return (this.name.compareTo(o.name));
}
}
EDIT: To print your array of MobilePhone object you can do:
System.out.printf("Phones: %s%n", Arrays.toString(phones));