0

I have a snippet of code (below) that when run, will (ideally) fill an app array to look something like this:

Header 1:

App 1

App 2

Header 2:

App 3

App 4

etc.

However, when I run it in my emulator, it produces this:

Header 1:

App 1

App 2

App 3

App 4

...

Header 2:

App 1

...

I'm not sure why this happens, as I have looked up the defaults and everywhere I look, people say that Java defaults to passing by value, not by reference. If this is true, how come it adds every app to every category?

Preconditions:

Store is defined as a list of class "App", each element containing a header and title, among other things.

ListDataChild is an empty hashmap, with types > to be filled by the loop and then outputted via an expandable list view. I would post the code for the view, but it is very bulky and long so I'll just add a simple testing algorithm at the end.

EmptyList is just that, a list of type that has nothing inside (at least to begin with? Could it be changing?)

Code:

    listDataChild = new HashMap<String, List<App>>();

    List<App> emptylist = new ArrayList<>();
    List<App> Store = synced.getAppStore();

    Boolean juststarted = true;

    for (App el : Store)
    {
        if (juststarted)
        {
            juststarted = false;
            listDataChild.put(el.getHeader(), emptylist);
            listDataChild.get(el.getHeader()).add(el);
        } else {
            if (listDataChild.containsKey(el.getHeader())) {
                listDataChild.get(el.getHeader()).add(el);
            } else {
                listDataChild.put(el.getHeader(), emptylist);
                listDataChild.get(el.getHeader()).add(el);
            }
        }
    }
    //TESTING
    for (String header : listDataChild.keySet())
    {
        for (int j = 0; j < listDataChild.get(header).size(); j++)
        {
            System.out.println("HashMap at " + header + ", " + j + ": " + listDataChild.get(header).get(j).getTitle());
        }
    }

App.Java:

public class App {
    public String header,title,link,url,redirect,icon;
    public Double order;
    public Boolean selected;

    public App() {
        header = "";
        title = "";
        link = "";
        url = "";
        redirect = "";
        icon = "";
        order = 0.0;
        selected = false;
    }

    public int compareTo(App another) {
        if (this.getOrder()<another.getOrder()){
            return -1;
        }else{
            return 1;
        }
    }

    public void setHeader(String h) {
        header = h;
        return;
    }

    public void setTitle(String t) {
        title = t;
        return;
    }

    public void setLink(String l) {
        link = l;
        return;
    }

    public void setUrl(String u) {
        url = u;
        return;
    }

    public void setRedirect(String r) {
        redirect = r;
        return;
    }

    public void setIcon(String i) {
        icon = i;
        return;
    }

    public void setOrder(Double o) {
        order = o;
        return;
    }

    public void setSelected(Boolean s) {
        selected = s;
        return;
    }    




    public String getTitle()
    {
        return title;
    }

    public String getHeader()
    {
        return header;
    }

    public Double getOrder()
    {
        return order;
    }


}

Thanks in advance!

