I'm attempting to make a stack and am running into issues where every time I attempt to check an index value I'm getting a NullPointerException.
private E[] items;
public Stack(Class<E> type) {
E[] items = (E[]) new Object[10];
}
public boolean isEmpty(){
if(items[0] == null){
return true;
}
return false;
}
When I run
public static void main(String[] args) {
Stack<String> myStack = new Stack<>( String.class );
System.out.println(myStack.isEmpty());
}
I'm getting a NullPointerException at
if(items[0] == null)
during the call to isEmpty().
Obviously I know items[0] should be null at this point and want to be able to do things based on if it is null or not, in this case returning true since the stack is empty. How can I do this without getting a NullPointerException?
The line in the constructor
E[] items = (E[]) new Object[10];
creates a local variable but doesn't initialize your class field items. Use
items = (E[]) new Object[10];
The compiler will have raised a warning that items is not used so it is a good idea to pay attention to these warnings.
Also, when making generic classes as such, I'd recommend doing it slightly differently. Instead of passing the class as a constructor parameter, you can declare the class as generic and it will work the same.
public class Stack<E>
{
private E[] items;
public Stack() {
items = (E[]) new Object[10];
}
public boolean isEmpty(){
if(items[0] == null){
return true;
}
return false;
}
public E push(E item){
...
}
public E peek(){
...
}
.
.
.
}
Then your main class would look like:
Stack<String> myStack = new Stack<String>();
myStack.push("hi");
System.out.println(myStack.isEmpty());
This more closely emulates the conventions that java's built in generic classes have.
Related
I am trying to create Expression Tree using the Postfix Expression.
This needs a Stack which could hold Tree Objects.
I created a generic Stack class which could except <TreeTemp> as type argument.
On trying to initialize the stack with following statement, its giving "Cannot infer type arguments for TreeStack<>" error.
private TreeStack<TreeTemp> stack1 = new TreeStack<>(new TreeTemp());
Stack Class:
public class TreeStack<T> {
private T [] stackElem;
private final int MAXSTACKSIZE;
private int top;
public TreeStack(Class<T> t) {
top = -1;
MAXSTACKSIZE = 20;
final T[] stackElem = (T[]) Array.newInstance(t, MAXSTACKSIZE);
this.stackElem = stackElem;
}
public void push(T elem) throws Exception{
if(isFull()) {
stackElem[++top] = elem;
}
else
throw new Exception("Stack is already Full");
}
public T pop() throws Exception {
if(isEmpty()) {
return stackElem[top--];
}
else
throw new Exception("Stack is Empty");
}
public boolean isEmpty() {return top == -1;}
public boolean isFull() {return top==MAXSTACKSIZE-1;}
}
Postfix.class(Class having method for creating tree)
public class PostFix {
private String expression = new String("A*B+C");
private char [] expElem = expression.toCharArray();
/*Error on below Statement*/
private TreeStack<TreeTemp> stack1 = new TreeStack<>(new TreeTemp());
public TreeTemp makeTree() throws Throwable {
try {
for(int i=0;i<expElem.length;i++) {
ExpNode eNode = new ExpNode();
eNode.setiData(expElem[i]);
TreeTemp t = new TreeTemp();
t.setRoot(eNode);
if(!Character.isLetter(expElem[i])) {
t.setLeftTree(stack1.pop());
t.setRightTree(stack1.pop());
}
stack1.push(t);
}
return stack1.pop();
}catch (Exception e) {
throw new Exception("Stack Error while creating a Tree", e);
}
}
public static void main(String[] args) throws Throwable {
PostFix pf = new PostFix();
TreeTemp t = pf.makeTree();
}
Tree Class(Type which i want to add into Stack):
public class TreeTemp {
private ExpNode root;
private TreeTemp leftTree;
private TreeTemp rightTree;
/*public TreeTemp(ExpNode expNode) {
root = expNode;
}*/
public TreeTemp getLeftTree() {
return leftTree;
}
public void setLeftTree(TreeTemp leftTree) {
this.leftTree = leftTree;
}
public TreeTemp getRightTree() {
return rightTree;
}
public void setRightTree(TreeTemp rightTree) {
this.rightTree = rightTree;
}
public ExpNode getRoot() {
return root;
}
public void setRoot(ExpNode node) {
this.root = node;
}
}
Can someone pls give some pointers.
Your TreeStack has only one constructor. Here it is:
public TreeStack(Class<T> t) {
Thus, to invoke it, you need to pass the class object that represents the class associated with the T type. So, the class itself, not 'some particular instance of T'. When you call it on your error line:
private TreeStack<TreeTemp> stack1 = new TreeStack<>(new TreeTemp());
You are passing an instance of TreeTemp. Not the concept 'TreeTemp, the class'. Try new TreeStack<>(TreeTemp.class);
Note that as a general rule, passing a Class<T> is a code smell; you're trying to make generics something that it isn't (you're trying to runtime reify). This is objectively bad: It means you can't make a TreeStack<List<String>>, for example, because you're restricted to the overlap where both generics as well as j.l.Class instances can represent the thing, and that's just simple, non-genericsed, non-primitive classes.
final T[] stackElem = (T[]) Array.newInstance(t, MAXSTACKSIZE);
Looks like the only reason you want that class is to make sure your array is properly typed.
This is not neccessary. Just make a new Object[] array, and cast to T anytime you need to return a T. Now your TreeStack constructor needs no arguments at all.
Check the source of java.util.ArrayList, which agrees with this assessment; it is backed by an Object array, not a T[].
The TreeStack constructor accepts a Class<T>, not a T, so you should do:
new TreeStack<>(TreeTemp.class);
Since this is an exercise to create expression trees, you don't really need to implement stacks from scratch. You should just use the ArrayDeque class through the Deque interface in the Java Collections API.
private Deque<TreeTemp> stack1 = new ArrayDeque<>();
Deque has all the methods your TreeStack has, and many more.
In Java, the peek() method throws an exception if it is invoked on an empty stack.
Currently, to get around this issue, I have to check if the stack isn't empty before calling peek().
Is there a way to override the peek() method so that it returns null whenever a stack is empty instead of throwing an exception?
I think you can simply extend your own version of stack like this:
public class MyCustomStack<E> extends Stack<E> {
#Override
public synchronized E peek() {
if (isEmpty()) {
return null;
}
return super.peek();
}
}
public class OwnStack<E> extends Stack<E> {
#Override
public synchronized E peek() {
int len = size();
if (len <= 0) return null;
return elementAt(len - 1);
}
}
You can do this with any class that is not final in java. Look up inheritance.
public class HackedStack<E> extends Stack<E> {
#Override
public E peek() {
//do your thing
}
}
although you can completely avoid this by using stack#empty
https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html#peek()
public void loop() {
Stack<String> stack = new Stack<>();
while (!stack.empty()) stack.peek();
}
If the stack is accessed by a single thread, you should use a Deque. Not only does its peek() method return null in the empty case, it is also not synchronized and thus faster in single-threaded scenarios.
Deque<T> stack = new ArrayDeque<>();
stack.addFirst(element);
T element = stack.peekFirst();
If the stack is accessed by multiple threads, implementing your own concurrent stack should be preferable in my opinion, and easy if the capacity is fixed.
I've been working on trying to implement an immutable set from scratch, so I'm not using HashSet or java.util.Set
I have this method in my Empty class to add an element to an empty set:
public Set<T> add(T x) {
return new Element<T>(x, new Empty<T>());
}
And in another class called Element, I have the following constructor:
public Element(T element, Empty<T> empty) {
assert(element != null);
assert(empty != null);
this.element = element;
this.set = empty;
}
EDIT: here is my other Element constructor used for adding an element to a set.
public Element(T x, Set<T> set) {
this.element = x;
this.set = set;
}
But when I try to add an element it fails and the set is still empty.
I've used a similar code when creating an immutable Binary Search Tree and it worked fine so I assumed that I could do the same but for an immutable Set.
I was just wondering if the problem was with my add method or my constructor
Thank you
The size method:
for the Empty class
/**
* returns number of elements in the set
* #return size - number of elements in the set
*/
public int size(){
return -1;
}
for the element class:
#Override
public int size() {
if (set.isEmpty() == true) {
return -1;
} else {
return set.toList().size();
}
}
the toList() method:
#Override
public List<T> toList() {
List<T> list = new ArrayList<T>();
int i;
for(i = 0; i < set.size(); i++){
list.set(i, element);
}
return list;
}
reading over this part I realise that the problem with returning the size may be from the toList method I wrote, but I don't think that should have an effect on adding an element to the set?
toString - Element Class:
#Override
public String toString() {
return "Set = [" + set + "]";
}
toString - Empty class:
public String toString() {
return "";
}
And the JUnit Test for Add:
EDIT: realised that the set was immutable and so tried to make a new set that was equal to the empty set with the added value - to store the change but kept getting the same NullPointerException error.
#Test
public final void testAdd() {
Set<Integer> set1;
set1 = set.add(1);
int i = 20;
set.add(i);
assertSame("Last element should be the newly added name object", i, set.toList().get(set.size()-1));
assertEquals("Set size should be two", 2, set.size());
}
The assertSame gives a NullPointerException (so I'm guessing this means that the add didn't work and the set is still empty); and if I comment it out to test the next line the assertEquals says that set.size() is -1 (empty)
Almost everything in your existing code is flawed. Your Element's ctor does not make sense, size() and toList() are implemented in weird way, even the unit test is flawed in basic Java.
Some pseudo code
interface Set<T> {
Set<T> add(T v);
int size();
boolean contains(T v);
}
class Element<T> extends Set<T> {
T value;
Set<T> next;
public Element<T>(T element, Set<T> next) {...}
public Set<T> add(T value) {
if contains(value) { // already in set
return this;
}
return new Element(value, this);
}
public int size() {
return next.size() + 1;
}
public boolean contains(T value) {
return (this.value.equals(value) || next.contains(value));
}
}
public class Empty<T> extends Set<T> {
public Set<T> add(T value) {
return new Element(value, this);
}
public int size() {
return 0; // come on! 0 means empty, not -1!
}
public boolean contains(T value) {
return false;
}
}
Having reviewed my code, I realised where I was making the mistake.
Aside from the messy code in other areas, the add(T x) method was not working as expected due to the fact that I did not import the Empty or Element class to the Demo set or the JUnit test and, as mentioned by #shmosel, my toString method wasn't working properly because I did not include the element field and so was not going to output anything.
The following is my Demo code showing how I've added the import line. Furthermore, the constructor for Element works fine too. Again, I just needed to import the class for an Empty set for it to work.
package immutable.set;
import immutable.set.Empty;
public class DemoSet {
public static void main(String[] args) {
Set<Integer> set, set1, set2;
set = new Empty<Integer>();
System.out.println(set.isEmpty());
set1 = set.add(1).add(2);
set2 = set.add(3);
System.out.println(set1.toString());
System.out.println(set1.isEmpty());
System.out.println(set2.toString());
System.out.println(set2.isEmpty());
}
}
And it does print out the expected outcome.
Thank you for you help everyone.
I wrote a program to make a stack with the help of Iterator in Java. But I don't understand why I am getting the null pointer exception.
Here is my class for stack
import java.util.Iterator;
public class linkedStack1<Item> implements Iterable<Item>
{
public Iterator<Item> iterator()
{
return new listIterator();
}
private class listIterator implements Iterator<Item>
{
private node current = first;
public boolean hasNext() { return current!=null;}
public Item next()
{
Item item = current.item;
current=current.next;
return item;
}
}
private node first=null;
private class node
{
Item item;
node next;
}
public boolean isEmpty()
{
return first==null;
}
public void push(Item item)
{
node oldFirst=first;
first=new node();
first.item=item;
first.next=oldFirst;
}
public Item pop()
{
Item item=first.item; // ERROR SHOWING HERE
first=first.next;
return item;
}}
And my main class is this
import java.util.Scanner;
public class evaluate
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
String s=input.nextLine();
linkedStack1<String> ops = new linkedStack1<String>();
linkedStack1<Double> vals = new linkedStack1<Double>();
String op;
double a,b;
for(int i=0;i<s.length();i++)
{
if(s.charAt(i)=='(');
else if(s.charAt(i)=='+' || s.charAt(i)=='*'
|| s.charAt(i)=='-' || s.charAt(i)=='/')
ops.push(Character.toString(s.charAt(i)));
else if(s.charAt(i)==')')
{
op =ops.pop();
a=vals.pop();
b= vals.pop(); // ERROR SHOWING HERE
if(op=="+") vals.push(b+a);
else if(op=="-") vals.push(b-a);
else if(op=="*") vals.push(b*a);
else if(op=="/") vals.push(b/a);
}
else if(s.charAt(i)==' ')
continue;
else
vals.push(Double.parseDouble(Character.toString(s.charAt(i)) ));
}
System.out.println(vals.pop());
}
}
But when I execute this code for some input, say (1+(2*3)),
I get the null pointer exception
Exception in thread "main" java.lang.NullPointerException
at linkedStack1.pop(linkedStack1.java:47)
at evaluate.main(evaluate.java:25)
I have made the comments in front of the specified line numbers, so you can have a look at that,
and help me figuring out what's the bug in my code!!
When your stack is empty and you call pop, first.item throws a NullPointerException since first is null.
This means you are popping more elements than exist in your stack here :
a=vals.pop();
b= vals.pop(); // ERROR SHOWING HERE
you should check the stack is not empty before calling pop.
Your first element is initialized to null.
private node first=null;
But you use it in the pop method running before push() where you assign a new value. Either you initialize first to a valid value or change your code to use push() before the pop().
A textbook error.
You're comparing references (==) not values (equals()).
The result of the operation is not getting pushed onto the stack
Try this:
if(op.equals("+")) vals.push(b+a);
else if(op.equals("-")) vals.push(b-a);
else if(op.equals("*")) vals.push(b*a);
else if(op.equals("/")) vals.push(b/a);
In place of:
if(op=="+") vals.push(b+a);
else if(op=="-") vals.push(b-a);
else if(op=="*") vals.push(b*a);
else if(op=="/") vals.push(b/a);
See also:
How do I compare strings in Java?
I keep getting an error that says:
Note: ABag.java uses unchecked or unsafe operations.
I googled it and found this post, and made the changes that I thought would remove the error but I continue to get the error.
Is there anything else I can do to stop getting this error message?
public class ABag<Item> implements BagInterface<Item>
{
private ArrayList<Item> bag;
//creates an empty bag
public ABag(){
bag = new ArrayList<Item>();
}
//creates an empty set with initial capacity
public ABag (int initialCapacity){
bag = new ArrayList<Item>(initialCapacity);
}
public boolean add(Item newEntry){
if (newEntry == null)
return false;
else
{
bag.add(newEntry);
return true;
}
}
public boolean isFull(){
return false;
}
public Item[] toArray(){
Item[] temp = (Item[])bag.toArray();
return temp;
}
public boolean isEmpty(){
return false;
}
public int getCurrentSize(){
return bag.size();
}
public int getFrequencyOf(Item anEntry){
int count = 0;
if (!(bag.contains(anEntry)))
{
for (int i=0;i<bag.size();i++)
{
if (bag.get(i) == anEntry)
count++;
}
}
return count;
}
public boolean contains(Item anEntry){
return bag.contains(anEntry);
}
public void clear(){
bag.clear();
}
public Item remove(){
int size = bag.size();
Item removed = bag.remove(size-1);
return removed;
}
public boolean remove(Item anEntry){
return bag.remove(anEntry);
}
}
Thank you in advance!
You should enable linting to get verbose warnings about the specific problems:
javac -Xlint:all ...
Among other things, toArray() is broken. The List.toArray() method returns an Object[], not an array of <T>, so your cast to (Item[]) is incorrect and will fail at runtime. You should be using <T> T[] toArray(T[] a).
In order to create an array of the generic type (possibly the biggest weakness of Java generics), you need to pass in the Class for the target type and use reflection and suppress the warning, like so:
static public <T> T[] create(Class<T> typ, int len) {
return uncheckedCast(java.lang.reflect.Array.newInstance(typ,len));
}
#SuppressWarnings("unchecked")
static public <T> T uncheckedCast(final Object obj) {
return (T)obj;
}
The other option is to push the problem back one layer to the code that can be assumed to know the correct type and pass an array of that type into your toArray method, just as the Collections API does:
public Item[] toArray(Item[] dummy) {
return this.bag.toArray(dummy);
}
As something of an aside, convention is to use a single uppercase letter for the generic type; your use of <Item> fooled me at first when I was looking at toArray in isolation.
Replace your toArray with this, to avoid the cast
public Item[] toArray(){
Item[] temp = bag.toArray(new Item[0]);
return temp;
}