1

I am trying to implement my own ArrayList. This is the code I have so far:

public class StringArrayList {
    private int size = 0;
    private String[] strings = new String[0];

    // Constructors
    public StringArrayList(){
        strings = new String[size];
    };
    public StringArrayList(int initialCapacity){
        strings = new String[0];
    }
    public StringArrayList(String[] strings){
        this.strings = strings;
        size = strings.length;
    }

    public int size() {
        return size;
    }

    public String get(int index){
        return strings[index];
    }

    public boolean add(String content){
        boolean add = false;
        strings = new String[10];
        for(int i = 0; i < strings.length; i++){
            if(strings[i] == null) {
                strings[i] = content;
                return true;
            }
        }
        return add;
    }

I have to make following test succeed:

     public void add__given_empty_list__then_adds_string()
    {
        StringArrayList lst = list();

        lst.add( "string" );

        assertSameItems( list( "string" ), lst );
    }

I am getting this error:

java.lang.AssertionError: expected<1> but was <0>

I'm actually lost in what is asked of me. I know there is a difference between null and an empty list, but if I don't specify then null I'm getting ArrayOutOfBounds exceptions.

What am I not understanding.

Thank you

12
  • Which line throws the error? Commented Apr 15, 2015 at 13:04
  • what do the functions list() and list(String) do? Commented Apr 15, 2015 at 13:05
  • That would be 'assertSameItems( list( "string" ), lst );' the only assert in the code Commented Apr 15, 2015 at 13:05
  • where are the methods list() and list(String str)? Commented Apr 15, 2015 at 13:06
  • 1
    what on earth are you trying to achieve in the add method? Commented Apr 15, 2015 at 13:08

3 Answers 3

2

Your implementation has a few errors.

public StringArrayList(int initialCapacity){
    strings = new String[0];
}

This type of constructor is meant to allocate with the initial capacity, not with "0".

And most importantly, your add method doesn't actually add a new element, but overwrites your current internal array, and places a new element at the 0th index (without incrementing the size variable).

public boolean add(String content){
    boolean add = false; //unnecessary, can replace bottom `add` with `false` for same result
    strings = new String[10]; //overwrites internal array of "list" with a new array
    for(int i = 0; i < strings.length; i++){
        if(strings[i] == null) { //will always replace only first element as this is a new array
            strings[i] = content;
            return true;
        }
    }
    return add;
}

The size variable is meant to keep track of how many elements the current array contains (which would be incremented when you add a new element).

Knowing that, you'd be able to add a new element instrings[size] to add a new element, in case size < strings.length was true.

If that condition is not met (you want to add more than the current capacity), it should "resize" the internal array by creating a new array, copying all previous elements into the new array, then replacing the old array, and adding the new element to the new array.

EDIT: Your new code

public boolean add(String content) { 
    strings = new String[strings.length+1]; //still erases the internal array!
    strings[0] = content; //only modifies the first element, rather than add to the list
    size = 1; //if it was implemented correctly, this would be size++;
    return true; 
} 

Make a test that adds TWO elements to the list, and assert if the list contains both of them.

EDIT2:

Here is a solution that ought to work:

public class StringArrayList {
    private int size = 0;
    private String[] strings;

    // Constructors
    public StringArrayList() {
        this(0);
    };
    public StringArrayList(int initialCapacity){
        String[] innerStrings = new String[initialCapacity];
        this(innerStrings);
    }
    public StringArrayList(String[] strings){
        this.strings = strings;
    }

    public int size() {
        return size;
    }

    public String get(int index){
        return strings[index];
    }

    public boolean add(String content){
        if(size == strings.length) {
            String[] newStrings = new String[size+10];
            for(int i = 0; i < size; i++) {
                newStrings[i] = strings[i];
            }
            strings = newStrings;
        }
        strings[size++] = content;
        return true;
    }
}

EDIT3:

public boolean add(String content){ 
    if(size == strings.length) { 
        String[] temp_list = new String[strings.length]; //no need to allocate a new array here if this is just to store your current array
        temp_list = strings; 
        strings = new String[size++]; //wrong, this allocates a `size`-long array and increases `size` by 1 afterwards, rather than create a new, larger internal array
        strings = temp_list; //this just overwrites your internal array with the old array which is not increased in size

     } 
     for(int i = 0; i < strings.length; i++) { 
         if(strings[i] == null) { //this is not necessary with proper `size`
             strings[i] = content; 
         } 
     } 
     return true; 
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks all for the help. I have a checklist of tasks to do, I'm aware the implementation isn't as it should be, but I have to make more and more tests pass, without breaking any of the tests that do work. Still 80 tests to go. I made it work like this: public boolean add(String content){ strings = new String[strings.length+1]; strings[0] = content; size = 1; return true; } Thank you all for the replies!
@user3302053 Imagine you have a bag of goodies and I give you one piece of candy and say "put it in your bag :)". Would you throw your bag away and add that candy into a new and empty bag? If not, then why do you make your code to do that? Rethink your add method and think about the necessary steps to keep the existing data of your strings array and to add a new item to it. It might also help if you describe the steps in a text or in a checklist first, then you can program these steps.
public boolean add(String content){ if(size == strings.length){ String[] temp_list = new String[strings.length]; temp_list = strings; strings = new String[size++]; strings = temp_list; } for(int i = 0; i < strings.length; i++){ if(strings[i] == null){ strings[i] = content; } } return true; } I came up with this, which doesn't work. I'll compare the code
Nope, insert content at index size, then increment size by 1: it is equivalent to writing strings[size] = content; size += 1;
OK. I get it now. Thanks a lot for your help. Sadly, I don't think I can accept or grade your response (as of yet) - I'm new here.
|
0

Your add implementation is incorrect.

It will always rewrite the internal strings array and set the passed argument to the first element.

The reason why it is failing is because the add(String) method does not increment the size variable.

Comments

0

Currently you are using if(strings[i] == null) { to determine where a new element should be added. But an arraylist can contain nulls...

I think there should be a difference between the length of the array (e.g. the capacity of the arraylist) and the size field.

The size field should probably indicate how many elements are currently in the list. When a new element cannot be added because size is equal to the array length then some work is needed to create a new, larger array and copy all the elements from the old to the new array.

BTW I noticed you are not using the initialCapacity parameter in a constructor. This should probably be used to initialize the array to that length.

2 Comments

If I do use it, following test fails: public void constructor_int_initializes_to_empty_list() { StringArrayList lst = new StringArrayList( 15 ); assertSameItems( list(), lst ); } I find it strange
You should not set size = initialCapacity but strings = new String[initialCapacity]. The the size method should still return 0 even though the capacity is 15.

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.