Implements Comparable Missing One trait - java

So I'm working on a very basic code which implements Comparable comparing a painting based on year, artist and title.
However my code isn't comparing the paintings by title, just year and artist.
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Painting p1 = new Painting(Year.NINETYEIGHT, artist.ART1, title.TIT1);
Painting p2 = new Painting(Year.NINETYEIGHT, artist.ART1, title.TIT2);
System.out.println("p1: " + p1.toString());
System.out.println("p2: " + p2.toString());
if(p1.compareTo(p2)> 0){
System.out.println(p1.toString() + " beats " + p2.toString());
} else if(p1.compareTo(p2) < 0){
System.out.println(p2.toString() + " beats " + p1.toString());
} else{
System.out.println("Same Everything");
}
}
}
public enum Year {
NINETYSEVEN, NINETYEIGHT, NINETYNINE, TWOTHOUSAND
}
public enum artist {
ART1, ART2, ART3,
}
public enum title {
TIT1, TIT2,TIT3,
}
public class Painting implements Comparable {
private title title;
private Year year;
private artist artist;
public Painting(Year y, artist a, title t) {
title = t;
year = y;
artist = a;
}
#Override
public int compareTo(Object o) {
//compare values
Painting other = (Painting) o;
int yearCompare = this.year.compareTo(other.year);
int artistCompare = this.artist.compareTo(other.artist);
if (yearCompare == 0) {
//same year, compare artist
return this.artist.compareTo(other.artist);
} else if (artistCompare == 0) {
return this.title.compareTo(other.title);
} else {
return yearCompare;
}
}
#Override
public String toString() {
return title.name() + " by " + artist.name() + " produced " + year.name();
}
}

Dang. Slow by just a few seconds. Haha. I came up with the same solution as shmosel.
public int compareTo(Painting other) {
int yearCompare = year.compareTo(other.year);
if (yearCompare != 0)
return yearCompare;
int artistCompare = artist.compareTo(other.artist);
if (artistCompare != 0)
return artistCompare;
return title.compareTo(other.title);
}
One difference. I would consider changing your class header. Specifically, I would change:
public class Painting implements Comparable
to:
public class Painting implements Comparable<Painting>
This way, instead of using the "raw" Object type, you're Painting class's compareTo() method signature will become:
public int compareTo(Painting o)
In other words, you don't have to cast or worry about checking if an argument is an instance of Painting!

Your if-else logic is flawed in several ways. It should more look like this:
int yearCompare = this.year.compareTo(other.year);
if (yearCompare != 0) {
return yearCompare;
}
int artistCompare = this.artist.compareTo(other.artist);
if (artistCompare != 0) {
return artistCompare;
}
return this.title.compareTo(other.title);
On a side note, you should generics and avoid casting:
public class Painting implements Comparable<Painting> {
#Override
public int compareTo(Painting other) {
// no casting necessary
}
}

Related

How to merge two alike items within the ArrayList?

