Using arrayList pointers instead of multiple loops? - java

I am trying to write a program that contains many classes and in one class called "Dorm",I have an arrayList of Blocks,and in the "Block" class,I have an arrayList of Rooms,and in the "Room" class,I have an arrayList of "Students".
I am trying to access the number of available rooms(the rooms that at least have one empty space) through another class called the "Manager class". I have been told that I can just create another arrayList in the manager class to be used as a pointer and search up the empty rooms of the whole dormitory.
My question is,how is this going to work?
ps:This is what I wrote:
public static void availableRooms() { //Shows the available rooms in the dormitory.
Dorms dormitory = new Dorms();
Room room1 = new Room();
for(int i=0;i<dormitory.getBlocks().size();i++)
for(int j=0;j<Block.getRoomList().size();j++) {
if(!(room1.getStudentList().get(room1.getRoomCapacity()).equals(null)))
System.out.print("/t" + room1.getStudentList().get(i) + "/t");
}
}
My code isn't complete yet,so I'm not sure if it works...

Could you share your code/tentative? and clearly specify what's not working?
This being said, unless tied to specific constraints, one should make use of encapsulation and single responsibility principle (see SOLID on wiki) by keeping implementation details private and delegating tasks to the more relevant classes.
You may have something like:
class Dorm {
private List<Block> blocks = ...
...
public int getAvailableRooms() {
int total = 0;
for (Block b : blocks) {
total += b.getAvailableRooms();
}
return total;
}
}
class Block {
private List<Room> rooms = ....
...
public int getAvailableRooms() {
int total = 0;
for (Room r : rooms) {
if (! r.isFull()) {
total++;
}
}
}
class Room {
private int capacity = ...
private List<Student> students = ..
...
public boolean isFull() {
return capacity == students.size();
}
}
Where the Manager class, holding (an) instance(s) of Dorm, just make use of the getAvailableRooms() method which behind the scene delegate to the underlining Blocks and aggregate result... and so on.

Related

Fundamental misunderstanding of objects and attributes in Java

I'm sitting on an assignment for university and I'm at a point, where I fear I haven't really understood something fundamental in the concecpt of Java or OOP altogether. I'll try to make it as short as possible (maybe it's sufficient to just look at the 3rd code segment, but I just wanted to make sure, I included enough detail). I am to write a little employee management. One class within this project is the employeeManagement itself and this class should possess a method for sorting employees by first letter via bubblesort.
I have written 3 classes for this: The first one is "Employee", which contains a name and an ID (a running number) , getter and setter methods and one method for checking whether the first letter of one employee is smaller (lower in the alphabet) than the other. It looks like this:
static boolean isSmaller(Employee source, Employee target) {
char[] sourceArray = new char[source.name.length()];
char[] targetArray = new char[target.name.length()];
sourceArray = source.name.toCharArray();
targetArray = target.name.toCharArray();
if(sourceArray[0] < targetArray[0])
return true;
else
return false;
}
I tested it and it seems to work for my case. Now there's another class called EmployeeList and it manages the employees via an array of employees ("Employee" objects). The size of this array is determined via constructor. My code looks like this:
public class EmployeeList {
/*attributes*/
private int size;
private Employee[] employeeArray;
/* constructor */
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
}
/* methods */
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
/* adds employee to end of the list. Returns false, if list is too small */
boolean add(Employee m) {
int id = m.getID();
if (id > employeeArray.length) {
return false;
} else {
employeeArray[id] = m;
return true;
}
}
/* returns employee at certain position */
Employee get(int index) {
return employeeArray[index];
}
/* Sets employee at certain position. Returns null, if position doesn't exist. Else returns old value. */
Employee set(int index, Employee m) {
if (employeeArray[index] == null) {
return null;
} else {
Employee before = employeeArray[index];
employeeArray[index] = m;
return before;
}
}
Now comes my real problem: In a third class called "employeeManagement" I am supposed to implement the sorting algorithm. The class looks like this:
public class EmployeeManagement {
private EmployeeList ml = new EmployeeList(3);
public boolean addEmployee(Employee e) {
return ml.add(e);
}
public void sortEmployee() {
System.out.println(ml.getSize()); // I wrote this for debugging, exactly here lies my problem
for (int n = ml.getSize(); n > 1; n--) {
for (int i = 0; i < n - 1; i++) {
if (Employee.isSmaller(ml.get(i), ml.get(i + 1)) == false) {
Employee old = ml.set(i, ml.get(i + 1));
ml.set(i+1, old);
}
}
}
}
The "println" before my comment returns "0" in console... I am expecting "3" as this is the size I gave the "EmployeeList" as parameter of the constructor within my "EmployeeManagement" class. Where is my mistake ? And how can I access the size of the object I created in the "EmployeeManagement" class (the "3") ? I'm really looking forward to your answers!
Thanks,
Phreneticus
You are not storing size in your constructor. Something like,
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
this.size = size; // <-- add this.
}
Also, setSize isn't going to automatically copy (and grow) the array. You will need to copy the array, because Java arrays have a fixed length. Finally, you don't really need size here since employeeArray has a length.
The size variable you are calling is the class field. If you take a quick look at your code, the getter is getting the field (which is initialized as zero when created). The size you are using it. The good way of doing it would be to get the size of the array in the getter like this:
public int getSize() {
return employeeArray.length;
}
This would return the size of the array in the object.

How to create my own collection?

So lets say I have a class BaseballCard that creates a baseball card.
Now I need to make another class which would be my collection class.
For example I would call it BaseballCardCollection
and then I want to create methods like
size (which returns the numbers of cards in the collection)
addCard(adds a baseball object to the collection object)
removeCard (removes a baseball card)
and so on
What would be the best way to do this. I tried doing this
public CardCollectionList() {
BaseballCard[] baseballCardList = new BaseballCard[101];
}
So each object is insinuated with an array of type BaseballCard of size 100.
And then for example the size method I tried something like this
public int size(){
int size = 0;
for(int i = 1; i<this.baseballCardList.length; i++)
if (baseballCardList!= null)
size+=1;
}
But it doesn't work because "baseballCardList cannot be resolved to a variable"
You could try using ArrayLists - http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html:
ArrayList<baseballCard> baseballCardList = new ArrayList<baseballCard>(0);
public boolean addCard(baseballCard card){
return baseballCardList.add(card);
}
public boolean removeCard(int card){
return baseballCardList.remove(card);
}
public baseballCard getCard(int card){
return baseballCardList.get(card);
}
public int sizeBaseballCardList(){
return baseballCardList.size();
}
public ArrayList<baseballCard> getBaseballCardList(){
return baseballCardList;
}
Move the variable BaseballCard[] baseballCardList outside the constructor, make it a field in your class. Do similar with size.
This is how the class should look like:
public class CardCollectionList {
//fields
private BaseballCard[] baseballCardList;
private int size;
//constructor
public CardCollectionList() {
baseballCardList = new BaseballCard[101];
}
//method
public int getSize() {
return this.size;
}
}
You could try creating your own class implementing the Collection interface and define your own methods + implement Collection methods:
public class myContainer implements Collection <BaseballCard> {
}
You need to move the variable declaration from the constructor to the class, so you can access it in other methods, too.
class CardCollectionList {
BaseballCard[] baseballCardList;
public CardCollectionList() {
baseballCardList = new BaseballCard[101];
}
public int size(){
int size = 0;
for(int i = 1; i<this.baseballCardList.length; i++) {
if (baseballCardList[i] != null) {
size+=1;
}
}
return size;
}
}
The code is as close to your fragment as possible. There are several ways to improve this (keep track of the size when adding, automatic array reallocation etc.). But it is a start if you want to try this yourself.
Normally, you'd probably just use ArrayList<BaseballCard>.
Now I need to make another class which would be my collection class.
... What would be the best way to do this.
I don't have enough reputation to comment on your question, so I am going to assume that you just want to store BaseballCard objects in a Java Collection. The Java SDK offers a lot of options. Since you are asking about the "best" way to go then I would use one of those unless you need to add additional functionality .
if you don't find what you need from the Java SDK or just want to create your own Collection then follow the advice given by #michał-szydłowski above

Error: Constructor Room in class Room cannot be applied to given types

I am completely new to java. I have searched for hours upon hours for the solution to this problem but every answer involves passing args or using a void which I do not do in this situation.
I have two java files, one for Room class, and one for TourHouse class. I am trying to create a new Room in the TourHouse class. Here is my error, it's driving me nuts, I've tried everything I am capable of understanding. Thank you in advance.
HouseTour.java:15: error: constructor Room in class Room cannot be applied to given
types;
{
^
required: String, String
found: no arguments
reason: actual and formal arguments differ in length
Here is the Room class, will have 7 rooms total once I can figure this out
// Room.java
import java.util.*;
public class Room
{
// Define Instance Variables
private String name;
private String description;
// Define Constructor
public Room(String theName, String theDescription)
{
name = theName;
description = theDescription;
}
public String toString( )
{
return "The " + name + "\n" + description + "\n";
}
}
Here is the HouseTour class
import java.util.*;
public class HouseTour extends Room
{
// Define Variables
public Room[ ] rooms = new Room[7];
//Define Constructor
public HouseTour( )
{
rooms[0] = new Room("Living Room", "Mayonnaise and Brill Grates, Michaelsoft");
rooms[1] = new Room("Basement", "Hopefully no dead bodies down here...");
}
// this is horrible and not right
public String rooms( )
{
for (int i = 0; i <=7; i++)
{
String output = "House Rooms included in tour\n";
String output2 = output + rooms.toString() + "\n";
return output2;
}
}
}
EDIT: Solved but still need help here because I am complete n00b, :(
// this is horrible and not right
public String rooms( )
{
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
output += rooms[i]; // I can't do this but how do i?
}
return output.toString(); // do I do this?
}
}
What I am doing is trying to learn java by converting the ruby projects I have created. So in ruby you say:
def rooms
output = "House Rooms included in tour\n"
#rooms.each do |r|
output += r.to_s + "\n"
end
return output
end
Edit: Still trying, any ideas?
added public String s; and public String output; to declarations
// this is horrible and not right
public String rooms( )
{
s = ""
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
s += rooms[i];
}
s.toString() // I don't know
return output + s; // do I do this?
}
}
Edit: Solved thanks to Hovercraft Full Of Eels
Ah, I see your problem: HouseTour extends Room. Don't do this! HouseTour is not a more specific case of a Room type and so should not extend this class. It does not fulfill the "is-a" rule, and would be similar to trying to define Bus as a child class of SchoolKid. Just like a Bus isn't a type of SchoolKid but rather contains SchoolKids, a HouseTour isn't a Room but rather contains Rooms. It fulfills the has-a relationship, not the is-a relationship.
If the inheritance were proper in this situation, your HouseTour constructor would need to call the Room super constructor and pass in two String parameters:
// Don't do this!!!
public class HouseTour extends Room {
public HouseTour() {
super("foo", "bar");
....
}
But having said that, again inheritance is not proper here -- just get rid of extends Room, and you're home free.
e.g.,
public class HouseTour { // no extends!
private Room[] rooms; // has-a not is-a
public HouseTour() {
// don't call super here
}
Also, as per my comment, this will give you ugly output: rooms.toString()
Instead iterate through the Array and get the toString() result from each Room item in the array.
Edit
Suggestions on your rooms() method:
Create a String or StringBuilder before the loop.
Build up the String or StringBuilder inside the loop.
Return the String or StringBuilder#toString after the loop.
Inside of the loop get the toString() from the current Room item in the list.
You will need to check that the rooms[i] item isn't null before calling a method on it.
Edit 2
You state that this:
public String rooms( )
{
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
output += rooms[i]; // I can't do this but how do i?
}
return output.toString(); // do I do this?
}
is causing problems, but you don't specify the problem.
Myself, I'd do something like:
public String rooms( ) {
// declare your String locally, not globally in the class
String output = "House Rooms included in tour\n";
// again, avoid using "magic" numbers like 7
for (int i = 0; i < rooms.length; i++) {
output += rooms[i].toString(); // **** you must extract Room's String
}
return output; // no need to call toString() on a String
}

Java Inheritance - Getting a Parameter from Parent Class

I'm trying to take one parameter from the parent class of Car and add it to my array (carsParked), how can i do this?
Parent Class
public class Car
{
protected String regNo; //Car registration number
protected String owner; //Name of the owner
protected String carColor;
/** Creates a Car object
* #param rNo - registration number
* #param own - name of the owner
**/
public Car (String rNo, String own, String carColour)
{
regNo = rNo;
owner = own;
carColor = carColour;
}
/** #return The car registration number
**/
public String getRegNo()
{
return regNo;
}
/** #return A String representation of the car details
**/
public String getAsString()
{
return "Car: " + regNo + "\nColor: " + carColor;
}
public String getColor()
{
return carColor;
}
}
Child Class
public class Carpark extends Car
{
private String location; // Location of the Car Park
private int capacity; // Capacity of the Car Park - how many cars it can hold
private int carsIn; // Number of cars currently in the Car Park
private String[] carsParked;
/** Constructor for Carparks
* #param loc - the Location of the Carpark
* #param cap - the Capacity of the Carpark
*/
public Carpark (String locations, int room)
{
location = locations;
capacity = room;
}
/** Records entry of a car into the car park */
public void driveIn()
{
carsIn = carsIn + 1;
}
/** Records the departure of a car from the car park */
public void driveOut()
{
carsIn = carsIn - 1;
}
/** Returns a String representation of information about the carpark */
public String getAsString()
{
return location + "\nCapacity: " + capacity +
" Currently parked: " + carsIn +
"\n*************************\n";
}
}
Last Question Method
public String getCarsByColor (String carColour)
{
for (int num = 0; num < carsParked.length; num++)
{
if ( carColour.equals(carsParked[num]) )
{
System.out.print (carsParked[num]);
}
}
return carColour;
}
I have this so far so that if "red" is put in the parameters, it would list all the cars with the color red and it's corresponding information but does not seem to work ~_~.
You seem to have the wrong relationship here: a car park is not a car. I would recommend against using inheritance in either direction between these classes. And Carpark should probably just have an array or collection of cars.
Also note that the parameter carsIn isn't necessary - just get the length of the array of cars (or size() if it's a Collection).
Edit: Okay, ignoring the inheritance part, it seems like it makes sense to add cars when driveIn is called, and remove them when driveOut is called.
driveIn should probably take a Car as an argument, so the method can access the parameter you want to store (personally I would just store Car references, but fine). Since we're going to be adding and removing these parameters, it'll be much easier to use a List that can resize itself instead of an array, like ArrayList. For example:
private final List<String> carsRegNosParked = new ArrayList<String>();
public void driveIn(Car car) {
carsRegNosParked.add(car.getRegNo());
}
It's less clear what driveOut should do. It could take a specific registration number to remove:
public void driveOut(String regNo) {
carsRegNosParked.remove(regNo);
}
Or it could just indiscriminately remove a car, say the first car added:
public void driveOut() {
if (!carsRegNosParked.isEmpty()) {
carsRegNosParked.remove(0);
}
}
Note the difference between remove(Object) and remove(int).
First change carsParked to a list. So:
private String[] carsParked;
becomes
private List<String> carsParked;
Then in you constructor initialize it to an empty list by doing:
carsParked = new ArrayList();
Then in your drive in method, make it take a car parameter and pull the param you want:
public void driveIn(Car car) {
carsParked.add(car.getRegNo());
}
Also you do not need to keep track of the number of cars this way. Since you could always do carsParked.size() to find out.
Now I would probably change that list to be List<Car> instead of string and just dump the whole car in there. Sure you may only need one item right now, but who knows down the road, maybe you will need something else.
EDIT:
Sure you could do it with an simple array. The issue with that is sizing. Say you initially create an array of size 5, when you go to add the 6 item you will need to create a new larger array, copy the original data, then add the new item. Just more work. Now if the idea is you have a carpark, and it can have X number of spots then you initilize your array to that size from the begining.
public Carpark (String locations, int room){
location = locations;
capacity = room;
//this creates an array with the max number of spots
carsParked = new String[capacity];
//also good idea to init
carsIn = 0; //initial number of cars parked
}
then in your driveIn() method:
public void driveIn(Car car) {
carsParked[carsIn] =car.getRegNo();
carsIn=carsIn+1;
}
now driveOut()
public void driveOut(Car car) {
//loop through the array until we find the car
for (int i=0; i < carsParked.length; i=i+1){
if (car.getRegNo().equals(carsParked[i])){
//we found the car, so set the space null
carsParked[i] = null;
carsIn=carsIn-1;
//stop looping now
break;
}
}
}
Looks nice doesn't it. Well no it is not. Now the driveIn will not work, since we have null spots scattered all over the place. How do we fix it:
public void driveIn(Car car) {
//loop through the array until we find a null spot,
//then park the car
for (int i=0; i < carsParked.length; i=i+1){
if (carsParked[i] == null){
//we found the car, so set the space null
carsParked[i] = car.getRegNo();
carsIn=carsIn+1;
//stop looping now
break;
}
}
}
It could still be improved further. I would probably still change String[] carsParked to Car[] carsParked as to not throw away information.
I would also change the driveIn and driveOut methods to return booleans to indicate if the successfully parked or un-parked a car.
Final Edit:
Okay, if you want to keep track of what cars are parked in the car park and which spot they are in you need to know enough about each car to make it unique. In your case you may only need regNo. So when you call driveIn or driveOut you have to pass that information so we can store it at the appropriate index (parking spot) in the array. Otherwise all you will know is a car was parked somewhere, or that a car left. Not which spots are open.
So in short the parameter Car car in those two methods contain the information needed to uniquely identify each car that is being parked, or is leaving. Without it the car park instance would have no clue who is currently parked, or where they are parked.

