Calling Methods on HashMap Objects [duplicate] - java

This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 6 years ago.
I have the following code:
public class Interval {
private HashMap intervals;
public Interval() {
this.intervals = new HashMap<String, List<Long>>();
}
public void addInterval(String name, long interval) {
List<Long> foo = new ArrayList<Long>();
foo.add(interval);
foo.add(System.currentTimeMillis());
this.intervals.put(name, foo);
}
public boolean isReady(String name) {
if (System.currentTimeMillis() - (this.intervals.get(name)).get(0) >
(this.intervals.get(name)).get(1)) { //ERROR
return true;
}
return false;
this.intervals.get(name).set(1, System.currentTimeMillis()); //ERROR
}
}
The code is supposed to store intervals (in milliseconds) by a key in a HashMap and have a method to see if the interval has passed yet (since the last call). It will be used as a cooldown for a player shooting in a game. Anyways, the code doesn't work because the value returned by intervals.get(String key) is an Object, and doesn't allow methods like "get" and "set" to be called on it like I would be able to on a ArrayList. Anyone know how to fix this?
P.S. The lines with the comment "ERROR" are the ones that give the error.

Change your private field from
private HashMap intervals;
to
private HashMap<String, List<Long>> intervals;

Related

Using String value as a name of another Variable [duplicate]

This question already has answers here:
To use a string value as a variable name [duplicate]
(5 answers)
Closed 2 years ago.
I was just simplifying my code and I ran into a small problem which I can't solve.
So I have an activity which has a getter like so:
private String[][] Example001 ={{"String1","String2"},{"Light","Normal","Heavy"}};
public String getExerciseValue(String variableName ,int codeOrValue,int type){
switch (variableName){
case "Example001":
return Example001[codeOrValue][type];
case "Example999"
return Example999[codeOrValue][type];
}
return "default";
}
so instead of having numerous number of cases, I would rather simplify the code by something like this
public String getExerciseValue(String variableName ,int codeOrValue,int type){
return variableName[codeOrValue][type];
}
I ask for an example of working code work this case coz I have no idea how to figure this out. Thanks for any suggestions :)
This is not possible in Java. However, it is also not necessary.
Whenever you have series of numbered variable names, that's actually just a very cumbersome way of implementing an array:
private String[][][] examples = {
{
{ "String1", "String2" },
{ "Light", "Normal", "Heavy" }
}
};
public String getExerciseValue(int exampleNumber, int codeOrValue, int type) {
return examples[exampleNumber - 1][codeOrValue][type];
}
Suggest you to use HashMap, and put each array as a value with your preferred name in it. Something like it:
Map<String, String[][]> examples = new HashMap<>();
examples.put("Example001", Example001);
You can then easily retrieve your element with its names and indexes as you needed.
examples.get("Example001")[codeOrValue][type]

