JavaFX reference a master array list - java

I am writing a mock hotel reservation system with two menus, employee and guest. Created rooms are stored in a master array called roomArray and added to a list view in the employee menu, and added to a list view in the guest menu. Rooms can be available or booked, however only available rooms are shown in the guest menu list view, so I might have 5 rooms but only 2 show in the guest menu list view. If the user clicks on the second one, I don't want to try and book the index 1 room in the main roomArray static ArrayList because they don’t match up.
For example, say in the employee list view I have three rooms, two of which are booked. In the guest list view, only the available rooms show up. So the list view on the right would show a selected index of 0, but the same index in the master roomArray is 1 for that same room. How can I make an intermediary of array list of available rooms that reference rooms in the master list?
Nathan

Since you are using JavaFX, you should use ObservableList for your rooms. Additionally, you would need to use FilteredList and FXCollections.observableArrayList(extractor).
This is how you can implement it:
public class Room {
public enum State {AVAILABLE, BOOKED}
private final ObjectProperty<State> state = new SimpleObjectProperty<>(AVAILABLE);
public final ObjectProperty<State> stateProperty() { return state; }
public final State getState() { return state.get(); }
public final void setState(final State value) { state.set(state); }
}
Main class:
private final ObservableList<Room> rooms;
public final ObservableList<Room> getRooms() { return rooms; }
private final ObservableList<Room> guestRooms;
public final ObservableList<Room> getGuestRooms() { return guestRooms; }
// Constructor
public MyClass() {
rooms = FXCollections.observableArrayList(room -> new Observable[] {room.stateProperty()});
guestRooms = rooms.filtered(room -> room.getState() == Room.State.AVAILABLE);
}
The guestRooms list is just a wrapper for rooms list, filtered with a Predicate. The filtered list will change according to the rooms list, but it will only react to changes to the list itself (add, remove, replace of elements). To make sure it responds to changes of the state of existing rooms, you need to use FXCollections.observableArrayList(extractor) overload. This overload allows you to control which property in each Room object would also trigger a ListChangeListener.Change, which would also causes the filtered list to update itself.

Related

getting the holder of an arrayList

