Iterator and printing details - java

Hey all. I've been asked to create a method that uses an iterator to print details of 'lots'. I'm able to create an iterator that prints all of the details, however, for any lots that haven't been bought, a message should print out this fact and I'm unsure how I can add that code in. It is the public void close method I'm focusing on. This is what I have so far. Help is greatly appreciated.
public class Auction{
// The list of Lots in this auction.
private final ArrayList<Lot> lots;
// The number that will be given to the next lot entered
// into this auction.
private int nextLotNumber;
/**
* Create a new auction.
*/
public Auction(){
lots = new ArrayList<Lot>();
nextLotNumber = 1;
}
/**
* Enter a new lot into the auction.
*
* #param description
* A description of the lot.
*/
public void enterLot(final String description){
lots.add(new Lot(nextLotNumber, description));
nextLotNumber++;
}
/**
* Show the full list of lots in this auction.
*/
public void showLots(){
for(final Lot lot : lots){
System.out.println(lot.toString());
}
}
public void close(){
final Iterator<Lot> it = lots.iterator();
while(it.hasNext()){
}
}
/**
* Bid for a lot. A message indicating whether the bid is
* successful or not is printed.
*
* #param number
* The lot number being bid for.
* #param bidder
* The person bidding for the lot.
* #param value
* The value of the bid.
*/
public void bidFor(final int lotNumber,
final Person bidder,
final long value){
final Lot selectedLot = getLot(lotNumber);
if(selectedLot != null){
final boolean successful =
selectedLot.bidFor(new Bid(bidder, value));
if(successful){
System.out.println("The bid for lot number " + lotNumber
+ " was successful.");
} else{
// Report which bid is higher.
final Bid highestBid = selectedLot.getHighestBid();
System.out.println("Lot number: " + lotNumber
+ " already has a bid of: " + highestBid.getValue());
}
}
}
}

Does the Lot class have a flag indicating if it's purchased or not? If so then
for(final Lot lot : lots){
if (!lot.purchased) {
System.out.println("not bought");
}
}
BTW - I noticed you're using the pre for-each style iterator in the close method. There's no reason to do this since you'll have access to individual Lot instances in the for-each also.

I would add the information you want the Lot to print to the Lot.toString() I would suggest your close() method should close() each lot, and the lot should print anything which needs to be printed.

Add an attribute to the Lot class of type Person called "winner" or something similar.
In the bidFor method, in the if (successful) block, set the winner attribute:
selectedLot.setWinner(bidder);
Then when iterating through the lots, if the winner attribute is null, print your message that the lot hasn't been bought.
Or you could use:
if (lot.getHighestBid() == null)
depending on how the Lot class is implemented, hard to know without seeing the Lot class.

Related

Should I use atomic integer or sync

