3

To my knowledge, string arrays in Android are not dynamic. At least according to what I've been told on this site. I can't just create a string array and then add as many items to it whenever I feel like it. To get around that, you do a ListArray and then convert it to a String array when you've completed the array. If I was misinformed about this, then you can answer this question by telling me how to create a dynamic String array for example:

String[] menuList = new String[];
menuList.add("One");
menuList.add("A");
String firstItem = menuList[0];
menuList.add("Two");

Notice I can pull from it and then add to it without having to take any additional steps or conversions.

Assuming the above isn't possible, I am trying to set the array based on data in an online text file. So far so good, and each time they access this text file, the app saves the text file locally within the app. Still good. However if there is no internet access, I want the String array to be based on the saved local text file. The problem is that I believe I need to declare the length of the string array as it is being created, and if I create it within the if statement, the rest of the app won't recognize it. Like this:

ListArray<String> menuList = getFile(filename);
//The above line populates the ListArray with the online file, and returns an empty ListArray if there is no internet connection or if there is some problem with getting the file.
//Now I want to populate a String[] with the ListArray if it was successful (and overwrite the local copy), or if it was unsuccessful, I want to get the local copy and populate it with that.
if(menuList.size != 0){
   writeToFile("Menu List", menuList);
   String[] menuArray = menuList.toArray(new String[menuList.size()]);
} else {
   String[] menuArray = readFromFile("Menu List");
}
setUpView(menuArray);

Now obviously this won't work because setUpView can't see that menuArray was created since it is inside an if statement. How can I get use String array's (without simply using ListArray instead) whiles using an if statement to determine its content?

I should mention, since now I've written out the problem, I already see several work arounds. For example, I can simply combine the write and read methods and then I won't need to use the if statement here. Or I could just work with the ListArray until the last minute, or set the String[] to be far longer than I need it to be and stop pulling from it when it gets to an empty slot. That said, using String[] in an if statement has come up before, and I'd like to know how to implement such a thing if it is possible. Thoughts?

8
  • this has nothing to do with android, it is how arrays (not only string arrays) work in java. Commented Jan 13, 2014 at 16:59
  • 1
    In my opinion using static array implementation is not efficient, because when you resize it (the arrayList), what actually happens is to alocate in main memory twice its size and then traverse the array and update the second. The first gets carbage collected. There are java build in implementations for dynamic lists, why dont you use them? Commented Jan 13, 2014 at 17:02
  • why on earth would you restrict yourself to using exclusively arrays? (and also you can notice that your issue is not related whatsoever to the arrays being immutable, as you would have the exact same issue with any object, since it is only a matter of scope.) Commented Jan 13, 2014 at 17:02
  • @NikosMargaritis : what you describe is exactly how ArrayList works, btw. Commented Jan 13, 2014 at 17:02
  • @njzk2 yes i know, arrayList is a static array implementation. I wanted to demonstrate how inefficient it is when resizing takes place. Commented Jan 13, 2014 at 17:06

3 Answers 3

1

You need to declare the variable outside the if statement, then assign it inside.

String[] menuArray;
if(menuList.size != 0){
   writeToFile("Menu List", menuList);
   menuArray = menuList.toArray(new String[menuList.size()]);
} else {
   menuArray = readFromFile("Menu List");
}
Sign up to request clarification or add additional context in comments.

2 Comments

Don't I need to set the length at the declaration? I was told I would have to do that earlier.
@MarcelMarino: You're confusing variables with objects. You need to set the length when you create an instance of an array.
1

I can't just create a string array and then add as many items to it whenever I feel like it. To get around that, you do a ListArray and then convert it to a String array when you've completed the array. If I was misinformed about this, then you can answer this question by telling me how to create a dynamic String array.

In my opinion using static array implementation is not efficient, because when you resize it (the arrayList), what actually happens is to alocate in main memory twice its size and then traverse the array and update the second. The first gets carbage collected. There are java implementations provided for dynamic lists, why dont you use them?

