BST intersection, NullPointerException - java

I am trying to create a new BST from the intersection of 2 known BSTs. I am getting a NullPointerException in the intersect2 method int he second case, at the line "cur3.item.set_account_id(cur1.item.get_accountid()+ cur2.item.get_accountid());". I know you get the error when you try to dereference the variable without initializing it but i think i am initializing it? I'm not really sure. I would appreciate the help.
public static Bst<Customer> intersect(Bst<Customer> a, Bst<Customer> b){
return( intersect2(a.root, b.root));
}
public static Bst<Customer> intersect2(BTNode<Customer> cur1, BTNode<Customer> cur2){
Bst<Customer> result = new Bst<Customer>();
// 1. both empty -> true
if (cur1==null && cur2==null){
result=null;
}
// 2. both non-empty -> compare them
else if (cur1!=null && cur2!=null) {
BTNode<Customer> cur3 = new BTNode<Customer>();
cur3.item.set_account_id(cur1.item.get_accountid()+ cur2.item.get_accountid());
result.insert(cur3.item);
intersect2(cur1.left, cur2.left);
intersect2(cur1.right, cur2.right);
}
// 3. one empty, one not -> false
else if (cur1==null ||cur2==null){
BTNode<Customer> cur3 = new BTNode<Customer>();
cur3.item=null;
intersect2(cur1.left, cur2.left);
intersect2(cur1.right, cur2.right);
}
return result;
}
Here is the image of the problem:

A NullPointerException can be caused by a number of things. In your given example, cur1 and cur2 are not null, but there is no guarantee that cur1.item, cur1.item.accountId (and similarly for cur2) are not null.
Being as you have no description for the underlying implementation, I cannot assist further.
I can suggest that you do some of a few things:
1.) check the implementation of your objects (if this happens EVERY time, there may be some sort of initialization problem.
2.) Whenever you create an instance of your item, do you make sure to specify the accountId field? Try giving a default value for this field so it cannot be null. (try some sort of illegal value [eg -1, false, etc] and test for it.
If you would post more implementation details, I (or someone) may be able to directly identify the problem.
Regards.
Edit:4/20#17:11
Here's an example of what you should be doing.
public class Customer {
private int accountId;
public Customer() {
this.accountId = 0;
}
public Customer(int account_identification) {
this.accountId = account_identification);
}
//As a side note, general practice implies fields be private
//Use a method (hence the term 'getter' and the reciprocal, 'setter')
public int getId() {
return this.accountId;
}
public void setId(int replacement_account_identification) {
this.accountId = replacement_account_identification;
}
}

It is because the item variable in Customer object is not initialized.

Does creating a BTNode automatically allocate its member item ?
You do:
cur3.item.set_account_id(.. )
For this to succeed, both cur3 and cur3.item need to be not null.
Same applies to cur1 and cur2 as well, that you reference later in that line.
And the example of the 3rd case shows that BTNode.item can be null in some scenarios:
cur3.item=null;

Related

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.

Optional <Integer> cannot be converted to Int (for use on GUI Progress Bar)