3-dimensions different types Map or List: List(ID=integer) of List(ID=integer) of int[]

I'm going to build a hotel table.
But I'm having problems when trying to implement this in Java.
My hotel has Level(int id) x Room(int id) x Field(String status, int counter)
The same in php would look like:
$level=1; $room=2;
if(isset($hotel[$level][$room])) {
print("Room: ".$level*100+$room);
print(", Status: ".$hotel[$level][$room]['status']);
print(", Total clients:".$hotel[$level][$room]['counter']);
}
And this print returns me(if room exist):
"Room: 102, Status: Reserved, Total clients: 8";
Now I want to have the same in JAVA.
But the problem is, that I'm not able to build this:
int[][][] my hotel;
Because, I have the different types in my multi-dimensional array.
I tried to make sth like this:
Map<String, List<String>> myHotel = new HashMap<String, List<String>>();
Or:
List<List<List<String>>> myHotel;
But
out.println(
myHotel.get(1).get(2).get("status") + "\n" +
out.println(myHotel.get(1).get(2).get("status"));
Or even:
out.println("Status:" +
myHotel.get(1).get(2).get(0) + "\tClients:" +
myHotel.get(1).get(2).get(1)
);
Also how to put elements. I'm thinking about sth like:
WHEN it's a MAP table:
myHotel.put(1).add(2).add(0, "Reserved"));
// But better would be:
// myHotel.put(1).add(2).add("status", "Reserved"));
Or WHEN it's a List<List<List<String>>>:
myHotel.add(1).add(2).add(0, "Reserved"));
// But better would be:
// myHotel.add(1).add(2).add("status", "Reserved"));
Thanks for helping :)
I'd probably model the hotel as an object Hotel, the room as an object Room etc. rather than stacking everything together in a multi-tiered collection. That becomes very verbose very quickly, and as soon as you change the relationships then that change is reflected throughout your code.
Each object then contains references to its components (Hotel contains a list of Rooms etc.). Once you do this I think everything should become a lot clearer. Furthermore your Hotel object understands how to find Rooms, the Room objects understand how to get its attributes and your calling code becomes a lot less verbose, and a lot less dependent on the Hotel/Room implementation. e.g. you can do this:
Hotel hotel = new Hotel();
Set<Room> rooms = hotel.getFreeRooms(RoomType.NON_SMOKING);
and so your objects do the work for you (the client) rather than you navigating the object hierarchy and doing the work yourself.
That's the ultimate goal of OO. As soon as I find myself putting together collections of collections, that's often an indicator that a new object class is required.
You should create proper classes
import java.util.*;
class Hotel {
public List<Level> levels = new ArrayList<Level>();
}
class Level {
public List<Room> rooms = new ArrayList<Room>();
}
class Room {
public Status status = Status.FREE;
public int counter = 0;
}
enum Status {
FREE, OCCUPIED
}
and then you use
Hotel hotel = new Hotel();
hotel.levels.add(new Level());
hotel.levels.get(0).rooms.add(new Room());
Room room = hotel.levels.get(0).rooms.get(0);
room.status = Status.OCCUPIED;
room.counter = 8;
et cetera...
NB: of course, OO purists will no come and tell you that all these fields need to be private and only be accessed through accessors. But I'd say it's okay if you start with this most simple design and later, as you learn more Java, evolve it to something more complex.
class HotelRoom{
int roomnumber;
int level;
boolean reserved;
int clientCount;
public int getUniqueNumber(){
return roomnumber + level*100;
}
}
...
HotelRoom[][] hotel = new HotelRoom[floorCount][roomCount];
HotelRoom myRoom = hotel[floor][room];
System.out.print("room: " + myRoom.getUniqueNumber());
System.out.print(", Status: " myRoom.reserved);
System.out.print(", Total clients: " myRoom.clientCount);
Your design is pretty crazy, by the way.
Since level and room number is the key, I would represent room as a value object like this (at a minimum):
class Room {
public static enum Status {RESERVED, AVAILABLE}
private Status status;
private int numberOfPersons;
// Getters and setters
}
And the key as:
class RoomKey {
private int levelNumber;
private int roomNumber;
public RoomKey(int levelNumber, int roomNumber) {
this.leveNumber = levelNumber;
this.roomNumber = roomNumber;
}
}
And keep the data in a Map like:
Map<RoomKey, Room> rooms = getRoomMap();
Room room = rooms.get(new RoomKey(levelNumber, roomNumber))

Categories

Resources