Examples: see LinkedList

I can't just create a string array and then add as many items to it whenever I feel like it. To get around that, you do a ListArray and then convert it to a String array when you've completed the array.

You wont need to create your own dynamic list (since there are java implementations), however, I am gonna explain how they work, so you can get an idea about it. Dynamic lists are implemented with a class node that keeps the pointer of the next node, so all together are formaing a list of connected items. Moreover, the first element of the list is marked as the head of the list and the last one as the tail (If you use a java's LinkedList, there are double pointers; keeping the previous and the next node so you can move backwards if needed). The difference between the dynamic list and an array is that you do not declare a size for it, but rather add as many items as you wish and allocate only the size of those nodes in your main memory. On the other hand, static arrays require alocating the memory for its whole size eventhough you have empty indeces. In addition, the nodes are stored not sequencially in the main memory, which is the case with the static arrays because like this time complexity O(1) can be achieved when you access an index.

An example of how this works:

public class Node {
    private Object item;
    private Node next;

    public Node() {
        next = null;
    }

    public Node(Object newItem) {
        item = newItem;
        next = null;
    }

    public Node(Object newItem, Node nextNode) {
        item = newItem;
        next = nextNode;
    }

    public void setItem(Object newItem) {
        item = newItem;
    }

    public Object getItem() {
        return item;
    }

    public void setNext(ListNode nextNode) {
        next = nextNode;
    }

    public Node getNext() {
        return next;
    }
}
public class LinkedList {
    private Node head;
    private Node tail;
    int numItems;

    public LinkedList() {
        head = tail = null;
        numItems = 0;
    }

    public int size() {
        return numItems;
    }

    public boolean isEmpty() {
        return (numItems == 0);
    }

    public void removeAll() {
        head = tail = null;
        numItems = 0;
    }

    private Node find(int index) {
        ListNode curr = head;
        for (int skip = 1; skip < index; skip++)
            curr = curr.getNext();
        return curr;
    }

    // Etc for the other methods.. like add/remove/etc
}

EDIT

The above example is not the best one to be used. I am just providing it for understanding purposes, there are other things that could be used, like a binary search tree for example or a hashMap. The algorithm complexity of a balanced binary search tree is O(log n) while hashMap has algorithm complexity from O(1) to O(n) (more frequently O(1))

2 Comments

linkedlist are terrible as soon as you need to access any arbitrary value. (and have a terrible constant factor (see docs.oracle.com/javase/tutorial/collections/implementations/…))
@njzk2 I agree. However, they are better than the static implementation i.e ArrayList(as resizing takes place in this case). Apart from that, I am just providing an example, there are other things that could be used, like a binary search tree for example or a hashMap. The algorithm complexity of a balanced binary search tree is O(log n) while hashMap has algorithm complexity from O(1) to O(n) (more frequently O(1)).
1

I quote SLaks's answer and I would like to add an answer to your comment here, as I do not have enough reputation yet. You "don't need to set the length at the declaration". The line

String[] menuArray;

actually only declares a reference to an array object, it does not create the object itself, it does not allocate the memory for the array (except the tiny bit for the reference on the stack). Remember to initialise the variable before accessing it though.

That said, I think if you are looking for an "expandable" array, then you should use ArrayList and the List interface. An ArrayList, not ListArray, is a 'Resizable-array implementation of the List interface', from the Java official docs.

Could you change the method setUpView to take a List? If not you can still convert ArrayList to array back and forth with:

List<String> menuList;
// ...
String[] arr = (String[]) menuList.toArray();
List<String> list = new ArrayList<String>(Arrays.asList(arr));

1 Comment

No worries. Also, for the last line, you could be tempted to write List<String> list = Arrays.asList(arr); but that would create an unmodifiable List. It would compile, but once you tryed adding an element, say, by list.add("hello"), then an Exception would be thrown. It is a common pitfall everybody comes across sooner or later

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.