I am receiving below error, when I try to set value on a JProgressBar.
"Optional cannot be converted to Int"
Could someone please advise any workarounds/Solution??
public GUI(){
initComponents();
tL = new TasksToDo();
jProgressBar1.setValue(tL.retrieveTotalHours());// [Where my error occurs]}
}
And from the TaskToDo Class, Originally I set this to ArrayList but the warnings said needed to switch to Optional:
public class TasksToDo {
public static ArrayList<Task> taskList;
public TasksToDo(){
taskList = new ArrayList<Task>();
taskList.add(new Task(0,"Whitepaper", "Write first draft of Whitepaper", 7));
taskList.add(new Task(1,"Create Database Structure", "Plan required fields and tables", 1));
taskList.add(new Task(2,"Setup ODBC Connections", "Create the ODBC Connections between SVR1 to DEV-SVR", 2));
}
public void addTask (int taskId, String taskTitle, String taskDescription, int taskHours){}
public ArrayList<Task> retrieveTask(){
return taskList;
}
public Optional<Integer> retrieveTotalHours(){
return taskList.stream().map(e -> e.getTaskHours()).reduce(Integer::sum);
}
}
You have to unwrap the optional and grab the value in it like this. Otherwise you can't assign an Optional where int is needed.
tL.retrieveTotalHours().orElse(0);
An Optional means that the value need not be there. It is basically there to force the caller to explicitly decide what to when a value does not exist. In your case, you can specifify a default value:
jProgressBar1.setValue(tL.retrieveTotalHours().orElse(0));
However, your retrieveTotalHours method probably should not return an Optional in the first place. Stream.reduce returns Optional.empty() when the stream is empty, but in your case it probably should return 0 when the list of tasks is empty. So you can do:
public int retrieveTotalHours(){
return taskList.stream().map(e -> e.getTaskHours()).reduce(0, Integer::sum);
}
(The 0 argument is the identity, which is returned when the stream is empty.)
or even:
public int retrieveTotalHours(){
return taskList.stream().mapToInt(e -> e.getTaskHours()).sum();
}
Well, basically, an Optional<Integer> is not assignment compatible with int.
But Integer is (after unboxing) ... so change:
jProgressBar1.setValue(tL.retrieveTotalHours());
to
jProgressBar1.setValue(tL.retrieveTotalHours().orElse(0));
Note that you must provide an integer value when you call setValue. Null or "nothing" is not acceptable.
If you are only interested in the sum of hours, you don't need the Optional and can make it simpler:
public int retrieveTotalHours()
{
return taskList.stream().mapToInt(e -> e.getTaskHours()).sum();
}

How do I maintain a pointer to a List in a Java class?

