Hey so I will do my best at explaining this (and will have to change some code sorry if it looks weird) so I currently have:
public Job(String name, int tickets, double wage) {
this.name = name;
this.tickets = tickets;
this.wage = wage;
& and getters and setters for these and also making a list here:
Job Peter = new Job (name: "Peter", tickets: 100, wage: 1.55);
System.out.println(Peter);
So my issue is that lets say the total wage is calculated by tickets * wage how do I go about doing this by automation.
I can do this, however want a simpler method where it is automated so I can just for example Peter.getTotalWage
System.out.println(Peter.getTickets() * (Peter.getWage()));
My issue is when it comes to multiplying int with double, I've tried something like this but can't seem to get it working as I know it is wrong (probably completely wrong to be honest):
}
public double totalWage(int tickets, double wage) {
int i = tickets;
Double d2=Double.valueOf(i);
double sum = d2 * wage;
return sum;
}
Right now I have two classes.
If you can help us identify how to go about doing this that'll be great!
tl;dr
Use BigDecimal for money.
Organize your classes properly. Apparently you have:
An employee with a wage rate
A job whose cost is the number of tickets multiplied by the assigned employee's wage rate.
So you need an Employee class with a member variable for wage rate. And you need a Job class with an assigned Employee object, and a getWageCost method with this logic:
BigDecimal cost =
this.employee // An `Employee` object is assigned to this `Job` object.
.getWageRate() // The `Job` object asks the `Employee` object for its current wage rate.
.multiply(
new BigDecimal( this.countOfTickets )
)
.setScale( 2 , RoundingMode.HALF_EVEN ) // Round to the penny using Banker’s Rounding.
;
Tip to students: Notice how working towards a simple clear problem description written down in plain English can lead naturally to a proper class design. Lesson learned: Prose before code.
BigDecimal
For money, never use double or Double, float or Float. The floating-point types trade away accuracy for speed of execution. Use BigDecimal for fractional money.
BigDecimal wageRate = new BigDecimal( "1.55" ) ;
Multiply.
BigDecimal cost = this.employee.getWageRate().multiply( new BigDecimal( this.countOfTickets ) ) ;
But that line above fails to address the fractional penny (assuming this is United States dollars). So round to the penny or to the tenth or hundredth of a penny as directed by your accounting staff.
Round by calling the setScale method. Use the rounding method as directed by your accounting staff. Often in business matters that would be Banker's Rounding. So to the line above we should add a call to setScale with the number of digits (2 for whole pennies of US Dollar) and the typing of rounding.
BigDecimal cost = this.employee.getWageRate().multiply( new BigDecimal( this.countOfTickets ) ).setScale( 2 , RoundingMode.HALF_EVEN ) ;
The code above is logic on the Job class. Notice how it reaches into the Employee object to obtain the current wage rate for that worker.
Example code
Here is complete example code.
Employee alice = new Employee( "Alice" , "EMP00013" , new BigDecimal( "1.55" ) );
Job whateverJob = new Job( alice , 100 , "whatever" , UUID.randomUUID() );
BigDecimal wagesCostForWhateverJob = whateverJob.getWageCost();
System.out.println( "whateverJob: " + whateverJob + " costs " + wagesCostForWhateverJob );
whateverJob: Job{ employee=Employee{ name='Alice' | employeeId='EMP00013' | wageRate=1.55 } | countOfTickets=100 | description='whatever' | id=b4e397b3-e02e-42be-b117-622cee96a192 } costs 155.00
Employee.java
package work.basil.example;
import java.math.BigDecimal;
import java.util.Objects;
public class Employee
{
// ---------| Member vars |----------------------------------
private String name, employeeId;
private BigDecimal wageRate;
// ---------| Constructors |----------------------------------
public Employee ( String name , String employeeId , BigDecimal wageRate )
{
this.name = Objects.requireNonNull( name );
this.employeeId = Objects.requireNonNull( employeeId );
this.wageRate = Objects.requireNonNull( wageRate );
}
// ---------| Accessors |----------------------------------
public String getName ( )
{
return name;
}
public String getEmployeeId ( )
{
return employeeId;
}
public BigDecimal getWageRate ( )
{
return wageRate;
}
// ---------| Object |----------------------------------
#Override
public boolean equals ( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
Employee employee = ( Employee ) o;
return getEmployeeId().equals( employee.getEmployeeId() );
}
#Override
public int hashCode ( )
{
return Objects.hash( getEmployeeId() );
}
#Override
public String toString ( )
{
return "Employee{ " +
"name='" + name + '\'' +
" | employeeId='" + employeeId + '\'' +
" | wageRate=" + wageRate +
" }";
}
}
Job.java
package work.basil.example;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
import java.util.UUID;
public class Job
{
// ---------| Member vars |----------------------------------
private Employee employee;
private Integer countOfTickets;
private String description;
private UUID id;
// ---------| Constructors |----------------------------------
public Job ( Employee employee , Integer countOfTickets , String description , UUID id )
{
this.employee = employee;
this.countOfTickets = countOfTickets;
this.description = description;
this.id = id;
}
// ---------| Accessors |----------------------------------
public Employee getEmployee ( )
{
return employee;
}
public Integer getCountOfTickets ( )
{
return countOfTickets;
}
public String getDescription ( )
{
return description;
}
public UUID getId ( )
{
return id;
}
public BigDecimal getWageCost ( )
{
BigDecimal cost = this.employee.getWageRate().multiply( new BigDecimal( this.countOfTickets ) ).setScale( 2 , RoundingMode.HALF_EVEN );
return cost;
}
// ---------| Object |----------------------------------
#Override
public boolean equals ( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
Job job = ( Job ) o;
return getId().equals( job.getId() );
}
#Override
public int hashCode ( )
{
return Objects.hash( getId() );
}
#Override
public String toString ( )
{
return "Job{ " +
"employee=" + employee +
" | countOfTickets=" + countOfTickets +
" | description='" + description + '\'' +
" | id=" + id +
" }";
}
}
In real work, if Job::getWageCost would be called very very often, we might consider caching the result. We could add a member variable to hold the result. But avoid falling into the trap of premature optimization.
I played around with the code a bit; maybe this helps?
public class Main {
public static void main(String[] args){
Job jobOne = new Job (100, 1.55);
Person p1 = new Person("Peter Williams");
double jobOnePay = jobOne.getTotal();
p1.setWage(jobOnePay);
System.out.println(p1.getName() + " gets paid: " + p1.getSetWage());
}
}
class Job{
private int tickets;
private double wage;
Job(int tickets, double wage) {
this.tickets = tickets;
this.wage = wage;
}
double getTotal(){
return tickets*wage;
}
}
class Person{
private String name;
private double setWage;
Person(String name){
this.name = name;
}
String getName() {
return name;
}
void setWage(double setWage) {
this.setWage = setWage;
}
double getSetWage() {
return setWage;
}
}
Output: "Peter Williams gets paid: 155.0"
Related
Collectors.counting() returns long values for each key in this method:
private static Map<Integer, Long> countDuplicates(HashSet<Card> cards) {
return cards.stream().collect(Collectors.groupingBy(Card::getRankNumber, Collectors.counting()));
}
Is there a way to cast or convert the resulting Map from Map<Integer, Long> to Map<Integer, Integer>?
Direct casting gives this exception:
Type mismatch: cannot convert from Map<Integer,Integer> to Map<Integer,Long>
Note: The implementation of my class guarantees that cards has five objects in it, so there is no chance of overflow.
Try the following:
private static Map<Integer, Integer> countDuplicates(HashSet<Card> cards) {
return cards.stream()
.collect(Collectors.groupingBy(Card::getRankNumber, Collectors.summingInt(x -> 1)));
}
Instead of Collectors.counting() use Collectors.summingInt(x -> 1) so that you get immediately the value as an Integer.
Another way to get Map<Integer, Integer> is to use toMap collector along with Integer::sum method reference as a merge function:
private static Map<Integer, Integer> countDuplicates(HashSet<Card> cards) {
return cards.stream()
.collect(Collectors.toMap(Card::getRankNumber, x -> 1, Integer::sum));
}
Both the Answer by dreamcrash and the Answer by Alex Rudenko seem correct. Here is example code I wrote to try both approaches.
The Card class.
package work.basil.example;
import java.util.Objects;
public class Card
{
public enum Suit
{
CLUB, DIAMOND, HEART, SPADE
}
// -------------| Member fields |-----------------------
private Suit suit;
private String name;
private Integer rankNumber;
// -------------| Constructors |-----------------------
public Card ( Suit suit , String name , Integer rankNumber )
{
Objects.requireNonNull( suit );
Objects.requireNonNull( name );
Objects.requireNonNull( rankNumber );
this.suit = suit;
this.name = name;
this.rankNumber = rankNumber;
}
// -------------| Getters |-----------------------
public String getName ( ) { return this.name; }
public Integer getRankNumber ( ) { return this.rankNumber; }
// -------------| Object methods |-----------------------
#Override
public String toString ( )
{
return "Card{ " +
"suit=" + suit +
" | name='" + name + '\'' +
" | rankNumber=" + rankNumber +
" }";
}
#Override
public boolean equals ( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
Card card = ( Card ) o;
return suit == card.suit && getName().equals( card.getName() ) && getRankNumber().equals( card.getRankNumber() );
}
#Override
public int hashCode ( )
{
return Objects.hash( suit , getName() , getRankNumber() );
}
}
In Java 16 and later, we could reduce that Card class to a brief record. And in the code further down we would change getRankNumber to the implicit getter method rankNumber. The Suit enum would move to its own .java file.
package work.basil.example.cardgame;
public record Card( Suit suit , String name , Integer rankNumber )
{
}
The CastingStream class to collect those cards.
package work.basil.example;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class CastingStream
{
public static void main ( String[] args )
{
CastingStream app = new CastingStream();
app.demo();
}
private void demo ( )
{
Set < Card > cards = Set.of(
new Card( Card.Suit.HEART , "Ten" , 10 ) ,
new Card( Card.Suit.SPADE , "Ten" , 10 ) ,
new Card( Card.Suit.HEART , "Queen" , 12 )
);
// Code taken from Question. https://stackoverflow.com/q/65910153/642706
Map < Integer, Long > countDuplicatesLong =
cards
.stream()
.collect(
Collectors.groupingBy(
Card :: getRankNumber ,
Collectors.counting()
)
);
// Code taken from Answer by dreamcrash. https://stackoverflow.com/a/65910215/642706
Map < Integer, Integer > countDuplicatesIntegerBySummingInt =
cards
.stream()
.collect(
Collectors.groupingBy(
Card :: getRankNumber ,
Collectors.summingInt( x -> 1 )
)
);
// Code taken from Answer by Alex Rudenko. https://stackoverflow.com/a/65910400/642706
Map < Integer, Integer > countDuplicatesIntegerBySumMethodReference =
cards
.stream()
.collect(
Collectors.toMap( Card :: getRankNumber ,
x -> 1 ,
Integer :: sum
)
);
System.out.println( "cards = " + cards );
System.out.println( "countDuplicatesLong = " + countDuplicatesLong );
System.out.println( "countDuplicatesIntegerBySummingInt = " + countDuplicatesIntegerBySummingInt );
System.out.println( "countDuplicatesIntegerBySumMethodReference = " + countDuplicatesIntegerBySumMethodReference );
}
}
When run.
cards = [Card{ suit=HEART | name='Queen' | rankNumber=12 }, Card{ suit=HEART | name='Ten' | rankNumber=10 }, Card{ suit=SPADE | name='Ten' | rankNumber=10 }]
countDuplicatesLong = {10=2, 12=1}
countDuplicatesIntegerBySummingInt = {10=2, 12=1}
countDuplicatesIntegerBySumMethodReference = {10=2, 12=1}
I am tasked with creating 5 book objects and storing in an array, which I do no problem! I am able to print out the objects' variables using println no problem but when I want be able to move the variable around using printf I dont know how to call upon a specific variable of a certain element of the array. Please Help!
public class BookReport {
public static void main(String[] args){
Book[] TheBooks = new Book[5] ;
TheBooks[0] = new Book("Gone With The Wild", "Paul Mitchell", 1000) ;
TheBooks[1] = new Book("Harry Toilet", "Donald Trump", 100) ;
TheBooks[2] = new Book("Huckles Finn Berry", "SpiderMan", 500) ;
TheBooks[3] = new Book("The Bad Habbit", "Nose Picker", 700) ;
TheBooks[4] = new Book("Alien", "Mister Green", 600) ;
System.out.printf("%10s %20s %18s \n", "Book Title" , "Author", "Pages") ;
System.out.printf("%s \n", "----------------------------------------------------") ;
//This works but I cant justify the variables to align!!!
System.out.println(TheBooks[0]) ;
}
}
public class Book {
private String title = "" ;
private String author = "" ;
private int pages = 0 ;
public Book(String title, String author, int pages){
setTitle(title) ;
setAuthor(author) ;
setPages(pages) ;
}
public String getTitle(){
return title ;
}
public String getAuthor(){
return author ;
}
public int getPages(){
return pages ;
}
public void setTitle(String newTitle){
title = newTitle ;
}
public void setAuthor(String newAuthor){
author = newAuthor ;
}
public void setPages(int newPages){
pages = newPages ;
}
public String toString(){
return title + " " + author + " " + pages ;
}
public boolean equals(Book anotherBook){
return ((title.equals(anotherBook.title)) && (author.equals (anotherBook.author)) &&
(pages == anotherBook.pages)) ;
}
}
Just call the getters for the various fields you want to print:
System.out.printf("%10s %20s %18s \n", "Book Title" , "Author", "Pages");
System.out.printf("%s \n", "----------------------------------------------------") ;
for (Book b : TheBooks) {
System.out.printf("%10s %20s %18s \n", b.getTitle(), b.getAuthor(), b.getPages());
}
By the way, you named your array of books TheBooks, but it is Java convention to not name variables with capital letters as the first letter. So theBooks would work better here.
If you want to call specific variable of a certain element of the array.
you can use
java.util.Map
for example you can make Id for all object you want to store.
HashMap<String, Book> h = new HashMap<>();
Book book = new Book("Gone With The Wild", "Paul Mitchell", 1000);
h.put(book.getTitle(), book);
book = new Book("Harry Toilet", "Donald Trump", 100);
h.put(book.getTitle(), book);
book = new Book("Huckles Finn Berry", "SpiderMan", 500);
h.put(book.getTitle(), book);
book = new Book("The Bad Habbit", "Nose Picker", 700);
h.put(book.getTitle(), book);
book = new Book("Alien", "Mister Green", 600);
h.put(book.getTitle(), book);
// if you want to call it
Book b = h.get("exampletitle);
You should also be able to use String.format() in your toString method so that you have a reusable formatted version.
#Override
public String toString(){
return String.format("%10s %20s %18s \n", title, author, pages);
}
P.s. I think it would be good practice to include hashCode() for classes where you include an equals().
I'm trying to make a program in java that you can add people's birthdays, names, birthmonths, and birthyears. I'm having a hard time trying to come up with the code to remove an object from the arraylist here is the following code. How would I go about writing the removePerson method?
import java.util.ArrayList;
public class Analyzer {
// instance variables - replace the example below with your own
private final static int DAYS_PER_MONTH = 31;
private final static int MONTHS_PER_YEAR = 12;
private int[] birthDayStats;
private int[] birthMonthStats;
private ArrayList<Person> people;
/**
* Constructor for objects of class Analyzer
*/
public Analyzer() {
this.people = new ArrayList<Person>();
this.birthDayStats = new int[Analyzer.DAYS_PER_MONTH];
this.birthMonthStats = new int[Analyzer.MONTHS_PER_YEAR];
}
public void addPerson(String name, int birthDay, int birthMonth, int
birthYear) {
Person person = new Person(name, birthDay, birthMonth, birthYear);
if (person.getBirthDay() != -1 || person.getBirthMonth() != -1) {
people.add(person);
birthMonthStats[birthMonth - 1]++;
birthDayStats[birthDay - 1]++;
} else {
System.out.println("Your current Birthday is " + birthDay + " or "
+ birthMonth + " which is not a correct number 1-31 or 1-12 please " +
"put in a correct number ");
}
}
public void printPeople() { //prints all people in form: “ Name: Tom Month: 5 Day: 2 Year: 1965”
int index = 0;
while (index < people.size()) {
Person person = (Person) people.get(index);
System.out.println(person);
index++;
}
}
public void printMonthList() { //prints the number of people born in each month
// Sample output to the right with days being similar
int index = 0;
while (index < birthMonthStats.length) {
System.out.println("Month number " + (index + 1) + " has " +
birthMonthStats[index] + " people");
index++;
}
}
public Person removePerson(String name) {// removes the person from the arrayList
}
}
/**
* Removes the {#code Person} with the given {#code name} from the list
* #param name the {#code Person}'s name
* #return the {#code Person} removed from the list or {#code null} if not found
*/
public Person removePerson(String name) {
if (name != null) {
for (Iterator<Person> iter = people.iterator(); iter.hasNext(); ) {
Person person = iter.next();
if (name.equalsIgnoreCase(person.getName())) {
iter.remove();
return person;
}
}
}
return null;
}
See the java.util.Iterator#remove() method.
Tuesday learning bonus:
If you want to look for a name faster in your list, you should consider to use a java.util.Map implementation:
HashMap<String,Person> people;
You can add Person objects in a smart way in order to make your search case insensitive:
people.put(name.toLowerCase(), new Person(name, ...));
... and your removePerson method become:
public Person removePerson(String name) {
if (name != null)
name = name.toLowerCase();
return people.remove(name);
}
See the java.util.Map#remove() method.
If you are using Java 1.8. It's pretty simple way to do. This will remove Person having 'name' from your list.
people.removeIf(x -> name.equalsIgnoreCase(x.getName()));
I have this class
class TimeSpentStats{
int manId;
String sessionId;
int userId;
Long timeStamp;
}
I have a List and I want to get the minimum timestamp and maximum
from the list for each (manId, sessionId, userId)
So for example, I have:
manId sessionId userId timeStamp
1 01F 5 1000
1 01F 5 1005
3 6Y 3 7
3 6Y 3 16
I need for (1 01F 5) -> min = 1000 , max = 1005
and for (3 6Y 3 ) - > min = 7 , max = 16
I need to add maybe 2 attributes in the same class?
Any ideas if I can do this? Thank you
If you have a List of TimeSpentStatus called list, the following algorithm should do what you want it to do.
HashMap<String, Pair> statsList = new HashMap<String, Pair>();
for(TimeSpentStats stats : list){
// Constructs the combination of IDs that is used as the key to a Pair object
String statsStr = stats.manId + " " + stats.sessionId + " " + stats.userId;
if(statsList.containsKey(statsStr)){
// Update min and/or max time for the current combination as necessary
statsList.get(statsStr).minTime = Math.min(statsList.get(statsStr).minTime, stats.timeStamp);
statsList.get(statsStr).maxTime = Math.max(statsList.get(statsStr).maxTime, stats.timeStamp);
}else{
// Construct a new Pair for the ID combination and add max and min times
Pair p = new Pair();
p.maxTime = stats.timeStamp;
p.minTime = stats.timeStamp;
// Adds the new combination to the HashMap, which can now be updated in the if-statement
statsList.put(statsStr, p);
}
}
statsList will now contain the max and min times for each combination with (userID + " " + manID + " " + sessionID) as the keys. You will then be able to get the Pair object for a specific combination by using statsList.get(userId + " " + manId + " " + sessionId) (as long as it exists of course).
Here is the Pair class
class Pair{
public long minTime;
public long maxTime;
}
public class Main
{
public static void main( String[] args )
{
Map< TimeSpentStats, MinMax > hashMap = new HashMap< TimeSpentStats, MinMax >();
addToMap( hashMap, new TimeSpentStats( 1, "01F", 5, 1000L ) );
addToMap( hashMap, new TimeSpentStats( 1, "01F", 5, 1005L ) );
addToMap( hashMap, new TimeSpentStats( 3, "6Y", 3, 7L ) );
addToMap( hashMap, new TimeSpentStats( 3, "6Y", 3, 16L ) );
for ( Map.Entry< TimeSpentStats, MinMax > entry : hashMap.entrySet() )
{
TimeSpentStats timeSpentStats = entry.getKey();
MinMax minMax = entry.getValue();
System.out.println( timeSpentStats.getManId() + "\t" + timeSpentStats.getSessionId() + "\t" + timeSpentStats.getUserId() + "\tMin Time Stamp :" + minMax.getMin() + "\tMax Time Stamp :" + minMax.getMax() );
}
}
private static void addToMap( Map< TimeSpentStats, MinMax > hashMap, TimeSpentStats timeSpentStats )
{
MinMax timeStampMinMax = hashMap.get( timeSpentStats );
if ( timeStampMinMax != null )
timeStampMinMax.updateValues( timeSpentStats.getTimeStamp() );
else
hashMap.put( timeSpentStats, new MinMax( timeSpentStats.getTimeStamp() ) );
}
}
class MinMax
{
private Long min;
private Long max;
MinMax( Long timeStamp )
{
this.min = timeStamp;
this.max = timeStamp;
}
public Long getMin()
{
return min;
}
public Long getMax()
{
return max;
}
public boolean updateValues( Long timeStamp )
{
if ( timeStamp < this.min )
{
this.min = timeStamp;
return true;
}
else if ( timeStamp > this.max )
{
this.max = timeStamp;
return true;
}
return false;
}
}
class TimeSpentStats
{
private final int manId;
private final String sessionId;
private final int userId;
private final Long timeStamp;
public TimeSpentStats( int manId, String sessionId, int userId, Long timeStamp )
{
this.manId = manId;
this.sessionId = sessionId;
this.userId = userId;
this.timeStamp = timeStamp;
}
public int getManId()
{
return manId;
}
public String getSessionId()
{
return sessionId;
}
public int getUserId()
{
return userId;
}
public Long getTimeStamp()
{
return timeStamp;
}
#Override
public boolean equals( Object obj )
{
if ( obj instanceof TimeSpentStats )
{
TimeSpentStats timeSpentStats = (TimeSpentStats)obj;
return this.manId == timeSpentStats.manId && this.sessionId.equals(timeSpentStats.sessionId) && this.userId == timeSpentStats.userId;
}
return false;
}
#Override
public int hashCode()
{
return sessionId.hashCode();
}
}
Edit : a small bug is fixed. Here I had forgot to use .equals(), as the sessionId you have mentioned is of String type.
If the elements of the triple are independent, then this is a problem in combinatorics as much as anything else: you need to find all of the triples. That's a pretty well-described problem, and there are recursive solutions that Java can handle, though of course you have to watch the stack if the problem gets large. If the elements of the triple are dependent, then life is easier.
In any case, the brute force approach is obvious: iterate over the comparable items and compare item to max and compare item to min. Record the max and the min.
If these are in an object, then you can make a nested HashMap, for example mapping manIds to (maps of sessionIds to (maps of Userids to (max,min))) where max, min might be the object which contains the max/min value or they might be the values themselves - that's up to you and what you need.
This map would be a static member of the class that these instantiate, essentially you'd be caching the maxen and the mins as the objects are created. Not too hard to see how this would go into the constructor. This adds some overhead as the problem gets large, but it spares you a lot of iteration, so it's probably a worthwhile tradeoff.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I created this package, and the problem is when is runs it repeats the same catalog entries between bins.
I think the problem is in the detailedInventory method.
SHOULD BE: It should create a new random bin item (type, title, artist) for Bin B, not use the same element from Bin A. Other than this, the output is correct. SKU numbers are correctly generated and displayed.
**The values of i, when they correspond to the catalog, are objects. they are actually different types of physical media, such as DVDs or cassettes, with title, artist and SKU attributes.
***Although it does not seem to make sense, the data should be generated randomly. (This class is part of a larger concept/lesson to illustrate inheritance.)
Any help would be greatly appreciated!
Here is the output I see:
Bin A:
DVD - Greatest Hits Volume 2 (Limp Bizkit), SKU 1234-0: 500
Cassette - The Best Of (Michael Jackson), SKU 1234-1: 25
DVD - Love Songs (Michael Jackson), SKU 1234-2: 7720
Bin B:
DVD - Greatest Hits Volume 2 (Limp Bizkit), SKU 1234-3: 1000
The bin item under Bin B should not be the same as A.
public class testMusicMedia
{
public static ArrayList<MusicMedia> MakeMusicCatalog( int size )
{
String[] titles =
{
"Greatest Hits Volume 1", "Greatest Hits Volume 2",
"The Best Of", "Love Songs",
"The Early Years", "The Later Years"
};
String[] artists =
{
"Michael Jackson", "Eminem",
"The Beatles", "Shania Twain",
"Limp Bizkit"
};
ArrayList<MusicMedia> catalog = new ArrayList<MusicMedia>();
Random rn = new Random();
for ( int i = 0 ; i < size ; i++ )
{
MusicMedia m;
int mediatype = rn.nextInt( 3 );
String title = titles[ rn.nextInt( titles.length ) ];
String artist = artists[ rn.nextInt( artists.length ) ];
String sku = "1234-" + i;
if ( mediatype == 0 )
m = new CompactDisk( title, artist, sku );
else if ( mediatype == 1 )
m = new DigitalVideoDisk( title, artist, sku );
else
m = new CassetteTape( title, artist, sku );
catalog.add( m );
}
return catalog;
}
public static String lookupMedia( ArrayList<MusicMedia> catalog,
String sku )
{
for ( MusicMedia m : catalog )
{
if ( m.getSKU().equals( sku ))
return "SKU is in catalog";
}
return "SKU not in catalog";
}
public static String detailedInventory( ArrayList<MusicMedia> catalog, ArrayList<Bin> warehouse )
{
String s = "";
for ( Bin bn : warehouse ){
s += "Bin " + bn.getName() + ":\n";
for (int i = 0; i < bn.getContents().size(); i++){
s += catalog.get(i) + ", " + bn.getContents().get(i) + "\n";
}
}
s += "\n";
return s;
}
public static void main( String[] args )
{
ArrayList<MusicMedia> catalog = MakeMusicCatalog( 10 );
ArrayList<Bin> warehouse = new ArrayList<Bin>();
Bin a = new Bin( "A" );
Bin b = new Bin( "B" );
warehouse.add( a );
warehouse.add( b );
a.add( new BinItem( "1234-0", 500 ) );
a.add( new BinItem( "1234-1", 25 ) );
a.add( new BinItem( "1234-2", 7720 ) );
b.add( new BinItem( "1234-3", 1000 ) );
System.out.println( detailedInventory( catalog, warehouse ) );
}
}
I call the collection of all the items in a bin that share the same SKU a “bin item”. Each object of the Bin class (not shown) represents a bin in a pretend warehouse. A Bin object has two instance variables: a String that contains the bin name and an ArrayList that contains a BinItem for each of the SKUs stored in the bin. The toString method of the Bin class uses the toString method of the BinItem class. It generates lists that only involve SKUs and quantities.
This method should use a for-each loop to cycle thorugh all the bins in the warehouse. For each bin, s should be extended by the String "Bin " followed by the name of the bin, followed by a colon and \n to start new line. Then it should cycle through all the bin items in the current bin, for each one
extending s by a new line of text that begins with the result of looking up the current bin item’s SKU in the input catalog, and continue with a comma followed by the String representation of the bin item.
The output should look something like this:
Bin A:
CD - The Later Years (Shania Twain), SKU 1234-0: 500
Cassette - Greatest Hits Volume 2 (The Beatles), SKU 1234-1: 25
Cassette - Greatest Hits Volume 1 (Shania Twain), SKU 1234-2: 7720
Bin B:
Cassette - Greatest Hits Volume 2 (Michael Jackson), SKU 1234-3: 1000
Full code:
public class MusicMedia
{
private String myTitle,
myArtist,
mySKU;
public MusicMedia( String title, String artist, String sku )
{
myTitle = title;
myArtist = artist;
mySKU = sku;
}
public String getTitle()
{
return myTitle;
}
public String getArtist()
{
return myArtist;
}
public String getMediaType()
{
return "Unknown";
}
public String getSKU()
{
return mySKU;
}
public String toString()
{
return " - " + getTitle() + " (" + getArtist() + ")";
}
}
public class Disk extends MusicMedia
{
/**
* Constructor for objects of class Disk
*/
public Disk( String title, String artist, String sku )
{
super(title, artist, sku);
}
public String getMediaType()
{
return "Disk";
}
public String toString()
{
return getMediaType() + super.toString();
}
}
I also have an identical CassetteTape class that also extends MusicMedia. Also two other subclasses of Disk, called CompactDisk and DigitalVideoDisk. These two are also almost identical to each other, so I have pasted the DVD class below.
public class DigitalVideoDisk extends Disk
{
/**
* Constructor for objects of class DigitalVideoDisk
*/
public DigitalVideoDisk( String title, String artist, String sku )
{
super(title, artist, sku);
}
public String getMediaType()
{
return "DVD";
}
}
public class BinItem
{
private String mySKU;
private int myQuantity;
public BinItem( String sku, int quantity )
{
mySKU = sku;
myQuantity = quantity;
}
public String getSKU()
{
return mySKU;
}
public int getQuantity()
{
return myQuantity;
}
public String toString()
{
return "SKU " + getSKU() + ": " + getQuantity();
}
}
public class Bin
{
private String myName; //bin name
private ArrayList<BinItem> myContents; //contains a binItem
public Bin( String name )
{
myName = name;
myContents = new ArrayList<BinItem>();
}
public String getName()
{
return myName;
}
public ArrayList<BinItem> getContents()
{
return myContents;
}
public void add( BinItem b )
{
myContents.add( b );
}
public String toString()
{
String s = "Bin " + myName + ":\n";
for ( BinItem b : myContents )
s += b + "\n";
return s;
}
}
Ok, per your edit:
...the result of looking up the current bin item’s SKU in the input catalog...
You aren't doing this right now and it was the key point that we needed to understand what the program was supposed to do. Right now you're just retrieving an element from catalog using i, basically arbitrarily.
So the first thing you need to do is create a helper method that searches catalog for a MusicMedia object of a certain SKU. You have a method very much like it called lookupMedia so I've just modified it to this slightly different specification. This returns m instead of a String value:
public static MusicMedia getMediaBySKU(
ArrayList<MusicMedia> catalog, String sku
) {
for ( MusicMedia m : catalog ) {
if ( m.getSKU().equals(sku) )
return m;
}
return null;
}
Now that you are able to retrieve an item based on the SKU you can modify the detailedInventory loop to use it:
for ( Bin bn : warehouse ){
s += "Bin " + bn.getName() + ":\n";
for ( BinItem item : bn.getContents() ){
MusicMedia mm = getMediaBySKU(catalog, item.getSKU());
s += mm + ", " + item + "\n";
}
}
(Not sure how to get the SKU from the BinItem so I guessed but I hope you get the idea. If you don't have a method that returns the SKU already, you probably need to make one.)