So, I have 1 superclass DessertItem. Which has 4 subclasses Candy, Cookie, Ice Cream, Sundae. The Sundae class extends the Ice Cream class. Superclass is an abstract class. I also have a separate class which does not belong to the superclass, but in the same package - Order. There is another class - DessertShop, where the main is located.
Candy, Cookie classes implement SameItem<> generic class. The generic interface SameItem<> class looks like this:
public interface SameItem<T> {
public boolean isSameAs(T other);
}
The Candy, Cookie classes have this method:
#Override
public boolean isSameAs(Candy other) {
if(this.getName() == other.getName() && this.getPricePerPound() == other.getPricePerPound()) {
return true;
}
else {
return false;
}
}
And something similar, but for the cookie class.
All the subclasses have these methods :
default constructor,
public Cookie(String n, int q, double p) {
super(n);
super.setPackaging("Box");
cookieQty = q;
pricePerDozen = p;
}
public int getCookieQty() {
return cookieQty;
}
public double getPricePerDozen() {
return pricePerDozen;
}
public void setCookieQty(int q) {
cookieQty = q;
}
public void setToppingPricePricePerDozen(double p) {
pricePerDozen = p;
}
#Override
public double calculateCost() {
double cookieCost = cookieQty * (pricePerDozen/12);
return cookieCost;
}
and toString() method
So, what my program does is gets the input from the User, asks the name of the dessert, asks the quantity, or the quantity according to the dessert, ask the unit price. Asks the payment method. And then prints the receipt. This how the Order class looks like:
import java.util.ArrayList;
import java.util.List;
public class Order extends implements Payable{
//attributes
PayType payMethod;
private ArrayList<DessertItem> OrderArray;
//Constructor
public Order() {
OrderArray = new ArrayList<>();
payMethod = PayType.CASH;
}
//methods
public ArrayList<DessertItem> getOrderList(){
return OrderArray;
}// end of getOrderList
public ArrayList<DessertItem> Add(DessertItem addDesert){
enter code here
OrderArray.add(addDesert);
/* for(DessertItem i : getOrderList()) {
if(i instanceof Candy) {
for(DessertItem j : getOrderList()) {
if(j instanceof Candy) {
if(((Candy) i).isSameAs((Candy) j)) {
*/
//this is what I have tried so far, but I am lost
}
}
}
} else if(i instanceof Cookie) {
for (DessertItem j : getOrderList()) {
if(((Cookie) i).isSameAs((Cookie)j)) {
OrderArray.add(j);
} else {
OrderArray.add(i);
}
}
}
}
return OrderArray;
}// end of Add
public int itemCount(){
int counted = OrderArray.size();
return counted;
}//end of itemCount
public double orderCost() {
double orderResult = 0;
for(int i=0; i<OrderArray.size(); i++) {
orderResult = orderResult + OrderArray.get(i).calculateCost();
}
return orderResult;
}
public double orderTax() {
double taxResult = 0;
for(int i = 0; i<OrderArray.size(); i++) {
taxResult = taxResult + OrderArray.get(i).calculateTax();
}
return taxResult;
}
public double orderTotal() {
double ordertotal = orderTax() + orderCost();
return ordertotal;
}
#Override
public PayType getType() {
// TODO Auto-generated method stub
return payMethod;
}
#Override
public void setPayType(PayType p) {
payMethod = p;
}
public String toString() {
String finalOutput = "";
finalOutput += "------------------------Receipt--------------------------\n";
for(int i = 0; i < OrderArray.size(); i++) {
finalOutput = finalOutput + OrderArray.get(i).toString();
}
finalOutput += "--------------------------------------------------\n";
String line2 = "Total Number of items in order: " + itemCount() + "\n";
String line3 = String.format("Order Subtotals:\t\t\t\t $%-6.2f", orderCost());
String line4 = String.format("[Tax: $%.2f]\n", orderTax());
String line5 = String.format("\nOrder Total:\t\t\t\t\t $%-6.2f\n", orderTotal());
String outputVar = String.format("%s\n%s%s%17s", line2, line3, line4, line5);
String ending = "----------------------------------------------------";
String payType = String.format("\nPaid for with: %s", payMethod.name());
return finalOutput + outputVar + ending + payType;
}
So, my question is, how can I combine like items into one item?

Java inheritance - subclass method override