I've got a little confused about using atomic/volatile/sync in my code.
Let's say I have an object of book info in a bookstore and for example, it may happen that two threads want to take the same book while the amount in the inventory is only 1, how can I promise that only one thread will take the book?
do I have to use synchronize?
BookInventoryInfo:
package bgu.spl.mics.application.passiveObjects;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Passive data-object representing a information about a certain book in the inventory.
*
* <p>
*
*/
public class BookInventoryInfo {
//The title of the book, his amount in the inventory and the price
private String bookTitle;
private AtomicInteger amountInInventory;
private int price;
public BookInventoryInfo(String bookTitle, int amountInInventory, int price) {
this.bookTitle = bookTitle;
this.price = price;
this.amountInInventory = new AtomicInteger(amountInInventory);
}
/**
* Retrieves the title of this book.
* <p>
* #return The title of this book.
*/
public String getBookTitle() {
return this.bookTitle;
}
/**
* Retrieves the amount of books of this type in the inventory.
* <p>
* #return amount of available books.
*/
public int getAmountInInventory() {
return this.amountInInventory.get();
}
/**
* Retrieves the price for book.
* <p>
* #return the price of the book.
*/
public int getPrice() {
return this.price;
}
public void reduceAmountInInventory() {
this.amountInInventory.decrementAndGet();
}
}
The way I want to take the book:
if(book.getAmountInInventory > 0)
{
book.amountInInventory--
}
You should use synchronized as using AtomicInteger isn't as simple as it might appear at first glance. While individual operations on AtomicInteger are thread safe, using multiple operations might not be. Your example is a good one. say you have
// say it start at 1
Thread1: if(book.getAmountInInventory > 0)
Thread2: if(book.getAmountInInventory > 0)
Thread1: book.amountInInventory--
Thread2: book.amountInInventory--
The amount is now -1.
If you use synchronized it is much simpler to hold the lock for the whole operation
synchronized (book) {
if(book.getAmountInInventory > 0) // no chance for a race condition here.
{
book.amountInInventory--
}
An AtomicInteger isn't sufficient here. While it would allow you to decrement the number of copies in the inventory atomically, that isn't enough - you don't need to just decrement it atomically, you also need to add some custom logic.
I'd use a plain old int, and protect its modification with explicit synchronized blocks or methods:
public class BookInventoryInfo {
private String bookTitle;
private int amountInInventory;
private int price;
public synchronized void checkOut() {
if (amountInInventory <= 0) {
throw new BookCheckoutException("No book in inventory");
}
amountInInventory--;
}
// All the other methods...
}
As an alternative to synchronization, you can also use a compareAndSet:
int a = book.amountInventory.get();
if (a > 0) {
boolean updated = book.amountInInventory.compareAndSet(a, a - 1);
}
This will only decrement the value of amountInInventory if its value is still a when you come to update it. The return value of compareAndSet indicates whether the value was changed or not.
You can wrap this in a loop, something like:
while (true) {
int a = book.amountInventory.get();
if (a == 0) {
return false; // To mean "no book in inventory";
}
if (book.amountInInventory.compareAndSet(a, a - 1)) {
return true; // To mean "there was a book in inventory, and it was removed".
}
}

How to iterate through array list and add or remove Object based on conditions?

So I'm making a few classes that handle a collection of DVD Objects. My add and remove methods are supposed to do this:
add – this method is used to add a new DVD. It should have five parameters that
represent the title, category, running time, year, and price of a DVD. If the title is already in the DVD collection, there is no need to add or change anything.Otherwise, the DVD is added to the collection. It returns the DVD entry if it is already in the DVD collection, or returns null if a new one is added.
remove – this method should have a title as the parameter. It should remove the
DVD from the collection if the title is found. It returns the DVD entry which was removed, or returns null if the title is not found.
My methods currently work only for the first object in my text file but when I type in another object further down the file, It just returns null.
My text file contains the following 6 objects.
Adam
Documentary
78 minutes
2012
7.99
Choo Choo
Documentary
60 minutes
2006
11.99
Good Morning America
Documentary
80 minutes
2010
9.99
Life is Beautiful
Drama
125 minutes
1999
15.99
Morning Bird
Comic
150 minutes
2008
17.99
Mystic River
Mystery
130 minutes
2002
24.99
public DVD add(String titlez, String categoryz, String runTimez, String yearz, String pricez) {
Iterator<DVD> it = arraylist.iterator();
DVD dvd = it.next();
if(dvd.getTitle().equals(titlez)){
return dvd;
}
else{
DVD dvd1 = new DVD (titlez, categoryz, runTimez, yearz, pricez);
arraylist.add(dvd1);
return null;
}
}
#Override
public DVD remove(String title) {
Iterator<DVD> it = arraylist.iterator();
DVD dvd = it.next();
if(dvd.getTitle().equals(title)){
arraylist.remove(dvd);
return dvd;
} else {
return null;
}
}
You are not looping on entire list try to use this instead:
Iterator<DVD> it = arraylist.iterator();
while(it.hasNext()) {
DVD dvd = it.next();
if(dvd.getTitle().equals(title)){
arraylist.remove(dvd);
return dvd;
}
}
return null;
Your add method is not iterating through the list; it's just testing the first element. (It would also throw an exception if your list was empty.) Try this instead, which iterates through the entire list before deciding that the title is not present. (I'm using the enhanced for loop syntax instead of a traditional for loop.)
public DVD add(String titlez, String categoryz, String runTimez, String yearz, String pricez) {
for (DVD dvd : arrayList) {
if(dvd.getTitle().equals(titlez)){
return dvd;
}
}
DVD dvd1 = new DVD (titlez, categoryz, runTimez, yearz, pricez);
arraylist.add(dvd1);
return null;
}
Your remove method has a similar problem. Use this instead:
public DVD remove(String title) {
for (DVD dvd : arrayList) {
if (dvd.getTitle().equals(title)) {
arrayList.remove(dvd);
return dvd;
}
}
return null;
}
Note that this is style is a bit dangerous. Normally, you shouldn't modify a list while iterating through it. If the iteration continued, you'd get a ConcurrentModificationException thrown. However, since you also stop iterating immediately upon modifying the list, it should be okay. There are two ways to avoid an exception and still modify the list. (1) use a ListIterator instead of an Iterator, because ListIterator has it's own remove() method you can use. You'd have to go back to a traditional for loop syntax. (2) defer the removal until iteration is done, like this:
public DVD remove(String title) {
DVD toRemove = null;
for (DVD dvd : arrayList) {
if (dvd.getTitle().equals(title)) {
toRemove = dvd;
break;
}
}
if (toRemove != null) {
arrayList.remove(toRemove);
}
return toRemove;
}
As someone has already "answered", you are not iterating through the whole list.
I have refactored your code to make the add and remove methods cleaner. I have created a POJO (plain old java object) DVD, and a DVDService which has a DVDStore.
The DVDStore stores a DVD using the titlez as its "key". The add and remove methods use an exists method to check if the DVD key is in the DVDStore.
I return true of false for add or remove. I try and add a new DVD "film1" twice, and then remove twice.
The output from running is here:
film1 has been added = true
film1 has been added = false
film1 has been removed = true
film1 has been removed = false
I have removed the iterator you are using, and search the HashMap for the "titlez" key. I also return a "simple boolean" for add and remove. Has add or remove been successful (true or false).
This makes add and remove easy to understand, and maintain.
import java.util.HashMap;
import java.util.Map;
class DVD {
private String titlez;
private String categoryz;
private String runTimez;
private String yearz;
private String price;
/**
* DVD constructor
*
* #param titlez - title
* #param categoryz - category
* #param runTimez - length of file
* #param yearz - year made
* #param price - price
*/
DVD(String titlez, String categoryz, String runTimez, String yearz, String price) {
this.titlez = titlez;
this.categoryz = categoryz;
this.runTimez = runTimez;
this.yearz = yearz;
this.price = price;
}
/**
* get DVD titlez
* #return - DVD titlez
*/
String getTitlez() {
return titlez;
}
}
public class DVDService {
private Map<String, DVD> dvdStore; // DVD store - use DVD titlez to "look up" DVD
/**
* Convenience method for checking if a title exists in our DVD Store
* #param titlez - DVD title
* #return - true if exists in DVD store
*/
private boolean exists(String titlez) {
return dvdStore.containsKey(titlez);
}
/**
* Add a DVD to the DVD store
* #param dvd - DVD to be added
* #return - true if DVD added
*/
private boolean add(DVD dvd) {
if (dvdStore == null) { // if DVD store is null - create it
dvdStore = new HashMap<>();
}
// if title does NOT exist - add it to the DVD store and return true
if (!exists(dvd.getTitlez())) {
dvdStore.put(dvd.getTitlez(), dvd);
return true;
}
return false; // title already exists
}
/**
* Remove DVD from DVD store
* #param dvd - DVD to be removed
* #return - true if DVD removed
*/
private boolean remove(DVD dvd) {
if (exists(dvd.getTitlez())) {
dvdStore.remove(dvd.getTitlez());
return true;
}
return false;
}
public static void main(String[] args) {
DVD dvd = new DVD("film1", "Mystery", "2 hours", "1971", "2.00");
DVDService dvdService = new DVDService();
/**
* Add a DVD = true
* Add again = false as it exists in the DVD store
*
* Remove DVD = true as it exists
* Remove DVD = false as it no longer exists
*/
System.out.printf("%s has been added = %s\n", dvd.getTitlez(), dvdService.add(dvd));
System.out.printf("%s has been added = %s\n", dvd.getTitlez(), dvdService.add(dvd));
System.out.printf("%s has been removed = %s\n", dvd.getTitlez(), dvdService.remove(dvd));
System.out.printf("%s has been removed = %s", dvd.getTitlez(), dvdService.remove(dvd));
}
}

