Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
OK i have multiple Java files but only looking at 2 at the moment and i am doing a GUI program.
I have an arraylist of Landlords in one file with a getLandlords method that returns the array and it won't work eclipse just gives an error no matter what i try
File 1
package assignment2;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class RealEstateManage extends JFrame implements ActionListener, ListSelectionListener{
public static void main(String[] args)
{
RealEstateManage theGUI = new RealEstateManage();
}
//Initial setup for base of GUI
private JFrame jfFrame;
private JButton jbAddLandlord, jbAddProperty, jbAddLease, jbRecord, jbMaintenance, jbDisplayproperty;
private JTextArea jtaResults;
private JTextField jtfinput1, jtfinput2, jtfinput3, jtfinput4;
private JList <Landlord> jlLandlord;
private Vector<Landlord> vlist = new Vector<Landlord>();
private JPanel jpButtons = setupButtons(), jpResults = setupResults();
public RealEstateAgency R = new RealEstateAgency();
public RealEstateManage()
{
jfFrame = new JFrame ();
jfFrame.add(jpButtons, "North");
jfFrame.add(jpResults,"West");
jfFrame.setSize(900, 400);
jfFrame.setLocation(400, 300);
jfFrame.setTitle("Real Estate Management");
jfFrame.setVisible(true);
}
//Setup the buttons at the top of the GUI
public JPanel setupButtons()
{
JPanel jp = new JPanel ();
jbAddLandlord = new JButton("Add New Landlord");
jbAddProperty = new JButton("Add New Property");
jbAddLease = new JButton("Add New Lease");
jbRecord = new JButton("Record Payment");
jbMaintenance = new JButton("Maintenance");
jbDisplayproperty = new JButton("Display Properties");
jp.add(jbAddLandlord);
jp.add(jbAddProperty);
jp.add(jbAddLease);
jp.add(jbRecord);
jp.add(jbMaintenance);
jp.add(jbDisplayproperty);
jbAddLandlord.addActionListener(this);
jbAddProperty.addActionListener(this);
jbAddLease.addActionListener(this);
jbRecord.addActionListener(this);
jbMaintenance.addActionListener(this);
jbDisplayproperty.addActionListener(this);
return jp;
}
public JPanel setupResults()
{
JPanel jp = new JPanel ();
vlist.add(new Landlord("Fred Jones", "23 Hamilton Road", "0458 789 456", 456123369));
jtfinput1 = new JTextField (10);
jtfinput2 = new JTextField (10);
jtfinput3 = new JTextField (10);
jtfinput4 = new JTextField (10);
ArrayList<Landlord> Alist = R.getLandlords();
jlLandlord = new JList<Landlord>(vlist);
jlLandlord.addListSelectionListener(this);
jlLandlord.setPreferredSize(new Dimension(250, 300));
JLabel jlResults = new JLabel ("Output!");
jtaResults = new JTextArea (18, 30);
jtaResults.setEnabled(false);
jp.add(jlLandlord);
jp.add(jlResults);
jp.add(jtaResults);
return jp;
}
//List Events
#Override
public void valueChanged(ListSelectionEvent arg0) {
// TODO Auto-generated method stub
}
//Button Action Events
public void actionPerformed(ActionEvent ae) {
// Button Events
if(ae.getSource() == jbAddLandlord)
{
addLandlord();
}
if(ae.getSource() == jbAddLandlord)
{
}
}
//Add landlord function
public void addLandlord()
{
boolean inputIsOk = true;
String stName, stAddress, stNum, stBank;
long bank = 0;
JPanel myPanel = new JPanel();
myPanel.add(new JLabel("Name:"));
myPanel.add(jtfinput1);
myPanel.add(new JLabel("Address:"));
myPanel.add(jtfinput2);
myPanel.add(new JLabel("Phone:"));
myPanel.add(jtfinput3);
myPanel.add(new JLabel("Bank Account: (8-10 Digits)"));
myPanel.add(jtfinput4);
int result = JOptionPane.showConfirmDialog(null, myPanel,
"Please Enter X and Y Values", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
stName = jtfinput1.getText();
stAddress = jtfinput2.getText();
stNum = jtfinput3.getText();
stBank = jtfinput4.getText();
try{bank = Long.valueOf(stBank).longValue();
}
catch(NumberFormatException nfe){
inputIsOk = false;
}
if (inputIsOk = true){
R.addLandlord(new Landlord(stName, stAddress, stNum, bank));
}
}
// jlLandlord.updateUI();
}
}
FILE 2
package assignment2;
import java.util.*;
// The RealEstateAgency class is intended to be the central place to go to for finding
// a landlord that the system "knows" about.
public class RealEstateAgency {
private ArrayList<Landlord> allLandlords; // A way of collecting all the Landlords
public RealEstateAgency()
{
// prepare the agency for future landlords...
allLandlords = new ArrayList<Landlord>();
addLandlord(new Landlord("stName", "stAddress", "stNum", 12456897));
System.out.println(getLandlords());
}
// Method to note the provided Landlord, by adding it to the RealEstateAgency's internal ArrayList.
// Returns true if apparently successful, false if something goes wrong such as the landlord already being present.
public boolean addLandlord(Landlord whoToStore)
{
boolean success = false;
if (whoToStore == null) // ensure there is actually a parameter
success = false;
else {
if (allLandlords.contains(whoToStore)) // landlord already in the list
success = false;
else
{ // Landlord not yet in list
allLandlords.add(whoToStore); // So add this landlord
success = true;
}
}
return success;
}
// Method to obtain a landlord from the RealEstateAgency's collection of known landlords,
// by providing the full name. If no such landlord exists, null will be returned.
public Landlord getLandlord(String fullName)
{
Landlord current = null;
boolean found = false;
int index = 0;
while ((!found) && (index < allLandlords.size()))
{
current = allLandlords.get(index);
if (current.getFullName().equals(fullName))
found = true;
else
index++;
}
// If we get to here, and "found" is true, then "current" will be the matching Landlord
if (!found) // did not find a match
current = null; // so ensure we return no Landlord
return current;
}
// Method to obtain an ArrayList containing the same landlords as those which the
// RealEstateAgency knows about (but without exposing the inner ArrayList object
// so that any alterations made to the returned ArrayList won't impact the RealEstateAgency)
public ArrayList<Landlord> getLandlords()
{
ArrayList<Landlord> duplicate;
duplicate = (ArrayList<Landlord>) allLandlords.clone();
return duplicate;
}
public ArrayList<Landlord> getLandlords1()
{
return allLandlords;
}
}
Any help or suggestions would be appreciated.
The Issues i am having is in the setupResults() function and the getLandlords() function
Thanks in advance
LANDLORD CODE
package assignment2;
import java.util.*;
// The Landlord class allows you to create objects that encapsulate the key data
// about each Landlord, as well as the information about all the properties that
// they make available for rent (some of which may have current leases active).
public class Landlord {
private String fullName; // The name of the landlord
private String address; // Where the landlord lives!
private String phone; // allow for spaces in number
private long bankAccount; // To permit 10 digits, requires the 'long' data type
private ArrayList<Property> myProperties; // All properties owned by this landlord
public Landlord(String fullName, String address, String phone, long bankAccount)
{
// Simply store the parameters into the fields...
this.fullName = fullName;
this.address = address;
this.phone = phone;
this.bankAccount = bankAccount;
// prepare for future leases...
myProperties = new ArrayList<Property>();
}
// ACCESSORS for each field of basic information
public String getFullName()
{
return fullName;
}
public String getAddress()
{
return address;
}
public String getPhone()
{
return phone;
}
public long getBankAccount()
{
return bankAccount;
}
// Method to note/store another Property, where this Landlord is considered the owner of the property.
// It returns true if successfully added to the list of properties belonging to this landlord.
public boolean addProperty(Property theProperty)
{
boolean result;
if (theProperty == null) // if it is null, we ignore this method call.
result = false;
else if (!myProperties.contains(theProperty)){ // Make sure it is not already in the array list
myProperties.add(theProperty);
result = true;
}
else // This means w have already added the property, so cannot add it again.
result = false;
return result;
}
// Method to return an iterator that may be used to cycle over all leases involving this landlord.
public Iterator<Property> getPropertiesIterator()
{
return myProperties.iterator();
}
public String toString()
{
return "Landlord: " + fullName;
}
}
PROPERTY CODE
package assignment2;
// The Property class encapsulates the basic information about one property the system knows
// about: essentially the address of the property, and a reference to the Lease details of the property.
public class Property {
private String propertyAddress;
private Lease currentLease; // When null, there is no active lease (it is available).
public Property(String address)
{
this.propertyAddress = address;
this.currentLease = null; // Initially, nobody is leasing it.
}
public String getPropertyAddress()
{
return propertyAddress;
}
// no mutator for address, because it won't ever change.
// Method to return the current lease's details.
public Lease getCurrentLease()
{
return currentLease;
}
// Method to set the current Lease of this Property.
// If null is provided, the property will not have any Lease assigned to it;
// otherwise, the provided Lease will be recorded as describing the relationship for this property.
public void setCurrentLease(Lease newLease)
{
currentLease = newLease;
}
// Method to report whether or not this property is currently associated with a lease (regardless
// of whether fully paid or not)
public boolean isLeased()
{
if (currentLease == null)
return false;
else
return true;
}
public String toString()
{
return "Property: " + propertyAddress;
}
}
LEASE CODE
package assignment2;
import java.util.*;
// The Lease class encapsulates information about an individual lease of a property by a tenant.
// The data stored here includes all the tenant’s details (name, phone number) as well as
// characteristics of the lease itself such as the duration, the weekly rent amount, how long
// remains in terms of payments, what maintenance has occurred.
public class Lease {
private String tenantFullName; // The name of the person who is living in the leased property.
private String tenantPhone; // Contact number for the person. Allow a leading zero at start, spaces between sections.
private int rentRate; // The amount of rent to be paid each week.
private int leasePeriod; // Either 6 or 12, being a 6 month or 12 month agreement
private int weeksRemaining; // How many weeks remain to be paid for. Initially 26 or 52.
private ArrayList<Maintenance> maintenanceRecord; // record of all maintenance during life of lease
// Create a new lease, recording the following details:
// - tenantName: records the name of the person living in the property
// - tenantPhone: records a contact phone number for the tenant
// - rentRate: the amount of rent which is to be paid each week.
// - leasePeriod: Either 6 or 12, indicating the number of months the lease is to last for.
public Lease(String tenantName, String tenantPhone, int rentRate, int leasePeriod)
{
this.tenantFullName = tenantName;
this.tenantPhone = tenantPhone;
this.rentRate = rentRate;
if (leasePeriod == 12 || leasePeriod == 6) // Check validity of parameter
this.leasePeriod = leasePeriod;
else // if not valid, set to default of 6 month.
this.leasePeriod = 6;
// Determine (automatically) how many weeks the lease is for, and set as initial value
// for the 'weeksRemaining' field:
if (this.leasePeriod == 12)
this.weeksRemaining = 52; // a Year remains to be paid for
else
this.weeksRemaining = 26; // Only half a year remains to be paid for.
// Prepare the lease for future Maintenance records...
maintenanceRecord = new ArrayList<Maintenance>();
}
// ACCESSORS
public String getTenantFullName()
{
return tenantFullName;
}
public String getTenantPhone()
{
return tenantPhone;
}
public int getRentRate()
{
return rentRate;
}
public int getLeasePeriod()
{
return leasePeriod;
}
public int getWeeksRemaining()
{
return weeksRemaining;
}
// Method to reduce the number of weeks remaining to be paid over the period of the lease.
// If the parameter is in excess of the current number of remaining weeks, the method will
// return false, otherwise it returns true and adjusts the number of remaining weeks.
public boolean reduceWeeksRemaining(int howMuch)
{
boolean result;
if (howMuch > weeksRemaining)
result = false;
else
{
weeksRemaining -= howMuch; // Reduces how many weeks remain unpaid.
result = true;
}
return result;
}
// Method to add another maintenance information record to this lease's list of maintenance records.
public void noteMaintenance(String reason, double cost)
{
Maintenance maintInfo = new Maintenance(reason,cost);
maintenanceRecord.add(maintInfo);
}
// Method to return an Iterator that may be used to cycle over all maintenance records for this lease
public Iterator<Maintenance> getMaintenanceRecords()
{
return maintenanceRecord.iterator();
}
}
MAINTENANCE CODE
package assignment2;
// The Maintenance class is used to represent an individual occurrence of Maintenance
// and records the cost and description of the maintenance.
public class Maintenance {
private String reason;
private double cost;
public Maintenance(String reason, double cost)
{
this.reason = reason;
this.cost = cost;
}
// ACCESSORS:
public String getReason()
{
return reason;
}
public double getCost()
{
return cost;
}
// Gives a explanation of the cost and reason represented by this Maintenance object.
public String toString()
{
return "$" + cost + " for " + reason;
}
}
The reason is that you initialize setupResults() before R.
change:
private JPanel jpButtons = setupButtons(), jpResults = setupResults();
public RealEstateAgency R = new RealEstateAgency();
public RealEstateManage()
{
to
private JPanel jpButtons;
private JPanel jpResults;
public RealEstateAgency R = new RealEstateAgency();
public RealEstateManage()
{
jpButtons = setupButtons();
jpResults = setupResults();
As a sidenote:
You take the result as:
ArrayList<Landlord> Alist = R.getLandlords();
but never use that value.
Maybe you meant to write:
ArrayList<Landlord> Alist = R.getLandlords();
jlLandlord = new JList<Landlord>(Alist.toArray(new Landlord[0]));
^ ^^^^^^^^^^^^^^^^^^^^^^^^^
but you did not.
Related
I'm writing a simple Java program.
First, the program asks user to input some info like name and id of the student and uses radio button for asking whether the student is present or absent. After finishing the inputs, then program validate whether predefined student names and inputs are match or not. And check id number again and spit out if input is over 4. Lastly check radio button is true or false. If one of the above two rules get error then program will quit without executing next method.
I have three .java files. One for UI. One for validation and one for storing data.
UI.java
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class UI extends JFrame {
JTextField name = new JTextField("Name", 10);
JTextField id = new JTextField("Id", 10);
JRadioButton attendance = new JRadioButton("Present");
JButton JB = new JButton("Check");
public UI() {
super("Test");
JPanel JP = new JPanel();
JP.add(name);
JP.add(id);
JP.add(attendance);
JP.add(JB);
add(JP);
pack();
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void buttonAction(){
UI UIbutton = new UI();
UIbutton.JB.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == UIbutton.JB) {
String nameInput = UIbutton.name.getText();
int idInt = Integer.parseInt(UIbutton.id.getText());
boolean attInput = UIbutton.attendance.isSelected();
Validate.nameChk(nameInput);
Validate.idChk(idInt);
Validate.attChk(attInput);
Student studentObj = new Student(UIbutton.name.getText(), idInt, UIbutton.attendance.isSelected());
System.out.println(studentObj.name + "'s ID number is : " + studentObj.id + ".");
System.out.println(studentObj.name + " is present: " + studentObj.attendance);
System.exit(0);
}}});
}
public static void main(String[] args) {
buttonAction();
}
}
Validate.java
public class Validate {
public static void nameChk (String nameInput) {
String n1 = "Matthew";
String n2 = "John";
String n3 = "Mark";
String n4 = "Luke";
if ((nameInput.equalsIgnoreCase(n1))||
(nameInput.equalsIgnoreCase(n2))||
(nameInput.equalsIgnoreCase(n3))||
(nameInput.equalsIgnoreCase(n4))){
System.out.println("Your data is okay.");
}
else {
System.out.println("Error, wrong student name.");
System.exit(0);
}
}
public static void idChk (int idInt) {
if (idInt > 4) {
System.out.println("Your id is not correct.");
System.exit(0);
}
else {
System.out.println("Your id is correct.");
}
}
public static void attChk (boolean attInput) {
if (attInput) {
System.out.println("The student is present.");
} else {
System.out.println("The student is absent.");
}
}
}
Student.java
public class Student {
String name;
int id;
boolean attendance;
Student(String name, int id, boolean attendance) {
this.name = name;
this.id = id;
this.attendance = attendance;
}
}
What I want to know is how can I reuse output of that actionlister method somewhere else. Let say I would create foo.java class and use that studentObj variable to give grades like
System.out.println(studentObj.name+"has B+.");
Sort of.
How can I do that? How to turn that variable into global?
This can be achieved in different ways.
Quite simple, but not a good practice would be to create a Singleton. It would contain Students objects and you'll be able to access them from anywhere. Here is example with eager singleton, but you can implement much better versions (check about singleton implementations i.e. here https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples)
public class StudentsSingleton {
private Map<Integer, Student> students = new HashMap<>();
public Student getStudent(int id) { return students.get(id);}
public void addStudent(Student s) { students.put(s.id, s);}
private static final StudentsSingleton instance = new StudentsSingleton();
//private constructor to avoid client applications to use constructor
private StudentsSingleton(){}
public static StudentsSingleton getInstance(){
return instance;
}
}
In that case, you can access it from anywhere by getting the instance :
StudentsSingleton.getInstance().getStudent(id);
A much better solution and a good practice would be to use some Dependency Injection framework i.e. Spring. In that case, you would create a Bean and inject it whenever it is needed to use.
So I have this class "Member" :
package pkgData;
import java.io.Serializable;
public class Member implements Comparable<Member>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private String city;
public Member(String nameOfMember,String location) {
super();
this.name = nameOfMember;
this.city=location;
}
public String getNameOfMember() {
return name;
}
public String getLocationOfMember() {
return city;
}
public void setNameOfMember(String nameOfMember) {
this.name = nameOfMember;
}
#Override
public String toString() {
return name +", " + city;
}
#Override
public int compareTo(Member o) {
int result =this.getNameOfMember().compareTo(o.getNameOfMember());
if(result==0){
result = this.getLocationOfMember().compareTo(o.getLocationOfMember());
}
return result;
}
}
And I have a JComboBox which is EDITABLE and the model of the ComboBox is DefaultComboBoxModel.
So the problem is that if I cast the selectedItem:
Member nameOfMember = (Member)memberModel.getSelectedItem();
if(nameOfMember== null)
throw new Exception("please select a name and a location");
It only checks if the entered string is empty. If I enter a string like "Name, Location" I always get the exception that String cannot be cast to Member. Which String to I have to enter that the String can be cast to Member?
Here is my JComboBox:
private JComboBox<Member> getComboBoxMember() {
if (comboBoxMember == null) {
comboBoxMember = new JComboBox<Member>();
comboBoxMember.setEditable(true);
comboBoxMember.setModel(memberModel);
}
return comboBoxMember;
}
and here the global variables:
private DefaultComboBoxModel<Member> memberModel;
private JComboBox<Member> comboBoxMember;
String nameOfMember = (String) memberModel
.getSelectedItem();if(nameOfMember==null)throw new Exception("please select a name and a location");else
{
String[] parts = nameOfMember.split(",");
String part1 = parts[0]; // name
String part2 = parts[1]; // location
Member member=new Member(part1, part2);
}
String split & cast method
What you can do is first of all test if the string you get is null, or if it matches well you format. Then, you can create a new object with these elements.
Here's a small example code :
String memberData = (String)memberModel.getSelectedItem();
if(memberData == null || memberData.split(", ")[0].isEmpty() || memberData.split(", ")[1].isEmpty()) {
throw new Exception("Data is incorrect, please provide name and location separated with ", ");
}
Member member = new Member(memberData.split(", ")[0], memberData.split(", ")[1]);
JComboBox method
With Java 7 happened a new possibility of extension to JComboBox, which can now be generically parameterized (as for ArrayLists) in the form JComboBox<Type>. Thus, the objects you can get with getSelectedItem() can now be casted to the generic type you gave in parameter to JComboBox. The only problem is that, when a JComboBox is edited, as in your case, the data is casted to a simple String.
What you can do in your listener method (I will use ActionListener) is the following :
class ItemAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
try {
//In case the user has not modified the object
Member member = (Member)box.getSelectedItem();
//Just an example here
if(member != null) {
System.out.println(member.toString());
}
} catch(ClassCastException ex) {
//In case the object has been modified
String data = (String)box.getSelectedItem();
//Apply first method here
}
}
}
But the problem with this method is that you end up using the first method still.
I have been think for somedays how to fix this but i need someone’s help.
I have a 2 tableviews and one is fill up with data. and if customer clicked on a row it gets it to other tableview. but the problem is with total price which supposed to dynamical add any item pick by a user.
I got this code and is perfect but I can’t seem to get the total to label and not in a row.
model
private final ReadOnlyObjectWrapper<Double> total = new ReadOnlyObjectWrapper<>();
public LineItemProperty(String name, Integer quantity, Double unitPrice) {
setName(name);
setQuantity(quantity);
setUnitPrice(unitPrice);
// Obvious binding for the total of this line item:
// total = quantity * unit price
total.bind(Bindings.createObjectBinding(new Callable<Double>() {
#Override
public Double call() throws Exception {
if (quantityProperty().get() == null || unitPriceProperty().get() == null) {
return 0.0;
}else{
return quantityProperty().get() * unitPriceProperty().get();
}
}
}, quantityProperty(), unitPriceProperty()));
}
in view
table.getColumns().add(column("Total Price", LineItemProperty::totalProperty, false, null));
final Label selected = new Label("Total");
another class for total
public class LineItemListWithTotal extends TransformationList<LineItemProperty, LineItemProperty>{
private final TotalLine totalLine;
public LineItemListWithTotal(
ObservableList<? extends LineItemProperty> source) {
super(source);
totalLine = new TotalLine(source);
}
#Override
protected void sourceChanged(ListChangeListener.Change<? extends LineItemProperty> c) {
// no need to modify change:
// indexes generated by the source list will match indexes in this
// list
fireChange(c);
}
Thanx a lot. any idea will help and appreciated
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
So I am very new to Java... been at it for about 4 weeks... be gentle.
I am trying to get my takeItem method (below) to pass the itemName variable back to my Player Class so I can add an item from my current room to my player. I get the compiler error: Constructor Item in class Item cannot be applied to given types..
my end goal is to get the player class to hold the object after removing it from the room.
takeItem Method:
private void takeItem(Command command)
{
if(!command.hasSecondWord()) {
// if there is no second word, we don't know where to go...
System.out.println("Take what?");
System.out.println();
return;
}
String itemName = command.getSecondWord();
Item theItem;
// Try to take an item.
theItem = new Item(player.getCurrentRoom().removeItem(itemName));
if (theItem == null)
{
System.out.println("There is no item!");
}
else
{
player.addItem(theItem);
player.getItemsCarried();//print item info
}
Player Class:
//above code omitted//
public void setCurrentRoom(Room room)
{
currentRoom = room;
}
public Room getCurrentRoom()
{
return currentRoom;
}
//code below omitted//
public void addItem (Item thingy)
{
items.put(thingy.getName(), thingy);
}
//code below omitted//
Item Class:
public class Item
{
// instance variables - replace the example below with your own
private String name;
private String description;
private int weight;
/**
* Constructor for objects of class Item
*/
public Item(String n, String d, int w)
{
name = n;
description = d;
weight = w;
}
//code below omitted//
Room Class:
public class Room
{
private String description;
private HashMap <String, Room> exits;
private HashMap <String, Item> items;
//some code below omitted//
public Room (String description)
{
this.description = description;
exits = new HashMap<>();
items = new HashMap<>();
}
public void addItem (Item thingy)
{
items.put(thingy.getName(), thingy);
}
public String removeItem(String thingy)
{
items.remove(thingy);
return thingy;
}
//code below omitted
Your constructor in the Item class takes two String parameters and one int, but you are trying to create a new Item by passing in only one String (whatever is returned by the removeItem() method). You can either change the removeItem() method so that it returns the Item that is removed, in which case you should change
theItem = new Item(player.getCurrentRoom().removeItem(itemName));
to
theItem = player.getCurrentRoom().removeItem(itemName);
or you can create a new Item with the necessary parameters.
This question already has answers here:
Java time-based map/cache with expiring keys [closed]
(8 answers)
Closed 8 years ago.
I have a defined a class to manage the game room. When a user creates a new room, I generate a new room with unique room number and add it to the hashset.
Now ,I hope to remove that Room object from the hashset and recycle the Room object for perfarmance issue, say 24 hours , or the abandoned Room object will spend most of my mememory
How can I achieve this? Also, any suggestion to improve the performance will be highly appreciated.
My class is as follows:
public class RoomService {
private RoomService(){
super();
}
private HashSet<Room> roomSet =new HashSet<Room>();
private static RoomService instance =new RoomService();
public static RoomService getServiceInstance(){
return instance;
}
private static Integer generateRandom(int length) {
Random random = new Random();
char[] digits = new char[length];
digits[0] = (char) (random.nextInt(9) + '1');
for (int i = 1; i < length; i++) {
digits[i] = (char) (random.nextInt(10) + '0');
}
return Integer.decode(new String(digits));
}
/**
* Generate new Room with an unique Room number
* #return
*/
public Room newRoom(){
Room newRoom;
do{
newRoom =new Room(generateRandom(4));
}
while(!roomSet.add(newRoom));
return newRoom;
}}
public class Room {
private Integer roomNum;
private Date createTime=new Date();
private String creatorId;
/*
* constructor
*/
public Room(Integer roomNum) {
super();
this.roomNum = roomNum;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((roomNum == null) ? 0 : roomNum.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Room other = (Room) obj;
if (roomNum == null) {
if (other.roomNum != null)
return false;
} else if (!roomNum.equals(other.roomNum))
return false;
return true;
}
//getter and setter
//
//
public String getCreatorId() {
return creatorId;
}
public void setcreatorId(String creatorId) {
this.creatorId = creatorId;
}
public Integer getRoomNum() {
return roomNum;
}
public Date getCreateTime() {
return createTime;
}
}
You can do this yourself by using a Timer. Every time somebody creates a new room you create a new TimerTask instance that will delete the id again and schedule that task to be executed using public void schedule(TimerTask task, Date time). It could look something like this:
private final Timer timer; // Initialised somewhere
public Integer newRoomNum() {
Integer newRoomNum = ... // Create id
Date date = ... // Create date when the id should be deleted again
timer.schedule(new DeleteKeyTask(newRoomNum), date);
return newRoomNum;
}
Where DeleteKeyTask is a custom subclass of TimerTask that deletes the given id.
private class DeleteKeyTask extends TimerTask {
private final Integer id;
public DeleteKeyTask(Integer id) {
this.id = id;
}
#Override
public void run() {
// remove id
}
You could use different approaches to save space:
Instead of having a task per key, you can store the date along side the integer key. For example you can use a HashMap<Integer, Date> (or store milliseconds instead of date). The keys of the map form your previous set. The values indicate the time the key was inserted or expires.
You can then schedule the timer to remove the next expiring key, at that time you look for the next expiring key and schedule to remove that etc. This will cost you O(n) time to compute the next expiring key. Your run method for the task would look something like
public void run() {
map.remove(id);
Integer next = ... // Find next expiring key
timer.schedule(new DeleteKeyTask(next), map.get(next));
}
And you would need to adapt the creation method:
public Integer create() { // Previously newRoomNum()
Integer newRoomNum = ... // Create id
Date date = ... // Create date when the id should be deleted again
if(map.isEmpty()) // Only schedule when empty
timer.schedule(new DeleteKeyTask(newRoomNum), date);
map.put(newRoomNum, date);
return newRoomNum;
}
This way you will just need to store a date per integer. If the O(n) overhead is too much for you when calculating the next, you can make it faster by using more space: use a Queue and insert new keys. The queue will allow you to retrieve the next expiring key, making looking up the next expiring key O(1).