I am struggling with an inheritance task in Java
I was given an Animal.java class. My homework is to create a subclass called Lion.java. One of the tasks I'm struggling with within the entire task is outputting the type of Lion it is based on the weight of the lion. This is the code for the Animal.java
public class Animal {
private int numTeeth = 0;
private boolean spots = false;
private int weight = 0;
public Animal(int numTeeth, boolean spots, int weight){
this.setNumTeeth(numTeeth);
this.setSpots(spots);
this.setWeight(weight);
}
public int getNumTeeth(){
return numTeeth;
}
public void setNumTeeth(int numTeeth) {
this.numTeeth = numTeeth;
}
public boolean getSpots() {
return spots;
}
public void setSpots(boolean spots) {
this.spots = spots;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public static void main(String[] args){
Lion lion = new Lion(30, false, 80);
System.out.println(lion);
}
}
This is my code for the Lion.java class so far:
public class Lion extends Animal {
String type = "";
public Lion(int numTeeth, boolean spots, int weight) {
super(numTeeth, spots, weight);
}
public String type(int weight){
super.setWeight(weight);
if(weight <= 80){
type = "Cub";
}
else if(weight <= 120){
type = "Female";
}
else{
type = "Male";
}
return type;
}
#Override
public String toString() {
String output = "Number of Teeth: " + getNumTeeth();
output += "\nDoes it have spots?: " + getSpots();
output += "\nHow much does it weigh: " + getWeight();
output += "\nType of Lion: " + type;
return output;
The problem is the output does not return the type based on the if statement above. It's probably a very simple solution but I can't seem to figure it out.
In toString method, instead of type replace with type() method.
#Override
public String toString() {
String output = "Number of Teeth: " + getNumTeeth();
output += "\nDoes it have spots?: " + getSpots();
output += "\nHow much does it weigh: " + getWeight();
output += "\nType of Lion: " + type(getWeight());
return output;
Take a good look at your Lion constructor
public Lion(int numTeeth, boolean spots, int weight) {
super(numTeeth, spots, weight);
}
This doesn't do anything for the type (your public type method).
In order to set the private type class variable you need to either call the type method in the constructor or after the object has been created but before you call the toString method. For example
public Lion(int numTeeth, boolean spots, int weight) {
super(numTeeth, spots, weight);
type(weight);
}
Note that, as pointed out in the comments, you probably would be better off handling the type directly in the setWeight method. You can do something like
#Override
public void setWeight(int weight) {
super.setWeight(weight);
type(weight);
}
and leave the constructor alone.
Taking it one step further, you could refactor your code such that the type method has no parameter (you've already set the weight member).

Refactoring code to be Generics and functional interface

I have two interfaces one can be used to find some statistics by Key and Value and the other is used to visit an object and iterate over it, the first one has the following methods:
public interface Statistic {
public String getKey();
public Object getValue();
public String getDetails();
}
And here is the implementation for it:
public class Collector implements Statistic {
private String key;
private int val;
public Collector(String key, int val) {
this.key = key;
this.val = val;
}
public void setValue(int val) {
this.val = val;
}
#Override
public String getKey() {
return key;
}
#Override
public Integer getValue() {
return val;
}
#Override
public String getDetails() {
return null;
}
}
And the other one has the following:
public interface StatisticsCollector<T extends Object, S extends Statistic> {
public String getName();
public void visit(T object);
public Iterator<S> calculatedStatistics();
}
And here is the implementation for it:
public class CalculateFromObject<K, V> implements StatisticsCollector<Object, Collector> {
EmployeeValidator empValidator = new EmployeeValidator();
StringValidator strValidator = new StringValidator();
#Override
public String getName() {
return null;
}
#Override
public void visit(Object object) {
if (object instanceof String) {
String str = object.toString();
int upperCaseCount = strValidator.upperCaseFreq(str);
strValidator.set.add(new Collector("Upper Case Letters: ", upperCaseCount));
int lowerCaseCount = strValidator.lowerCaseFreq(str);
strValidator.set.add(new Collector("Lower Case Letters: ", lowerCaseCount));
int digitsCount = strValidator.digitFreq(str);
strValidator.set.add(new Collector("Digits Count: ", digitsCount));
int wordCount = strValidator.wordFreq(str);
strValidator.set.add(new Collector("Words Count: ", wordCount));
int nonWordCount = strValidator.nonWordFreq(str);
strValidator.set.add(new Collector("Non Word Count: ", nonWordCount));
} else if (object instanceof Employee) {
Employee emp = (Employee) object;
empValidator.salaryValidator(emp);
empValidator.birthDateValidator(emp);
empValidator.birthPlaceValidator(emp);
empValidator.resignationDateValidator(emp);
empValidator.positionValidator(emp);
}
}
#Override
public Iterator<Collector> calculatedStatistics() {
return empValidator.set.iterator();
}
}
And in my package I have a bean for Employee which has few properties like firstName, lastName, salary and position with their setters and getters.
I would like to do some validations like get me the number of employees which has a salary of x and been born in 1990 and did the following class for these validations:
public class EmployeeValidator {
public Set<Collector> set = new HashSet<>();
public void salaryValidator(Employee emp) {
int count = 0;
// each collector consist of a condition (function), key, value (always incremented)
if (emp.getSalary() < 350) {
set.add(new Collector("Employee with salaries less than 350JD: ", ++count));
} else if (emp.getSalary() >= 350 && emp.getSalary() < 600) {
set.add(new Collector("Employee with salaries between 350JD And 600JD: ", ++count));
} else if (emp.getSalary() >= 600 && emp.getSalary() < 1200) {
set.add(new Collector("Employee with salaries between 600JD And 1200JD ", ++count));
} else if (emp.getSalary() >= 1200) {
set.add(new Collector("Employee with salaries more than 1200JD: ", ++count));
}
}
public void birthDateValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that where born in " + emp.getBirthDate().getYear() + " = ").equals(stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that where born in " + emp.getBirthDate().getYear() + " = ", 1));
}
public void birthPlaceValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that where born in " + emp.getBirthPlace() + " = ").equals(stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that where born in " + emp.getBirthPlace() + " = ", 1));
}
public void resignationDateValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that where Resignation in " + emp.getResignationDate().getYear() + " = ").equals(
stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that where Resignation in " + emp.getResignationDate().getYear() + " = ", 1));
}
public void positionValidator(Employee emp) {
for (Collector stats : set) {
if (("Employees that occupy the " + emp.getPosition() + " position = ").equals(stats.getKey())) {
count(stats);
return;
}
}
set.add(new Collector("Employees that occupy the " + emp.getPosition() + " position = ", 1));
}
private void count(Collector stats) {
int counter = stats.getValue() + 1;
stats.setValue(counter);
}
}
And I have another class to validate strings and see how many uppercase letters a string has, how many lower case it has...etc
As you can see in the visit method in the CalculateFromObject class im calling all my methods to do the validations, everything is working fine and I am getting the expected results, but my code is not very efficient as I would like to make it generic and make it accept any type of object, I have done few tries but im stuck.
I have tried to write a functional interface called Conditions that has one method that I can pass a condition and check it like the following:
public interface Conditions {
boolean checkCondition(Object obj);
}
So can someone suggest what is the best way to change my code to be generic and accept any type of objects like Student for example and to be as clean as possible maybe by applying a design pattern?
There's a lot of overhead in your classes and misunderstanding of interfaces against POJO's (simple classes). On a high level you should do the following:
1). Remove interface Statistic and class Collectors. They are just incapsulating data. Instead - create a POJO Employee with necessary fields + getters + setters. Don't use 'key-value`, give those fields meaningful names:
public class Employee
{
private String name;
private int id;
private double salary;
...
public String getName() {...}
public void setName(..) {...}
// other getters / setters
}
Create constructor if needed
2) Looks like your Employee class is also redundant, remove it. Use new Employee instead
3) Use Collections framework to store collections of your employee's instances.
`List<Employee> employees = new ArrayList<>();
employees.add(new Employee(.... )); `
4). Create interface EmployeeValidator with validating methods and implement it:
public interface EmployeeValidator {
void validate(List<Employee> employees);
}
5) If you want to operate some statistics data, create a separate Statistics class which will operate on collections of employees, e.g.
public class Statistics {
public double getAvgSalary(List<Employee> employees)
{
double avgSalary = 0;
for (Employee e : employees) {
....
}
}
}

What is the correct way to do this?

I know this must be a fundamental design problem because I clearly can't do this. I want to call the ownGrokk, ownTyce, etc methods from another class depending on the value of the integer assigned to OwnedSpirits(int). This in turn fills arrays.
The problem is, I do this multiple times, and doing it from another class it seems like I have to make a new object every time to pass the new int argument, and doing so resets the value of spiritInstance. And, since that resets to zero, the arrays don't fill properly. I try to print out my array values later and I get an "ArrayIndexOutOfBoundsException".
public class OwnedSpirits {
private int spiritTypeInt = 0;
public static int spiritInstance=0;
public static int[] spiritarray = new int[9];
public static String[] spiritName = new String[9];
public static int[] party = new int[3];
public OwnedSpirits(int spiritcall){
if(spiritcall == 1){
ownGrokk();
}
if(spiritcall == 2){
ownRisp();
}
if(spiritcall == 3){
ownTyce();
}
if(spiritcall == 4){
ownDaem();
}
if(spiritcall == 5){
ownCeleste();
}
}
private void ownGrokk(){
spiritName[spiritInstance] = "Grokk";
spiritInstance++;
}
private void ownRisp(){
spiritName[spiritInstance] = "Risp";
spiritInstance++;
}
private void ownDaem(){
spiritName[spiritInstance] = "Daem";
spiritInstance++;
}
private void ownCeleste(){
spiritName[spiritInstance] = "Celeste";
spiritInstance++;
}
private void ownTyce(){
spiritName[spiritInstance] = "Tyce";
spiritInstance++;
}
and this code is in another class, where it attempts to call the methods to fill the array
buttonConfirm.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
if(xcounter==3){
for(x=0; x<3; x++){
if(setdaemtrue == true){
new OwnedSpirits(4);
}
if(setrisptrue == true){
new OwnedSpirits(2);
}
if(setcelestetrue == true){
new OwnedSpirits(5);
}
if(settycetrue == true){
new OwnedSpirits(3);
}
if(setgrokktrue == true){
new OwnedSpirits(1);
}
}
}
}
});
and finally in yet another class:
System.arraycopy(OwnedSpirits.spiritName, 0, partylist, 0, 3);
#Override
public void show() {
System.out.println(partylist[0]);
System.out.println(partylist[1]);
System.out.println(partylist[2]);
spiritlist.setItems(partylist);
table.add(spiritlist);
table.setFillParent(true);
stage.addActor(table);
}
If the last part is confusing, it's because I am using libgdx. the print statements are there just to try to figure out why my list was having an error
I can show you what I would do to handle Spirits, and Parties.
The Spirit class, contains name and current party its assigned to:
package com.stackoverflow.spirit;
public class Spirit {
private String name;
private Party party;
private SpiritType type;
private static int id = 0;
public static enum SpiritType {
Grokk, Risp, Tyce, Daem, Celeste
};
public Spirit(String name, SpiritType type) {
create(name, type);
}
public Spirit(SpiritType type) {
create(null, type);
}
// This is to handle Java inexistance of default parameter values.
private void create(String name, SpiritType type)
{
Spirit.id++;
this.name = (name == null) ? (type.name() + " " + id) : name;
this.type = type;
}
public String getName() {
return name;
}
public Party getParty() {
return party;
}
public SpiritType getType() {
return type;
}
/**
* Used internally by #see Party
* #param party the party this Spirit belongs
*/
public void setParty(Party party) {
this.party = party;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString()
{
return this.name;
}
}
Finally the Party class, contains a set of Spirits, you can add and remove Spirits from the party.
package com.stackoverflow.spirit;
import java.util.HashSet;
public class Party {
private HashSet<Spirit> spirits = new HashSet<Spirit>();
private static int id = 0;
private String name = "Party " + Party.id++;;
public Party() {
}
public Party(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void add(Spirit spirit) {
if (!spirits.contains(spirit)) {
spirits.add(spirit);
if (spirit.getParty() != null) {
//Remove from previous party to update the other party set
spirit.getParty().remove(spirit);
}
spirit.setParty(this);
} else {
// throw new SpiritAlreadyOnParty();
}
}
public void remove(Spirit spirit)
{
if (spirits.contains(spirit))
{
spirit.setParty(null); // You could create a default empty party for "Nature/Neutral" Spirits perhaps :)
spirits.remove(spirit);
}
else {
//throw new SpiritNotInParty();
}
}
public boolean isOnParty(Spirit spirit) {
return spirits.contains(spirit);
}
public ArrayList<Spirit> getSpirits()
{
return new ArrayList<Spirit>(spirits);
}
public int getPartySize() {
return spirits.size();
}
public String getPartyInfo()
{
StringBuilder builder = new StringBuilder();
builder.append("Party:" + this.name + " Size:" + this.spirits.size() + "\n");
for (Spirit s : spirits)
{
builder.append(s.getName() + "\n");
}
return builder.toString();
}
#Override
public String toString()
{
return this.name;
}
}
Here I use the Spirit and Party classes, you could add more functionality, like properties for party strength, magic buffs on the party, etc:
package com.stackoverflow.spirit;
import com.stackoverflow.spirit.Spirit.SpiritType;
public class Main {
public static void main(String[] args) throws java.lang.Exception {
Party griffindor = new Party("Griffindor"), slytherin = new Party(
"Slytherin");
// You can also do for (SpiritType type : SpiritType.values() then
// type.ordinal()
for (int i = 0; i < SpiritType.values().length; i++) {
griffindor.add(new Spirit(SpiritType.values()[i]));
slytherin.add(new Spirit(SpiritType.values()[i]));
}
Spirit mySpirit = new Spirit("NotAHPFan", SpiritType.Celeste);
slytherin.add(mySpirit);
System.out.println("Name of party:" + mySpirit.getParty().getName());
System.out.println("Is on griffindor?:"
+ griffindor.isOnParty(mySpirit));
// What now?
griffindor.add(mySpirit);
System.out.println("Is " + mySpirit.getName() + " on "
+ slytherin.getName() + "?:" + slytherin.isOnParty(mySpirit));
System.out.println(mySpirit.getName() + " is now on "
+ mySpirit.getParty() + "\n");
System.out.println(griffindor.getPartyInfo());
System.out.println(slytherin.getPartyInfo());
}
}
P.D: I'm not a HP fan.

How to print out the contents of a HashMap in a certain format?

I'm not entirely sure how I would do this, here is my code:
public class PizzaMenu
{
static Map<String,Pizza> namedPizzas= new HashMap<String,Pizza>();
public static void main(String[] args)
{
}
public static void addItem(String name, Pizza pizza)
{
namedPizzas.put(name, pizza);
}
public String printMenu()
{
/*
String menuString="";
for (Every menu item)
{
//Add name of menu item to menuString with carriage return
//Add details of menu item (pizza.getInfo();) to menuString
}
*/
//return menuString
}
}
I would then call System.out.println(PizzaMenu.printMenu()) in another class. The sort of format I'm hoping to achieve is as follows:
/*
* PizzaName
* Details
*
* Next PizzaName in menu
* Details
*
* Next PizzaName in menu
* Details
*
*
*
*/
Am I maybe using the wrong data structure for this type of operation or is there a way of achieving this?
Here is the structure of the Pizza class (apologies for poor formatting):
public class Pizza
{
private double cost;
private Boolean veg;
private PizzaBase base;
private List<PizzaTopping> toppings = new ArrayList<PizzaTopping>();
public Pizza(PizzaBase base, PizzaTopping topping) //Constructor for pizza with 1 topping
{
setBase (base);
toppings.add(topping);
}
public Pizza(PizzaBase base, PizzaTopping topping, PizzaTopping topping2) //Constructor for pizza with 2 toppings
{
setBase (base);
toppings.add(topping);
toppings.add(topping2);
}
public Pizza(PizzaBase base, PizzaTopping topping, PizzaTopping topping2, PizzaTopping topping3) //Constructor for pizza with 3 toppings
{
setBase (base);
toppings.add(topping);
toppings.add(topping2);
toppings.add(topping3);
}
public double getCost()
{
return cost;
}
public void setCost(double cost)
{
this.cost = cost;
}
public PizzaBase getBase()
{
return base;
}
public void setBase(PizzaBase base)
{
this.base = base;
}
public List<PizzaTopping> getToppings()
{
return this.toppings;
}
public String getToppingsInfo()
{
String toppingInfo = "\n";
PizzaTopping t;
for (int i = 0; i<getToppings().size();i++)
{
t = toppings.get(i);
toppingInfo=toppingInfo+t.getInfo();
}
return toppingInfo;
}
public Boolean getVeg()
{
return veg;
}
public void setVeg(Boolean veg)
{
this.veg = veg;
}
public double calculateCost()
{
PizzaTopping p;
//Loop through all ingredients and add their costs to total cost
for (int i = 0; i<toppings.size();i++)
{
p = toppings.get(i);
cost+=p.getCost();
}
cost+=base.getCost(); //Add pizza base cost to total cost
return cost;
}
//Check if pizza is vegetarian depending upon its ingredients
public Boolean isVeg()
{
Boolean toppingCheck =true;
Boolean baseCheck = true;
PizzaTopping t; //Temporary value used to stored toppings being compared in for loop
//Check each topping and check if it's suitable for vegetarians
for (int i =0; i<toppings.size();i++)
{
while (toppingCheck == true)
{
t = toppings.get(i);
if (t.getVeg()==false)
{
toppingCheck = false;
}
}
}
//Check base to see if it's suitable for vegetarians
if (getBase().getVeg()==false)
{
baseCheck = false;
}
//Return value depending on if all ingredients are suitable for vegetarians
if (toppingCheck == true && baseCheck == true)
{
return true;
}
else return false;
}
public String getInfo()
{
String vegInfo;
if (this.isVeg()==true)
{
vegInfo = "Yes";
}
else vegInfo ="No";
return String.format("Toppings:%s\n"+"Base:\n%s"+"\nTotal Cost:\t£%.2f"+"\nSuitable for vegetarians: %s", getToppingsInfo(), getBase().getInfo(), calculateCost(), vegInfo);
//Return list of toppings, Total Price, vegetarian
}
}
Try this:
String menuString="";
for (Map.Entry<String, Pizza> pizzaItem : namedPizzas.entrySet()) {
menuString += pizzaItem.getKey() + "\n";
menuString += "\t" + pizzaItem.getValue().getInfo() + "\n\n";
}
public String printMenu()
{
String s ="";
for (String key: namedPizzas.keySet()){
s+= pizzaItem.getKey() + "\n";
s+= "\t" + pizzaItem.getValue().getInfo() + "\n\n";
}
return menuString
}
To address your question directly:
You need a set of keys. With a set of keys you can also get values. HashMap#keySet should work for this. You can loop through a set using a for each loop.
Then as you said, you need to build your string and return. Putting it together gives you:
public String printMenu()
{
String menuString = "";
for(String key : namedPizzas.keySet())
{
menuString += key + "\n" +
"\t" + namedPizzas.get(key).getInfo() + "\n\n";
}
return menuString;
}
I would also like to suggest a design improvement. You should be overriding the Object#toString method for things like this. The toString method will get automatically called when you try to print the object. This allows you to do: System.out.println(myPizzaMenu); instead of System.out.println(myPizzaMenu.printMenu());
The name printMenu is also misleading, so for that reason it's also bad.
Unfortunately, after switching the map to a list, it still didn't work. An hour later I found the bug causing it all! Thanks for everyone's answers, I will keep these methods in mind when I need to use maps again.
EDIT: Here is the new class structure for reference:
public class PizzaMenu
{
static List<Pizza> namedPizzas = new ArrayList<Pizza>();
public static void main(String[] args)
{
}
public static void addItem(String name, Pizza pizza)
{
pizza.setName(name.toLowerCase());
namedPizzas.add(pizza);
}
public static String printMenu()
{
String menuString="";
Pizza p;
//Collect all pizzas and add their information to string
for (int i =0; i<namedPizzas.size(); i++)
{
p = namedPizzas.get(i);
menuString+=p.getName().toUpperCase()+"\n"+p.getInfo()+"\n\n";
p.resetCost();
}
return menuString;
}
}

Categories

Resources