How to modify a constructor of LogAnalyzer class to include an argument that calls to LogReader class?

First, I am aware that a similar question has been asked a few years ago but it doesn't appear to work for some reason or another. The code fragment compiles, yes, but it doesn't work as each time I try to execute the program, I run into this error
"java.lang.String can not be converted to LogfileReader."
I know what this error means but I do not know why this is happening and I don't have enough coding experience to figure it out on my own. Additionally, this is the first time that I have encountered having to use 'this' or an argument inside of a constructor (rather than an argument in a method) so I have no previous experience with it.
I have a theory that I need to include some sort of LogfileReader reader = new LogfileReader(r); but that also seems incorrect.
The objective is to create a LogfileAnalyzer object that then passes the name of a file that I create in LogfileCreator onto LogfileReader's constructor. I believe that this includes an instance of 'this' and the book implies that this can be done without any modifications to the class of LogfileReader.
This is the relevant bit of code in LogfileAnalyzer:
public class LogAnalyzer
{
// Where to calculate the hourly access counts.
private int[] hourCounts;
// Use a LogfileReader to access the data.
private LogfileReader reader;
/**
* Create an object to analyze hourly web accesses.
* Reads files created in LogfileCreator
*/
public LogAnalyzer(LogfileReader r)
{
this.reader = r;
hourCounts = new int[24];
}
And it is based on a previous answered question of a similar nature.
After creating the file using LogfileCreator and typing in the string ("This Blog") into the prompt for LogfileAnalyzer(LogfileReader r), I end up with the String error above.
If this helps, this is the full code for the LogfileReader class:
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Random;
import java.util.Scanner;
/**
* A class to read information from a file of web server accesses.
* Currently, the log file is assumed to contain simply
* date and time information in the format:
*
* year month day hour minute
* Log entries are sorted into ascending order of date.
*
* #author David J. Barnes and Michael Kölling.
* #version 2016.02.29
*/
public class LogfileReader implements Iterator<LogEntry>
{
// The data format in the log file.
private String format;
// Where the file's contents are stored in the form
// of LogEntry objects.
private ArrayList<LogEntry> entries;
// An iterator over entries.
private Iterator<LogEntry> dataIterator;
/**
* Create a LogfileReader to supply data from a default file.
*/
public LogfileReader()
{
this("weblog.txt");
}
/**
* Create a LogfileReader that will supply data
* from a particular log file.
* #param filename The file of log data.
*/
public LogfileReader(String filename)
{
// The format for the data.
format = "Year Month(1-12) Day Hour Minute";
// Where to store the data.
entries = new ArrayList<>();
// Attempt to read the complete set of data from file.
boolean dataRead;
try{
// Locate the file with respect to the current environment.
URL fileURL = getClass().getClassLoader().getResource(filename);
if(fileURL == null) {
throw new FileNotFoundException(filename);
}
Scanner logfile = new Scanner(new File(fileURL.toURI()));
// Read the data lines until the end of file.
while(logfile.hasNextLine()) {
String logline = logfile.nextLine();
// Break up the line and add it to the list of entries.
LogEntry entry = new LogEntry(logline);
entries.add(entry);
}
logfile.close();
dataRead = true;
}
catch(FileNotFoundException | URISyntaxException e) {
System.out.println("Problem encountered: " + e);
dataRead = false;
}
// If we couldn't read the log file, use simulated data.
if(!dataRead) {
System.out.println("Failed to read the data file: " + filename);
System.out.println("Using simulated data instead.");
createSimulatedData(entries);
}
// Sort the entries into ascending order.
Collections.sort(entries);
reset();
}
/**
* Does the reader have more data to supply?
* #return true if there is more data available,
* false otherwise.
*/
public boolean hasNext()
{
return dataIterator.hasNext();
}
/**
* Analyze the next line from the log file and
* make it available via a LogEntry object.
*
* #return A LogEntry containing the data from the
* next log line.
*/
public LogEntry next()
{
return dataIterator.next();
}
/**
* Remove an entry.
* This operation is not permitted.
*/
public void remove()
{
System.err.println("It is not permitted to remove entries.");
}
/**
* #return A string explaining the format of the data
* in the log file.
*/
public String getFormat()
{
return format;
}
/**
* Set up a fresh iterator to provide access to the data.
* This allows a single file of data to be processed
* more than once.
*/
public void reset()
{
dataIterator = entries.iterator();
}
/**
* Print the data.
*/
public void printData()
{
for(LogEntry entry : entries) {
System.out.println(entry);
}
}
/**
* Provide a sample of simulated data.
* NB: To simplify the creation of this data, no
* days after the 28th of a month are ever generated.
* #param data Where to store the simulated LogEntry objects.
*/
private void createSimulatedData(ArrayList<LogEntry> data)
{
LogfileCreator creator = new LogfileCreator();
// How many simulated entries we want.
int numEntries = 100;
for(int i = 0; i < numEntries; i++) {
data.add(creator.createEntry());
}
}
}
Thank anyone who wants to help or assist. I apologize for my lack of knowledge. I feel like the answer is probably rather simple but I can't figure out.

How do a reference a variable in another object

I am an absolute programming beginner, and I am trying to learn Java from a book. I'm very confused.
The book has an exercise (this is like halfway through the chapter, so there's a lot building up to this, but I'll try to make it clear) that asks us to add a method to a class. Basically, we were given a prebuilt set of classes that are supposed to be like a simple auction program. So there is an array list which contains a list of bidders, how much they bid, and the lot number. This exercise asks us to add a method that will print out a list of the names of the winning bidders and the value of their bids.
Okay, that makes sense. I can wrap my mind around how it is supposed to work. I even wrote the following code: `
/**
* Exercise 4.48
* for each item in the list of lots, get the highest bid.
* if highest bid is not null, print the bidder and value
* otherwise, print "lot not sold"
*/
public void close()
{
for(Lot lot : lots) {
Bid highestBid = lot.getHighestBid();
if(highestBid != null) {
System.out.println(bidder, value);
}
else{
System.out.println("Lot not sold.");
}
}
}
When try to compile it, it stops on bidder because I haven't defined the variable. So obviously I am supposed to tell it what "bidder" is supposed to mean. Bidder is the name of the variable in the "Person" object in the same program and is used throughout the project, but I'm still not clear on how to get it to understand that my "bidder" is the same "bidder." I assume that I will have the same issue with "value."
What am I missing?
Edited to make the code actually look like code.
As requested, here is the Person... class? (I'm not great with the terminology. I'll get there. Sorry.)
/**
* Maintain details of someone who participates in an auction.
* #author David J. Barnes and Michael Kölling.
* #version 2011.07.31
*/
public class Person
{
// The name of this person.
private final String name;
/**
* Create a new person with the given name.
* #param name The person's name.
*/
public Person(String name)
{
this.name = name;
}
/**
* #return The person's name.
*/
public String getName()
{
return name;
}
}
**/**
* A class to model an item (or set of items) in an
* auction: a lot.
*
* #author David J. Barnes and Michael Kölling.
* #version 2011.07.31
*/
public class Lot
{
// A unique identifying number.
private final int number;
// A description of the lot.
private String description;
// The current highest bid for this lot.
private Bid highestBid;
/**
* Construct a Lot, setting its number and description.
* #param number The lot number.
* #param description A description of this lot.
*/
public Lot(int number, String description)
{
this.number = number;
this.description = description;
this.highestBid = null;
}
/**
* Attempt to bid for this lot. A successful bid
* must have a value higher than any existing bid.
* #param bid A new bid.
* #return true if successful, false otherwise
*/
public boolean bidFor(Bid bid)
{
if(highestBid == null) {
// There is no previous bid.
highestBid = bid;
return true;
}
else if(bid.getValue() > highestBid.getValue()) {
// The bid is better than the previous one.
highestBid = bid;
return true;
}
else {
// The bid is not better.
return false;
}
}
/**
* #return A string representation of this lot's details.
*/
public String toString()
{
String details = number + ": " + description;
if(highestBid != null) {
details += " Bid: " +
highestBid.getValue();
}
else {
details += " (No bid)";
}
return details;
}
/**
* #return The lot's number.
*/
public int getNumber()
{
return number;
}
/**
* #return The lot's description.
*/
public String getDescription()
{
return description;
}
/**
* #return The highest bid for this lot.
* This could be null if there is
* no current bid.
*/
public Bid getHighestBid()
{
return highestBid;
}
}
**
/**
* A class that models an auction bid.
* It contains a reference to the Person bidding and the amount bid.
*
* #author David J. Barnes and Michael Kölling.
* #version 2011.07.31
*/
public class Bid
{
// The person making the bid.
private final Person bidder;
// The value of the bid. This could be a large number so
// the long type has been used.
private final long value;
/**
* Create a bid.
* #param bidder Who is bidding for the lot.
* #param value The value of the bid.
*/
public Bid(Person bidder, long value)
{
this.bidder = bidder;
this.value = value;
}
/**
* #return The bidder.
*/
public Person getBidder()
{
return bidder;
}
/**
* #return The value of the bid.
*/
public long getValue()
{
return value;
}
}
import java.util.ArrayList;
/**
* A simple model of an auction.
* The auction maintains a list of lots of arbitrary length.
*
* #author David J. Barnes and Michael Kölling.
* #version 2011.07.31
*
* 3/12/15 added close method exercise 4.48
*
*/
public class Auction
{
// The list of Lots in this auction.
private ArrayList<Lot> lots;
// The number that will be given to the next lot entered
// into this auction.
private int nextLotNumber;
/**
* Create a new auction.
*/
public Auction()
{
lots = new ArrayList<Lot>();
nextLotNumber = 1;
}
/**
* Enter a new lot into the auction.
* #param description A description of the lot.
*/
public void enterLot(String description)
{
lots.add(new Lot(nextLotNumber, description));
nextLotNumber++;
}
/**
* Show the full list of lots in this auction.
*/
public void showLots()
{
for(Lot lot : lots) {
System.out.println(lot.toString());
}
}
/**
* Make a bid for a lot.
* A message is printed indicating whether the bid is
* successful or not.
*
* #param lotNumber The lot being bid for.
* #param bidder The person bidding for the lot.
* #param value The value of the bid.
*/
public void makeABid(int lotNumber, Person bidder, long value)
{
Lot selectedLot = getLot(lotNumber);
if(selectedLot != null) {
Bid bid = new Bid(bidder, value);
boolean successful = selectedLot.bidFor(bid);
if(successful) {
System.out.println("The bid for lot number " +
lotNumber + " was successful.");
}
else {
// Report which bid is higher.
Bid highestBid = selectedLot.getHighestBid();
System.out.println("Lot number: " + lotNumber +
" already has a bid of: " +
highestBid.getValue());
}
}
}
/**
* Return the lot with the given number. Return null
* if a lot with this number does not exist.
* #param lotNumber The number of the lot to return.
*/
public Lot getLot(int lotNumber)
{
if((lotNumber >= 1) && (lotNumber < nextLotNumber)) {
// The number seems to be reasonable.
Lot selectedLot = lots.get(lotNumber - 1);
// Include a confidence check to be sure we have the
// right lot.
if(selectedLot.getNumber() != lotNumber) {
System.out.println("Internal error: Lot number " +
selectedLot.getNumber() +
" was returned instead of " +
lotNumber);
// Don't return an invalid lot.
selectedLot = null;
}
return selectedLot;
}
else {
System.out.println("Lot number: " + lotNumber +
" does not exist.");
return null;
}
}
/**
* Exercise 4.48
* for each item in the list of lots, get the highest bid.
* if highest bid is not null, print the bidder and value
* otherwise, print "lot not sold"
*/
public void close()
{
for(Lot lot : lots) {
Bid highestBid = lot.getHighestBid();
if(highestBid != null) {
System.out.println(bidder, value);
}
else{
System.out.println("Lot not sold.");
}
}
}
Thanks for clarifying your question by providing the supporting code!
This should fix your problem. Change this line:
System.out.println(bidder, value);
to this:
System.out.println(highestBid.getBidder().getName() + " bids " + highestBid.getValue())
The highestBid variable stores an object of type Bid. You can see the Bid class definition to see what it means for an object to have type Bid. Basically, a Bid object has a method called getValue(), which returns the value of the bid, and a method getBidder(), which returns a Person object (an object that abides by the Person class definition). So, look in the Person class and see how a Person object has a method called getName(), which returns the name of the person as a String.
Finally, we can just print the name and value with our handy built-in System.out.println() function.
To teach you the very basic,
Consider a class as a real life object,
It has it own characteristics which you define as class variables.
These should be (generally) defined private so a call to them has to happen from a class-function (getters and setters). The reason why we do this is so you can setup some restrictions. (like: "not higher than 3" or "must be min. 4 char. long" ...)
The class functions are like: small hidden classes within a Class they execute some code. Notice the "In", functions IN class. not the other way around. So the variables you create inside the functions are not known to the class, but the function knows the class-variables.
I would suspect in your case that you called to bidderand value:
Without use of getters if they are defined private outside the same class where your close() function is defined.
But really it is very hard for us to know what is wrong. Please provide us with the classof the close() function
EDIT:
the code for close()should be...
public void close()
{
for(Lot lot : lots) {
Bid highestBid = lot.getHighestBid();
if(highestBid != null) {
System.out.println(highestBid.getBidder(), highestBid.getValue());
}
else{
System.out.println("Lot not sold.");
}
}

Adding elements to an hashmap

So I have an issue with Hashmaps and a login feature.
When using addLogin I am required to enter parameters but it makes no sense to do this since I have already done this in the constructor classes. How would I simply just use addLogin and the Surname, Forename and Personal ID number is added to the hashmap?
Upon using Math.round(Math.random()*999+1) to generate a random number between 1-999 how am I supposed to go around adding this to the hashmap with the other student details?
Here is the full code that applies to both questions, apologies for the stupid questions I'm very new to Java! I am very appreciative of any help I recieve. Thanks in advance.
public class TestApplication
{
// hashmap
private HashMap<String, ArrayList <String>> Application = new HashMap<String, ArrayList <String>>();
// hashset
private HashSet<String> loginsIssued = new HashSet<String>();
// An Arry List for storing student information
private ArrayList<String> Student = new ArrayList<String>();
/**
* Constructor for objects of class Application
*/
public TestApplication(String Surname, String personalIdNo)
{
if (isValidpersonalIdNo(personalIdNo) == true)
{
Student.add(Surname);
Application.put(personalIdNo, Student);
System.out.println("Application number ### " + "has registered successfully");
}
else
{
System.out.println("Application has failed, Personal id: " + personalIdNo);
}
}
/**
* Create a Student Information
*/
public void TestApplication(String personalIdNo, String Surname, String Forename)
{
Student.add(Surname);
Student.add(Forename);
Student.add (personalIdNo);
}
/**
* Add Login
* Pull First Letter of Forenames
* Pull First Letter of Surname
* Generate Random Number
* Print
*/
public void addLogin(String Surname, String Forename)
{
String login = "";
{
System.out.println (Surname.charAt(0) + "" + " " + Forename.charAt(0) + " " + Math.round(Math.random()*999+1));
Student.add(login);
loginsIssued.add(login);
}
}
/**
* CONDITION 1
* Check whether the ID supplied is only numbers
*/
public boolean isNumeric(String personalIdNo)
{
if (personalIdNo.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")) {
return true;
}
else
{
return false;
}
}
/**
* CONDITION 2
* Check whether the ID supplied has a length of 10
*/
public boolean checkLength(String personalIdNo)
{
if (String.valueOf(personalIdNo).length()==10)
{
return true;
}
else
{
return false;
}
}
/**
* CONDITION 3
* Check whether the ID supplied starts with 1
*/
public boolean checkFirstDigit(String personalIdNo)
{
if (personalIdNo.startsWith("1"))
{
return true;
}
else
{
return false;
}
}
/**
* Validation Check - Check if it satisfies all conditions.
*/
public boolean isValidpersonalIdNo(String personalIdNo)
{
if (isNumeric(personalIdNo) && checkLength(personalIdNo) && checkFirstDigit(personalIdNo))
{
return true;
}
else
{
return false;
}
}
/**
* FORENAME
* Add Forename
*/
public void addForename(String Forename)
{
Student.add(Forename);
}
/**
* Return Surname
*/
public String getSurname()
{
return Student.get(0);
}
}
Concerning to your first question
At the initialisation i guess you just want to give the string a value normally you achieve this through writing
String login= null;
But I'm quiet not sure what you want to achieve with the empty ""
And i dont get why you dont give your login a value before you add it to the arraylist or should be this the login by default
public void addLogin(String Surname, String Forename)
String login = null;
{
System.out.println (Surname.charAt(0) + "" + " " + Forename.charAt(0) + " " + Math.round(Math.random()*999+1));
Student.add(login);
loginsIssued.add(login);
}
And just as a tip if you return boolean at your equalization methods you dont need to check in the if clauses if true == true because the if clause checks if you do it your way wether true ==true and returns true if it like this do you get my point? you 'll save resources if you dont do this twice :)
So just write your method which returns the boolean value in the if braces .
I hope i can help you
Pls comment if you need further informations
To be honest, I think there should be some rework to fix your code (sorry to not answer directly to you two questions but is impossible as is):
Fix the second constructor, which is declared as a method
Create a Student class: it is harder to retrieve fields by index and the risk is to add twice the same field or to miss adding one field.
Unless I don't fully understand what your code should achieve, the major issue is a design error : your TestApplication class manages the whole set of students and their login thus the Student instance variable is a nonsense as well as the constructors with a single student fields. You should instead create an addStudent method with the student fields as parameter or better a Student instance.
I don't understand the use of "" + " " either.
By consequence, to answer to your questions:
You can keep your addLogin method and if so, yes you have to keep all the info but you can use a Student object (or a Collection as you currently modelise a student) as parameter.
If you update the same Student (same object instance), it is of course updated in your map. If not(you use a copy of Student) then just execute Application.put(personId,Student). Have a look at this answer to get more info

Categories

Resources