Reputation: 45
I just came to the problem where I want to call a function of an Object inside a HashMap. I already searched it up and found one thread but sadly I don't understand it.
So here's my code
public class Seat {
//some attributes
public int getNumber() {
return number;
}
public boolean isReserved() {
return status;
}
}
public class Hall {
private HashMap mySeats;
public HashMap getMeinePlaetze() {
return meinePlaetze;
}
public void createSeats() {
for (int i = 1; i <= this.getnumberOfSeats(); i++) {
this.getMySeats().put(i, new Seat(i, 1));
}
}
}
public class Main {
Hall h1 = new Hall(...);
h1.createSeats();
h1.getMySeats().get(2).isReserved(); //How do I have to write this to work out?
}
I hope my intend is reasonable. Feel free to correct me if my code sucks. I already apologize for it.
Thank you very much.
Upvotes: 0
Views: 187
Reputation: 1095
Following my tip in the comments, I wouldn't use a Map to link a meaningful row or number to a map-key or an array-index.
So, actually I would do it this way (because you asked, what I mean with my tip):
Seat:
public class Seat {
private final int row;
private final int number;
private boolean reserved = false;
public Seat(int row, int number) {
this.row = row;
this.number = number;
}
public boolean reserve() {
if (!reserved) {
reserved = true;
return reserved;
}
return !reserved;
}
public int getRow() {
return row;
}
public int getNumber() {
return number;
}
public boolean isReserved() {
return reserved;
}
public boolean is(int row, int number) {
return this.row == row && this.number == number;
}
@Override
public int hashCode() {
int hash = 7;
hash = 23 * hash + this.row;
hash = 23 * hash + this.number;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Seat other = (Seat) obj;
if (this.row != other.row) {
return false;
}
return number == other.number;
}
}
Hall:
public class Hall {
public final Set<Seat> seats = new HashSet<>();
public Set<Seat> getSeats() {
return Collections.unmodifiableSet(seats);
}
public void createSeats(int lastRow, int seatsPerRow) { // This is an example; in case you have different count of seats per row, you better make an boolean addSeat(int row, int number) function; boolean to check if it has been added or if the seat already exists
for (int row = 1; row <= lastRow; row++) {
for (int number = 1; number <= seatsPerRow; number++) {
seats.add(new Seat(row, number));
}
}
}
public Seat get(int row, int number) {
for (Seat seat : seats) { // or you use seats.iterator; I personally hate Iterators; it is my subjective point of view.
if (seat.is(row, number)) {
return seat;
}
}
return null;
}
public boolean reserve(int row, int number) {
Seat seat = get(row, number);
if (seat != null) {
return seat.reserve();
}
return false;
}
}
And my Test-drive:
public class TestDrive {
public static void main(String[] args) {
Hall hall = new Hall();
int lastRow = 15;
int seatsPerRow = 10;
hall.createSeats(lastRow, seatsPerRow);
boolean reserved = hall.reserve(5, 9);
System.out.println("Seat(Row=5, Number=9) is reserved: " + (reserved == hall.get(5, 9).isReserved()));
boolean reservedAgain = hall.reserve(5, 9);
System.out.println("Seat(Row=5, Number=9) cannot be reserved again: " + (reservedAgain != hall.get(5, 9).isReserved()));
}
}
Upvotes: 1
Reputation: 34470
Since version 5, Java has a feature called Generics. You'll find a lot about generics on the web, from articles, blog posts, etc to very good answers here on StackOverflow.
Generics allows Java to be a strongly typed language. This means that variables in Java can not only be declared to be of some type (i.e. HashMap
), but also to be of some type along with one or more generic type parameters (i.e. HashMap<K, V>
, where K
represents the type parameter of the keys of the map and V
represents the type parameter of the values of the map).
In your example, you are using a raw HashMap
(raw types are types that allow for generic type parameters to be specified, however the developer has not specified them). Raw types are considered bad practice and are highly error-prone, as you are experiencing right now.
HashMap
allows two generic type parameters (one for the keys and another one for the values). In your case, you are using Integer
for the keys and Seat
for the values. Put into simple words, you are mapping integers to seats, or you can also say that your map is a map of integers to seats.
So, inside you Hall
class, you should define your map with its generic type parameters:
private Map<Integer, Seat> mySeats = new HashMap<>();
Then, this code:
h1.getMySeats().get(2)
will return an instance of type Seat
, because your map already knows that all its values are of type Seat
.
So your code:
h1.getMySeats().get(2).isReserved();
will compile fine and will work without any errors.
Please note that, apart from declaring the generic types of your map, I've also changed two additional things.
First, I've created an actual instance of HashMap
by using its constructor:
mySeats = new HashMap<>()
If you don't create an instance of your type with new
, there won't be any HashMap
instance where to put your seats later, and you'll get a NullpointerException
(try it!).
Secondly, I've changed the type of the variable from HashMap
to Map
. HashMap
is a class, while Map
is just an interface. The thing is that the HashMap
class implements the Map
interface, so, unless your code explicitly needs to access a method of HashMap
that is not declared in the Map
interface (which is almost never the case), you will be fine with the mySeats
variable being of type Map<Integer, Seat>
instead of HashMap<Integer, Seat>
. This is called programming to the interface and is a best practice that you should embrace from the very beginning. It will save you a lot of headaches in the future.
Upvotes: 2
Reputation: 1416
h1.getMySeats().get(2).isReserved();
Please use an IDE like IntelliJ IDEA. It will tell you about mistakes like forgetting parentheses while typing.
Upvotes: 1