I have a very simple Java class:
public class Party {
private List<String> hosts = new ArrayList<String>();
private String headHost = null;
public void addHost(String name) {
hosts.add(name);
headHost = name;
}
}
But it seems a bit silly to maintain a String keeping track of the list's pointer...
1. Is there a better way for keeping track of who is the "head host"?
It won't always be the last person added, either:
public void setHost(int i) {
headHost = hosts.get(i); // potentially throws an exception based on i
}
public void setHost(String name) {
headHost = name;
}
2. What's the best way to change the current "head host"? Both of these methods could potentially take incorrect parameters.
The current version is just fine. If you are concerned about exceptions, you can apply some defensive programming to the code:
public void setHost(int i) {
if(i < 0 || i > hosts.size()-1){
throw new IllegalArgumentException("Index is out of range!");
}
headHost = hosts.get(i);
}
public void setHost(String name) {
if(!hosts.contains(name){
throw new IllegalArgumentException("The specified host does not exist.");
}
headHost = name;
}
List doesn't have a concept of current, at least not in Java. If you want to know what the first element is, just use List.get(0)
To get the last element, use hosts.get(hosts.size()-1).
You may also be interested in the Stack class, which has LIFO (last in, first out) methods to make it even easier to get the most recently entered element.
If for some reason you want to be able to lookup a host by String name, don't use a List, use a Map (preferably a HashMap)
You area already holding just a pointer. String is an object in java.
When you do this:
public void addHost(String name) {
hosts.add(name);
headHost = name;
}
There is only one string with two pointers to it, one pointer in the list and one in your instance variable headHost. There are not two copies of the actual data.

Java: Copy Constructor not going as planned

I have a bit of a problem. I'm making a Finite Automata checker.
Given an input, and the DFA, does it end on a accepting state.
My problem is creating a new DFA_State from another's target.
DFA_State state0, state1, curr_state, init_state, temp; //fine, I think
state0 = new DFA_State();
state1 = new DFA_State();
state0 = new DFA_State("State 0",true, state0, state1); //fine, I think
init_state = new DFA_State(state0); //fine, I think
but, this bit is throwing up problems.
temp = new DFA_State(curr_state.nextState(arr1[i]));
*
*
curr_state = new DFA_State(temp);
Thanks for any help,
Dave
Edit:
God I was retarded when I did this, AFAIK, I just wasn't thinking straight, added methods to set the values to the DFA_State object.
//in DFA_State class
public void set(DFA_State on_0, DFA_State on_1, Boolean is_accepting, String name){
this.on_0 = on_0;
this.on_1 = on_1;
this.is_accepting = is_accepting;
this.name = name;
}
//in main
DFA_State state0, state1, curr_state;
state0 = new DFA_State();
state1 = new DFA_State();
state0.set(state0, state1, false, "State 0");
state1.set(state1, state0, true, "State 1");
curr_state = state0;//initial state
//iterate across string input changing curr_state depending on char c
curr_state = getNextState(c);
//at end
if(curr_state.isAccepting())
System.out.println("Valid, " + curr_state.getName() + " is accepting);
else
System.out.println("Invalid, " + curr_state.getName() + " is not accepting);
In that first line, you declare the variables state0, state1, curr_state, init_state and temp as being variables of type DFA_State. However, that only declares them, they are not yet initialized. The next few lines are all okay. Second line creates a state without anything in it and assigns it to state0, so does the third line for state1. Fourth line overwrites your previous state0 assignment with a new DFA_State that has actual contents. Fifth line creates a DFA_State as a copy of state0 and assigns it to init_state.
Assuming there's nothing in between this and the first line of your second code block, now you'll get a problem. You're assigning temp with a new DFA_State that uses a copy-constructor with an argument relying on curr_state. But at that point, that variable hasn't been initialized yet. Just because it was declared doesn't mean it has somehow already been structured in memory. When you call nextState on it, there's simply no variable to resolve this to. Don't expect to get something like a pointer that will eventually point to a part of what you put in curr_state.
I'm just guessing, but from your code style I'd say you have a background in C or C++. Look into the differences between those languages and Java. If possible, I'd also advise you to make your DFA_State class immutable, since this is more reliable and will avoid mistakes. That means getting rid of the no-args constructor. Here's a reworking of it (not actually compiled, might contain errors):
package foundations.of.computing;
/**
*
* #author Kayotic
*/
class DFA_State {
private final String state;
private final DFA_State on_0;
private final DFA_State on_1;
private final boolean isAccepting;
//private DFA_State dummy;
public DFA_State(DFA_State arg) {
//this(arg.is_accepting(), arg.on0(), arg.on1());
state = arg.get_name();
isAccepting = arg.is_accepting();
on_0 = arg.on0();
on_1 = arg.on1();
}
public DFA_State(String name, Boolean accepting, DFA_State on0, DFA_State on1) {
state = name;
isAccepting = accepting;
on_0 = on0;
on_1 = on1;
}
public String get_name(){
return state;
}
public Boolean is_accepting() {
return isAccepting;
}
public DFA_State on0() {
return on_0;
}
public DFA_State on1() {
return on_1;
}
public DFA_State nextState(char i) {
if (i == '0') {
return on0();
} else if (i == '1') {
return on1();
} else {
System.out.println("Error with input");
return null;
}
}
}
Even if you can't make the instance variables final, it's best to at least make them private, since you already have methods for getting them.
There are better memory representations of DFAs than the object-oriented.
You should use a simple lookuptable:
int[] table = new int[vocabularyCount][stateCount];
Every State and every word gets a number, starting with 0.
Fill the table with the state transitions, or -1, if there is no transition. Now you just need the translation methods for the states and the words.
Heres a generic DFA algorithm:
public boolean checkSentence(String s, int[] finishes) {
// fill table
int state = 0; // assuming S0 is the start state
for (int i = 0; i < s.length(); i++) {
state = table[translate(s.charAt(i))][s];
}
for (int i = 0; i < finishes.length; i++) {
if (finishes[i] == state) {
return true;
}
}
return false;
}
The program is quite poorly written. Look at this in your FoundationsOfComputing.java:
state0 = new DFA_State();
state1 = new DFA_State();
state0 = new DFA_State("State 0",true, state0, state1);
You essentially created 3 instances of state - two instances which are not initialized (first two lines in your code) - all their instance variables are null.
Then you create the third instance, which you point to the first two uninitialized ones, and assign it to state0 variable. Please note, at this point, it is only the value of the variable that changes, not the values you passed in the DFA-State constructor!!! So, what you now have in state0 is a state that points to two uninitialized states.
Now let's look at the code further down in the FoundationsOfComputing.java:
while (i < arr1.length) {//loops through array
System.out.println(i + ". scan shows " + arr1[i]);
temp = new DFA_State(curr_state.nextState(arr1[i]));
System.out.println(" "+curr_state.get_name()+ " moves onto " + temp.get_name());
curr_state = new DFA_State(temp);
i++;
}
I am guessing this throws NullPointerException - that code moves to the on_0 state of state0 - which is a state that has not been initialized (all it's instance variables are null), so in the following pass of the loop, when it calls curr_state.nextState(whatever), it would return null and you are trying to pass that to the copy-constructor which would result in NPE.
Ok so we know this is homework. Let's do this instead of telling you the answer let's try and work through it on your own. If you are seeing a NullPointerException (NPE). Grab the second line of the exception:
java.lang.NullPointerException: null
at com.blah.blah.SomeObject.someMethod(SomeArgumentType):1234 <<< here
....
That 1234 is the line number in the file that contains SomeObject. If you goto that line number you can see exactly where the NPE is being generated from. For example if line 1234 was:
this.foo = bar.indexOf("caramel");
You can easily deduce what was null. No clue? Well this can never be null so this.foo isn't the problem. If this could be null you couldn't be inside that method because this points to the instance you are currently within. Therefore, the only other statement where a variable is being dereferenced is bar so bar must be null. Let's look at your code:
temp = new DFA_State(curr_state.nextState(arr1[i]));
Say you find out the line above is tossing an exception. Well there could be several things that could be null. curr_state could be null, or arr1 could be null in which case this line would blow up. However, if arr1[i] is null or curr_state.nextState() is returning null then you won't see the NPE pointing at this line, but would be coming out of the constructor should someone try to call methods on that method parameter.
Hopefully, this will give you the tools you need to track down problems in your application by understanding exception stack traces.

Trying to write priority queue in Java but getting "Exception in thread "main" java.lang.ClassCastException"

For my data structure class, I am trying to write a program that simulates a car wash and I want to give fancy cars a higher priority than regular ones using a priority queue. The problem I am having has something to do with Java not being able to type cast "Object" as an "ArrayQueue" (a simple FIFO implementation). What am I doing wrong and how can I fix it?
public class PriorityQueue<E>
{
private ArrayQueue<E>[] queues;
private int highest=0;
private int manyItems=0;
public PriorityQueue(int h)
{
highest=h;
queues = (ArrayQueue<E>[]) new Object[highest+1]; <----problem is here
}
public void add(E item, int priority)
{
queues[priority].add(item);
manyItems++;
}
public boolean isEmpty( )
{
return (manyItems == 0);
}
public E remove()
{
E answer=null;
int counter=0;
do
{
if(!queues[highest-counter].isEmpty())
{
answer = queues[highest-counter].remove();
counter=highest+1;
}
else
counter++;
}while(highest-counter>=0);
return answer;
}
}
EDIT
Thank you both for the quick answer to this question. I solved the problem by following your advice and one other bit of code:
public PriorityQueue(int h)
{
highest=h;
queues = new ArrayQueue[highest+1];
for(int i = 0; i <= highest; i++)
{
queues[i] = new ArrayQueue();
}
}
An Object is an Object and (in most cases) not an ArrayQueue. So indeed the cast is not possible.
Creation of generic arrays is a problem too, but in your case, this should work:
public PriorityQueue(int h)
{
highest=h;
queues = new ArrayQueue[highest+1]; // Gives an ignorable warning
}
EDIT
The way it is explained in your textbook is incorrect, the book needs a new revision cycle ;) The suggested cast is not allowed in Java, it's like an attempt to do
String forEverUseless = (String) new Object(); // this will not give an empty String
// but an ouch-that-hurts-Exception
which is more obvious. You can never cast a class to one of its subtypes (derived classes). This is true for all classes, including arrays and generic classes.
EDIT 2
Two more suggestions:
The 'add' method should get a check whether 'priority' is in the valid range of priorities, otherwise add will throw an exception (like in: queue.add(entry, -1))
A remove method usually has an argument - you might want to call it with the element that shall be removed from the queue. (Or - if you're intention is something else, i suggest using the common queue operation names pop, push and peek)
The problem is almost exactly what you said -- you're making something of type Object[] and trying to cast it to ArrayQueue[], and those aren't compatible types. You should just do:
queues = new ArrayQueue[highest+1];

Categories