0

I am trying to create class that extends the java.util.ArrayList by overriding the add method in the following way: it does nothing if the object to be added already exists in the collection; otherwise it calls the add method in the super class to add the object into the collection.

My code look like that so far but it gives a NullPointerException:

import java.util.ArrayList;

public class myArrayList<E> extends ArrayList<E> {
    public ArrayList<E> mylist;

    @Override
    public boolean add(E e) {
        if (!mylist.contains(e)) {
            super.add(e);
            return true;
        } else {
            return false;
        }
    }
}

    public static void main(String[] args) {
        myArrayList<Integer> listing = new myArrayList<Integer>();
        listing.add(4);
        listing.add(4);
        for (int i = 0; i < listing.size(); i++) {
            System.out.println(listing.get(i));
        }
    }
7
  • 1
    You should provide the entire error message? Exactly where did the null pointer come from? Commented Apr 18, 2020 at 5:45
  • I don’t understand the purpose of myList. You should be using this, as in if( ! this.contains( e ) ) Commented Apr 18, 2020 at 5:46
  • 1
    So you use inheritance & composition? This won't work. Commented Apr 18, 2020 at 5:54
  • 1
    @JohannesKuhn is right. extends ArrayList<E> is inheritance (what you said you want). public ArrayList<E> mylist; is composition. Don’t do both. Commented Apr 18, 2020 at 6:39
  • 1
    If you want to see what can go wrong if you do both, look at this. Don't do it. Commented Apr 18, 2020 at 7:44

2 Answers 2

2

While we can't be sure this is your problem (unless you show us the stacktrace!), it looks like an NPE is likely to occur in this line:

    if (!mylist.contains(e)) {

because mylist is never initialized.

In fact, if you are trying to extend ArrayList rather than create a list wrapper, the mylist variable should not exist at all. The list state is in the superclasses private variables. Instead, the add method should probably be written like this:

@Override
public boolean add(E e) {
    if (!super.contains(e)) {
        return super.add(e);  // See note
    } else {
        return false;
    }
}

Note: in general, you should return whatever the superclass returns here. However, when the superclass is ArrayList, we know1 that add will return true, so this is only "saving" a line of code. There might be marginal performance difference, depending on how smart the JIT optimizer is.

1 - We know because the ArrayList.add javadoc specifically states that true is returned.


But this looks like you are trying to create a "set-like" list class. There could be better alternatives; e.g. LinkedHashSet has a defined iteration order, and addition is O(1) rather than O(N). (Admittedly, LinkedHashSet uses a lot more memory, and it has no efficient equivalent to the positional List.get(int) method.)

Sign up to request clarification or add additional context in comments.

Comments

1

You got a NullPointerException on this line if (!mylist.contains(e)) { because myList is not instanciated in the default constructor.

public MyArrayList() {
 this.myList = new ArrayList<>();
}

But.. you mix inheritance and composition here...

That means add will be applied to myList and get(index) will be applied on this.. So you actually maintain 2 lists here..

In you example myList.contains will always return false because you never add something into. this -> super.add(e) is the same than this.add(e) and it is a different instance of list.

So just removed myList instance field and replace your add like this :

  @Override
    public boolean add(E e) {
        if (!contains(e)) {
            add(e);
            return true;
        } else {
            return false;
        }
    }

Watch out that this class is not thread-safe. Here there is a check-then-act race condition (check = contains(), act = add())

Finally List are designed to allow duplicates... if you don't want duplicates.. just use a Set

1 Comment

It is also not thread-safe because ArrayList (the superclass) is not thread-safe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.