Initializing a general HashMap with constant values for a class [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I am having problems instantiating a general HashMap with constant values. I intend to track inventory of various car types in a car rental service; with car type serving as key and num available to rent as the value.
I attempted using a method createAvailable cars which initializes the map to constants for max number of each car type. For further testing I included a setMaxCarsAvailable method as well. Despite all this I get a NullPointer Exception coming from my canReserveVehicle method enter image description hereon the line specifying that if there are 0 available cars then you can't reserve a vehicle. How do I properly handle inventory with my map of cars? Where should I place it? I tried using a static method and later including it in a constructor with no luck. See my code below.. (I have included a picture of the stack trace showing the errors in the testCase class. I hope all this extra info helps)
public class CarReservationController {
String phoneNumber;
long numDays = 0;
Vehicle vehicle;
VehicleType vType;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public static final int MAX_ECONOMY = 10; //used this to track the amount of cars available to rent. This was applied in the canReserveVehicle and addReservation methods
public static final int MAX_PREMIUM = 10;
public static final int MAX_SUV = 5;
public CarReservationController()
{
availableCars = createAvailableCarsMap(); //this is my attempt at instantiating my availableCars map to contain (VehicleType.ECONOMY, 10), (VehicleType.PREMIUM, 10), map.put(VehicleType.SUV, 5); ;
}
Map<VehicleType, Integer> availableCars;
Map<VehicleType, PriorityQueue<Date>> reservedVehicleReturnDates = new HashMap<>(); // Map from vehicle type to reserved car end dates. This will hold all the current reservations end dates for each vehicle type
//was public static map
public HashMap<String, List<CarReservation>> reservationsMap = new HashMap<>();
//previously private static Map...
private Map<VehicleType, Integer> createAvailableCarsMap() {
Map<VehicleType, Integer> map = new EnumMap<VehicleType, Integer>(VehicleType.class);
map.put(VehicleType.ECONOMY, MAX_ECONOMY);
map.put(VehicleType.PREMIUM, MAX_PREMIUM);
map.put(VehicleType.SUV, MAX_SUV);
return map;
}
public void setMaxCarsAvailable(VehicleType v, int maxAvailable) {
availableCars.put(v, maxAvailable);
}
//I UPDATE carReservationsMap here..this adds an actual reservation but first it checks the boolean canReserveVehicle below
public void addReservation(CarReservation res) throws Exception //right here
{
Date sDate = res.getStartDate(); //HERE
Date eDate = res.getEndDate(); //HERE
String phoneNumber = res.getPhoneNumber();
if(canReserveVehicle(vType, phoneNumber, sDate, eDate)) {
if (reservationsMap.containsKey(phoneNumber)) {
List<CarReservation> currCustomerRes = reservationsMap.get(phoneNumber);
currCustomerRes.add(res);
reservationsMap.put(phoneNumber, currCustomerRes);
} else {
List<CarReservation> currCustomerRes = new ArrayList<CarReservation>(Arrays.asList(res));
reservationsMap.put(phoneNumber, currCustomerRes);
}
int countForVehicleType = availableCars.get(vType);
availableCars.put(vType, countForVehicleType - 1);
if (reservedVehicleReturnDates.containsKey(vType)) {
reservedVehicleReturnDates.get(vType).add(eDate);
} else {
PriorityQueue<Date> q = new PriorityQueue<Date>();
reservedVehicleReturnDates.put(vType, q);
}
}
}
//NULL POINTER EXCEPTION COMING UP HERE FROM JUNIT TESTS
public boolean canReserveVehicle(VehicleType v, String phoneNumber, Date startDate, Date endDate) throws ParseException
{
PriorityQueue<Date> reservedVehicleQueue = reservedVehicleReturnDates.get(v);
if(endDate.before(startDate))
return false; // check that the start date of the reservation is before the end date
if (availableCars.get(v) == 0) { /// SAYS THERE IS A NULL POINTER EXCEPTION from here... because availableCars is still 0..
Date nextCarReturnDate = reservedVehicleQueue.peek();
if(nextCarReturnDate.after(startDate))
return false; // return false if a reserved car is not going to be available before the new customer is requesting one.
}
else {
// If a car that will become available before the customer requests it, remove it from the queue and replace with the
//requesting customer's return date (as they now lay claim to the car)
reservedVehicleQueue.poll();
reservedVehicleQueue.add(endDate);
}
//these are comparing strings.
if (reservationsMap.containsKey(phoneNumber)) {
List<CarReservation> resByCustomer = reservationsMap.get(phoneNumber);
CarReservation lastResByCustomer = resByCustomer.get(resByCustomer.size() - 1);
Date lastResEndDate = sdf.parse(lastResByCustomer.endDate);
if (startDate.before(lastResEndDate)) { //1 customer can only have one rental at a time within the system.
return false;
}
}
return true;
}
}
Test case looks like this with "java.lang.NullPointerException" CarReservationController.canReserveCarVehicle"
import java.text.SimpleDateFormat;
import org.junit.Test;
public class CarReservationTest {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
#Test
public void testThatCustomerCanMakeReservation() throws Exception {
CarReservationController reservationSystem = new CarReservationController();
reservationSystem.setMaxCarsAvailable(VehicleType.PREMIUM, 2);
CarReservation firstRes = new CarReservation(VehicleType.PREMIUM, "Jon Snow", "1234567890", "2019-01-23", "2019-01-31");
reservationSystem.addReservation(firstRes);
//assertTrue(reservationSystem.reservationsMap.containsKey("1234567890"));
assertTrue(reservationSystem.reservationsMap.size() > 0);
assertEquals(firstRes, reservationSystem.reservationsMap.get("1234567890"));
}
}
There are several issues that make this complicated to debug.
Perhaps most important for the question you asked, without a full stacktrace, it isn't obvious whether the NPE you are seeing is from availbleCars.get(v) or from availableCars.get(v) == 0.
That issue is complicated by the fact that without knowing what the ReservationSystem::addReservation method does, I don't think it's possible to rule out either possibility.
Possibility 1
However, if the issue is from availableCars.get(v) == 0, then it might be from your choice to compare equality between an Integer and a numeric primitive using == instead of .equals(). Please see this previous answer for a more complete discussion: Why comparing Integer with int can throw NullPointerException in Java?
Possibility 2
If the issue is from availableCars.get(v) (that availableCars itself is null), then you may have an issue with how you are instantiating that availableCars map. The method you are using there doesn't need to be static, and also you don't need the setter you have created.
Next Steps
To solve this problem, I'd recommend using a breakpoint or breaking that comparison into two steps with debug statements - first check to see that availableCars is not null, then check that availableCars.get(v) is an Integer, and then use .equals() to check the equality with 0.
In addition, you might try unit testing your methods to instantiate the availableCars map and the ReservationSystem::addReservation method separately as well, to help narrow down where the bug might be.

How can I access a stack or linked list that's inside an ArrayList? [duplicate]

This question already has answers here:
How to fill a List of Lists?
(3 answers)
Working with a List of Lists in Java
(8 answers)
Closed 5 years ago.
So I'm trying to create "piles" of cards in a class called Table using an ArrayList with stacks inside of it that contain the card objects (which are defined in a separate class).
I initialized it like so:
private MyArrayList<MyStack<Card>> piles;
public Table()
{
MyStack<Card> piles = new MyStack<>();
}
My issue is that I can't figure out how to add things to and from the stack inside the ArrayList. Is my initialization of it wrong? If so, how can I fix it?
Note: MyArrayList and MyStack are just slightly different versions of ArrayList and Stack essentially.
The variable names are a little confusing. Consider:
// private MyArrayList<MyStack<Card>> piles;
private final ArrayList<Stack<Card>> allPiles;
public Table() {
// MyStack<Card> piles = new MyStack<>();
allPiles = new ArrayList<>();
}
then you can do something like this:
public void addCardToPile(Card card, int pileIndex) {
while (allPiles.size() < pileIndex) {
allPiles.add(new Stack<Card>());
}
allPiles.get(pileIndex).push(card);
}
public Card getTopCardFromPile(int pileIndex) {
while (allPiles.size() < pileIndex) {
allPiles.add(new Stack<Card>());
}
if (allPiles.get(pileIndex).isEmpty()) {
return null;
}
return allPiles.get(pileIndex).pop();
}
But it's not clear if ArrayList is the most appropriate here. Consider a Map<Integer, Stack<Card>> allPiles, and instead of pileIndex have something like pileNumber. Or Map<String, Stack<Card>> allPileswith pileName.
Iterate through the list here piles, push card in the Stack.
for (MyStack cards: piles) {
cards.push(new Card);
}

Iterating through attributes of DIFFERENT types in a class and printing each [duplicate]

This question already has answers here:
Printing all variables value from a class
(9 answers)
Closed 6 years ago.
I have this simple class:
public class Events{
Boolean wentToGym;
String eventsToday;
public Events(Boolean wentToGym, String eventsToday){
this.wentToGym = wentToGym;
this.eventsToday = eventsToday;
}
Now for some reason I need to iterate through these fields and print them. As they are from different types, I thought I would use the Object declaration in the for-loop:
public static void main(String[] args){
Events events = new Events(true, "first trial");
for(Object e: events.getClass().getDeclaredFields){
System.out.println(e.toString);
}
}
Unfortunately not working because the object has no toString method. It gives me the same result you get when you try printing an array. And I dont know how to cast them inside the loop as they are declared as objects. Whats the best way to iterate through the attributes of a class and print them?
Edit: the question some guys rushed into referring to as duplicated is about attributes all of the same type (Strings), so there is no need for using an object nor the problem is the same. Its always a good idea to try helping by even reading the whole thing even if its harder than feeling important by simply flagging a question.
Is this what you're looking for?
import java.util.Arrays;
public class Events {
Boolean wentToGym;
String eventsToday;
public Events(Boolean wentToGym, String eventsToday) {
this.wentToGym = wentToGym;
this.eventsToday = eventsToday;
}
public static void main(String[] args) {
Events events = new Events(true, "first trial");
Arrays.stream(events.getClass().getDeclaredFields()).forEach(field -> {
try {
System.out.println(field.getName() + ": " + field.get(events));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
}
}
Output:
wentToGym: true
eventsToday: first trial

Using reverse values in enums in Java [duplicate]

This question already has answers here:
Why can't enum's constructor access static fields?
(5 answers)
Closed 6 years ago.
I have an enum with values like this (the example just shows a few of the values but you will catch on): _800, _830, _900, _24HOURS, CLOSED
These have a corresponding value, so I added to my enum, which you can do in Java, a value field and a getter and setter for the value, like this (for space sake I do not show the getter and setter but they are the standard ones):
enum Hours {
_800("08:00"),
_830("08:30"),
CLOSED("Closed"),
APPT("By Appt.")
// etc
;
Hours(String v) {
val = v;
}
String val;
}
I also want to be able to go the other direction, that is, if I have a value (e.g. "08:00") I want it to return the enum _800. So to the enum I added a map:
static Map<String,String> valToEnumMap = new HashMap();
then I added this to my constructor:
Hours(String v) {
val = v;
valToEnumMap.put(v, this);
}
and a new method:
Hours valToEnum(String v) {
return valToEnumMap(v);
}
but when I try running it I get an initialization error at the point where it tries to insert into the map. I have tried other things like
valToEnumMap.put(v, valueOf(name());
but the same error. I did find a workaround but it is very slow, so I wonder what I did wrong? Here is the workaround I used which is slow:
public static OfficeHoursTimes valToEnum(String val) {
for (OfficeHoursTimes o : OfficeHoursTimes.values()) {
if (o.getVal().equals(val)) {
return o;
}
}
return null;
}
But there has to be a better way
The problem is that you're trying to use the map before it's initialized, since your enum instances get created first.
You want to declare your map like this:
static final Map<String,Hours> valToEnumMap = _createValueMap();
and then
private static Map<String,Hours> _createValueMap()
{
Map<String, Hours> map = new HashMap<>();
//...iterate through values() and put them all in the map ...
return map;
}
At first glance, it seems your map is defined wrong.
Try
static Map<String,Hours> valToEnumMap = new HashMap<String,Hours>();

Categories