JFed-9
  • 297
  • 3
  • 17
  • *"If you have any suggestions for edits, please comment before just voting down."* is not constructive, and is likely to have the opposite of the desired effect. – T.J. Crowder Jul 25 '16 at 04:39
  • You haven't quoted nearly enough code, nor have you told us what `listDataChild` is or how it relates to the output you've specified. See: [mcve] – T.J. Crowder Jul 25 '16 at 04:40
  • 1
    *"everywhere I look, people say that Java defaults to passing by value, not by reference. If this is true, how come it adds every app to every category?"* Java doesn't "default" to pass-by-value, that's **all it has**. Note that when you're dealing with objects, the value that is passed is a reference to the object, not a copy of the object. That might have something to do with the problem you're having, it's impossible to tell from what you'v quoted. More: http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value?rq=1 – T.J. Crowder Jul 25 '16 at 04:42
  • Yes, Java uses pass by value. But the things being passed are always references (if they're object type). So sometimes, it seems a bit like it's pass by reference. If you want the hash map to store fresh objects rather than the ones that are passed to it, you'll need to write code to copy the objects. – Dawood ibn Kareem Jul 25 '16 at 04:43
  • Actually he did say that listDataChild was an empty hashmap (right above the **Code:** in the **Preconditions:** but I see what you mean, it's hard to understand the Store App class without seeing it. – H. Dog Jul 25 '16 at 04:44
  • I made some edits. Let me know if I need to add anything else. So with the last two comments, how can I fix this by forcing it to copy the list? – JFed-9 Jul 25 '16 at 04:44
  • Would it be helpful to include the code for App.java? – JFed-9 Jul 25 '16 at 04:45
  • And with the Store, I've tested it, and it looks fine. It is just filled with objects like I specified. – JFed-9 Jul 25 '16 at 04:45
  • One of the constructors for `ArrayList` lets you pass in an existing list, and copies the list for you. You could try using that. – Dawood ibn Kareem Jul 25 '16 at 04:46
  • yea, i'd like to see App.java... and are you declaring listDataChild somewhere? like right before the `for` loop? – H. Dog Jul 25 '16 at 04:47
  • @DavidWallace, which constructor is that? I'm sorry, I'm not familiar with Java – JFed-9 Jul 25 '16 at 04:48
  • I added the code for App.java, hope it helps – JFed-9 Jul 25 '16 at 04:51
  • I've looked at the question that this was marked as a duplicate of, @T.J.Crowder, and I don't see how it's an exact duplicate. I'm asking a very specific question about how I can add to a hashmap without seeing this bug. I'd really appreciate it if you would either explain how this is an exact duplicate, or unmark it as such. – JFed-9 Jul 25 '16 at 04:56
  • It is an exact duplicate because you are explicitly assuming passing of objects value, and Java is passes object *references* by value. – user207421 Jul 25 '16 at 04:59
  • I'm confused. Now you're saying Java uses pass-by-reference?? @EJP – JFed-9 Jul 25 '16 at 05:00
  • Look at the Javadoc, and remember that a List is a kind of Collection. – Dawood ibn Kareem Jul 25 '16 at 05:02
  • @JFed-9: No, that's not what EJP is saying. The word "reference" is used in for two very different things in programming (well, at least two). *Pass-by-reference* is a term of art which refers to the ability to pass a reference to a **variable** into a function and modify the **variable's value** from within that function, even though the variable is defined outside the function. That has nothing whatsoever to do with *object references*, which are values that refer to objects. Java (and many others) pass object references around, by value. – T.J. Crowder Jul 25 '16 at 05:02
  • Okay. So long story short, what can I edit to make the code work how I want it?? I'm looking for actual code here, since I'm very new to this. – JFed-9 Jul 25 '16 at 05:04
  • 1
    I've just looked at your code again. Probably the simplest thing to do would be just to put a new empty list into the map each time you need one, rather than reusing the same (initially empty) list over and over. – Dawood ibn Kareem Jul 25 '16 at 05:31
  • @DavidWallace So you're saying, before I put emptyList into the HashMap, I should reinitialize it? e.g. emptylist = new ArrayList<>(); – JFed-9 Jul 25 '16 at 05:33
  • You could give that a try, yes. – Dawood ibn Kareem Jul 25 '16 at 05:34
  • That worked!! Thank you so much! That's exactly what I was looking for. Do you mind putting that comment in the form of an answer so I can mark it as the accepted one? @DavidWallace – JFed-9 Jul 25 '16 at 05:36
  • I can't do that. Once a question has been marked as a duplicate, it's not possible to provide an answer. – Dawood ibn Kareem Jul 25 '16 at 05:42
  • Dang it. I'm so sorry, you deserve the extra reputation!! If this question ever gets unmarked, I'll accept your answer! – JFed-9 Jul 25 '16 at 05:43

1 Answers1

1

Yes you are right, java does pass by values but there are tricky situations:

  1. if you are using primitive data type: pass by value works fine.

  2. if you use Objects instead of primitive data type: pass by value works but for address of passing object. So it looks like passing reference. I know concept almost look like same but technically, it is pass by value.

Have a look at this link

Sachin Chandil
  • 17,133
  • 8
  • 47
  • 65