I have a Course class which has a method to add Items, which can be a note, an assignment, a URL, or just a generic item. All Items are kept in an ArrayList which the Course that created the list keeps up with. My question is from an item inside this ArrayList, how do I get the printLogger that I have attached to the course object in order to attach it to an item when the Item is created?
this from my Course:
public class Course {
private ArrayList<Item> items;
public PrintLogger p1 = null;
public Course(String code, String name) {
this.code = code;
this.name = name;
items = new ArrayList<>();
}
void add(Item item) {
items.add(item);
if (hasPrintLogger() == true) {
log(PrintLogger.INFORMATIONAL, "Adding " + item.toString());
}
}
And Im trying to have in the code that the assignment constructor runs a way to attach the same printLogger that is already on the course.
You could store a reference to the proper Course object in each of the items in the List.
You could also wrap the ArrayList class in your own class and add a field that points to the Course it belongs to if you need it to be a relationship between the List and the Course instead of between the items in the List and the Course.
You could also search each Course object in your system and check if it contains the List in question. However, this solution would scale badly.

Sort ArrayList of Objects by Specific Element

I have several arraylists which each contain player data for a specific team. Each object contains the following elements in order; Jersey Number, First Name, Last Name, Preferred Position, Goals, Assists. The user decides whether to view the data by goals or assists, and then the data is displayed in descending order. Goals and assists are both of int data type.
I will be able to display the data fine but what I am stuck on is how to sort the arrayList by one of these specific stats. Because the data from all the teams is in different arrayLists, and need to be sorted all together, do I need to combine the arrayLists into one master arrayList that will be sorted? As for the sorting, I have done a bit of research and it looks like I need to use a comparator? Could someone provide some assistance with this because I have never used these before and am quite lost. Examples would be great.
I have attached a few code snippets to hopefully provide some clarity.
ArrayList <blackTeam> blackTeam = new ArrayList <blackTeam>();
ArrayList <blueTeam> blueTeam = new ArrayList <blueTeam>();
ArrayList <greenTeam> greenTeam = new ArrayList <greenTeam>();
ArrayList <orangeTeam> orangeTeam = new ArrayList <orangeTeam>();
ArrayList <redTeam> redTeam = new ArrayList <redTeam>();
ArrayList <yellowTeam> yellowTeam = new ArrayList <yellowTeam>();
private void displaystatButtonActionPerformed(java.awt.event.ActionEvent evt) {
//sort arrayList by goals/assists
}
EDIT:
This is how my classes are set up, as well as how data is added to them. Hopefully this clears up some questions.
//add data to database
black = new blackTeam(jerseyNum, firstName, lastName, prefPosition, goals, assists);
blackTeam.add(black);
class blackTeam {
int goals, assists;
String jerseyNum, firstName, lastName, prefPosition;
blackTeam (String _jerseyNum, String _firstName, String _lastName, String _prefPosition, int _goals, int _assists) {
jerseyNum = _jerseyNum;
firstName = _firstName;
lastName = _lastName;
prefPosition = _prefPosition;
goals = _goals;
assists = _assists;
}
}
I have one these classes for each team.
I suggest using Comparator on your object, let me assume it is Team
public class Team{
private int jerseyNumber;
private String lastName;
...
public int getJerseyNumber(){
return jerseyNumber;
}
}
If you want to sort based on jersey number, generate JeseryNumberComaparator:
import java.util.Comparator;
public class JeseryNumberComaparator implements Comparator {
#Override
public int compare(Team t1, Team t2) {
// descending order (ascending order would be:
// t1.getJerseyNumber()-t2.getJerseyNumber())
return t1.getJerseyNumber()-t2.getJerseyNumber()
}
}
It will sort your list based on jersey number by:
Collections.sort(blackTeam, new JerseyNumberComparator());
For sorting Collection in Descending order (other than their natural sort order), you have to define your own Comparator.
For sorting on a specific field individually (one at a time), you have to define separate Comparator implementation.
In your class, you can define two individual Comparators. Here is example code.
static final Comparator<Team> SORT_TEAM_BY_GOALS_DESCENDING = new Comparator<Team>(){
public int compare(Team t1, Team t2){
return t2.getGoals() - t1.getGoals();
}
}
static final Comparator<Team> SORT_TEAM_BY_ASSIST_DESCENDING = new Comparator<Team>(){
public int compare(Team t1, Team t2){
return t2.getAssist() - t1.getAssist();
}
}
Make sure that, normal sort is always natural order, in your case for int it is always Ascending. In order to have Descending order, you need to do t2 - t1. t1 - t2 will give you natural Ascending order.
Now in order to use this Comparator, just use following code.
Collections.sort(team, SORT_TEAM_BY_GOALS_DESCENDING);
or
Collections.sort(team, SORT_TEAM_BY_ASSIST_DESCENDING);
And off course, if all these different color List (i.e. blackTeam and so on) are only for specific team identified by color, than add one more field to your Team class called 'color` which will identify each player along with what team they belongs to.
As long as your 6 classes blackTeam to yellowTeam all descend from the same parent, ie. that they are declared like this:
public class blackTeam extends Team { ... }
then you can make a new ArrayList<Team> and add them all to it:
ArrayList<Team> all = new ArrayList<>();
all.addAll(blackTeam);
all.addAll(blueTeam);
all.addAll(yellowTeam);
// etc...
Then you can sort this list using an instance of Comparator<Team>. Since Java8, however, there's a much neater way to create a comparator using lambda expressions:
all.sort((a, b) -> a.getScore() - b.getScore()); // or whatever attribute you want to compare on
If you want to do it the old fashioned way instead, then you can create an anonymous class like this:
all.sort(new Comparator<Team>() {
#Override
public int compare(Team a, Team b) {
return a.getScore() - b.getScore();
}
});
They amount to the same thing, but the lambda based approach is a bit less wordy!
Note that i suspect you don't actually want to have 6 different classes for the different colours. Are you sure you have understood the role of a class properly?

How do I keep two pieces of information in a LinkedList node?

As per requested by my instructor, we were asked to write a Surgery Room booking program as an assignment. He gave us the following breakdown:
A hospital contains a list (LinkedList) of rooms.
Each room contains a name (I set mine as a room number int) and a list (LinkedList) of bookings.
Each list (LinkedList) of bookings contains a start and end time (I set mines as Date) and a team (another LinkedList).
I've set my GUI and I have an idea of how to construct the methods, I'm just finding it difficult to start since I cannot place two pieces of information in one node (like, putting a name and a list of bookings for a particular room).
If it helps, I have a fully implemented:
LinkedList<T> extends AbstractSequentialList<T> implements List<T>, Deque<T>, Cloneable, Serializable
He gave us most of the code, but although it is mostly complete I'm still a little clueless.
Does anyone have any insight on how to deal with the LinkedList issue? Thanks!
Create a POJO, a class with two fields, and make your LinkedList of that POJO type. For example,
public class Room {
private final int number;
private final List<Bookings> bookings = new LinkedList<>();
public Room(int number) {
this.number = number;
}
public int getNumber() {
return this.number;
}
public List<Bookings> getBookings() {
return bookings;
}
}
And then, you can have a
List<Room> rooms = new LinkedList<>();
Above, creating Bookings with start and end Dates left as an exercise for the reader.

Delete/Add a specific Element(int) in an Array

This subclass should be able to let the user choose a specific employee ID, type it into the command line and choose to either add it to the array list, delete it from the array list or simply request to see more information about the specific employee ID. I've tried so many things with no luck at all.
package WorkIDServerStorage;
public class EmployeeList{
private Employee[] theEmployee;
private int arrayEmployee;
public EmployeeList(){
theEmployee = new Employee[100];
arrayEmployee = 0;
}
public EmployeeList(int arraySize){
theEmployee = new Employee[arraySize];
arrayEmployee = 0;
}
public void setTheEmployee(Employee[] inputTheEmployee){
theEmployee = inputTheEmployee;
}
public void setArrayEmployee(int inputArrayEmployee){
arrayEmployee = inputArrayEmployee;
}
public Employee[] getTheEmployee(){
return theEmployee;
}
public int getArrayEmployee(){
return arrayEmployee;
}
public Employee addEmployeeID(Employee employeeAdd){
return theEmployee[arrayEmployee++] = employeeAdd;
}
public Employee deleteEmployeeID(int employeeDelete){
//Delete an employee record with a
//specified record number from the array
}
public Employee readEmployeeInfo(int employeeRead){
//Read the employee data for a specified record number
//From the array and display this data to the screen
}
#Override
public String toString(){
StringBuilder sb = new StringBuilder();
for(int x = 0; x < arrayEmployee; x++){
sb.append(theEmployee[x].toString()).append("\n");
}return sb.toString();
}
}
Arrays are fixed length data structures. They are much like a multi-storied building. You can't take a floor out from the middle of the building and expect it to stand.
ArrayList (as others have pointed out), are dynamic structures, much like a train. You can take out compartments as you wish, you can reconfigure it.
I would in fact recommend NOT using a List at all, but a Map that maps an ID to an employee record. Let us say you have the following employees in a list -
Alice
Bob
John
Ruth
If you delete "Bob" the ID's for John and Ruth are going to change. Not a good practice. If you use a Map instead, everyone can keep their assigned ID's and you just add to the map by incrementing the keys (or IDs).
Hope this helps.
For being able to dynamically adding or removing from an array, you should use List, or ArrayList. Typical arrays don't provide delete or add at runtime, since they are fixed-size and if you want to control the procedure by handling the indices or other tricks, you'll probably end up in a messy and hard to maintain code.
On the other hand, Lists in java are dynamically sized and provide add(), remove(), get() and other convenient methods, which in my opinion best suits you.
You should use an ArrayList in order to dynamically add and remove entries in your array.
Make your theEmployee array into an ArrayList by doing:
ArrayList<Employee> theEmployee = new ArrayList<Employee>();
You can add and remove by doing:
public boolean addEmployeeID(Employee employeeAdd){
return theEmployee.add(employeeAdd);
}
public Employee deleteEmployeeID(int employeeDelete){
return theEmployee.remove(employeeDelete)
}
I changed the return type of addEmployeeID to boolean because an ArrayList returns a boolean when you add an object.
For remove, int employeeDelete would be the index of the object in the array. When you remove an object, all the remaining objects get shifted to the left. So if you have an array [1,2,3] and you remove 2, it would become [1,3]. The indexes are moved.
You could also remove an object so this should work:
public boolean deleteEmployeeID(Employee employeeDelete){
return theEmployee.remove(employeeDelete)
}
Where employeeDelete is an Employee and the function returns a boolean.

How do I add two ArrayLists of different classes that extend an abstract class into one ArrayList?

So I have the two following arraylists:
private List<Manager> _managers = new ArrayList<Manager>(); //Manager extends User
private List<Employee> _employees = new ArrayList<Employee>(); //Employee extends User
I want to have an arraylist that combines both of these, storing all users, both employees and managers.
Currently I am trying the following solution:
private List<User> _usrs = new ArrayList<User>();
/*
* function that I use before I get the current user list, preventing getting a outdated version of it
*/
public void refreshUserList() {
this._usrs.clear(); //prevent duplicates
this._usrs.addAll(_employees); //add all employees to user list
this._usrs.addAll(_managers); //add all managers to user list
}
Is this a good way to solve this problem?
I'm having some nullPointer iterator issues when iterating this list and before I get into solving this issue, I'd like to know if the problem isn't right here. Thanks.
Assuming that the Employee and the Manager classes both extend the User class, then yes, this is a good solution. If you want to prevent duplicates, however, you can use a Set:
private Set<User> _usrs = new HashSet<>();
/*
* function that I use before I get the current user set, preventing getting a outdated version of it
*/
public void refreshUserList() {
this._usrs.addAll(_employees); //add all employees to user set
this._usrs.addAll(_managers); //add all managers to user set
}
You don't need to call clear();, since Sets do not add duplicate elements.
This way, you will lose the special variables/methods that appear only for Managers or Employees, since all you will have will be the variables/methods available for Users. However, if you cast each User instance of your _usrs Set to Manager or Employee, then you can still get those special elements/methods:
for (User user : _usrs) {
if (user instanceof Manager) {
Manager mng = (Manager) user;
mng.manage(); // or whatever managers do that employees don't
} else { //if no other classes extend the User class
Employee emp = (Employee) user;
emp.work(); // or whatever employees do that managers don't :P
}
}
You could use a Set instead of a List which would solve your duplicate problem, as for the iterator issue you'd have to add more information about where it's happening.
I am guessing that your Manager and Employee classes are extending/ implementing your User class, Only then you will be able to combine the two arraylists.
If you want to prevent duplicates, use a Set, if you also want to maintain the order, use a LinkedHashSet.
private LinkedHashSet<User> _usrs = new LinkedHashSet<User>();
public void refreshUserList() {
usrs.clear(); //prevent duplicates
usrs.addAll(_employees); //add all employees to user list
usrs.addAll(_managers); //add all managers to user list
}

Categories

Resources