Peder
Peder

Reputation: 345

Get value from HashMap<String, ArrayList<String>>

[updated code] (Sorry guys, I didn't provide the whole code, because in my experience large codes seem to "scare off" possible helpers.)

For an ExpandableListView I want to build a HashMap<String, ArrayList<String>> where String is the name of a category and ArrayList<String> the names of animals belonging to that category. I populate the HashMap as such:

HashMap<String, ArrayList<String>> map_groups_childs;
ArrayList<String> list_group_titles;

private void prepareListData(ArrayList<Id_triv_cat> search_results) {
    list_group_titles = new ArrayList<String>();                  // this is a list of group titles
    map_groups_childs = new HashMap<String, ArrayList<String>>(); // this is a map. each group title gets a list of its respective childs

    // temporary List of items for a certain category/group
    ArrayList<String> temp_childs_list = new ArrayList<String>();

    // "search_results" is an ArrayList of self defined objects each containing an ID, a name and a category name
    int count = search_results.size();
    int i_cat = 0;
    int i=0;

    // if category "i" is the same as the next category "i+1", add child to list
    for (i=0; i<count-1; i++) {
        // build group with category name
        list_group_titles.add(search_results.get(i).get_type());

        // while category does not change, add child to the temporary childs-array
        while (i<=count && search_results.get(i).get_type().equals(search_results.get(i+1).get_type())) {
            temp_childs_list.add(search_results.get(i).get_name());
            i++;
        }

        // must be done, as the while loop does not get to the last "i" of every category
        temp_childs_list.add(search_results.get(i).get_name());

        Log.i("DEBUG", temp_childs_list.size());      // --> returns always more than 0
        Log.i("DEBUG", temp_childs_list.toString());  // --> returns always something like [word1, word2, word3, ...]
        Log.i("DEBUG", list_group_titles.get(i_cat)); // --> returns always a single word like "Insekten"

        // add [group_title:list_of_childs] to map
        map_groups_childs.put(list_group_titles.get(i_cat++), temp_childs_list);

        // clear temp_list, otherwise former category's species will be added to new category
        temp_childs_list.clear();
    }
Log.i("DEBUG", map_groups_childs.containsKey("Insekten"));  // --> returns true
Log.i("DEBUG", map_groups_childs.size());                   // --> returns 10
Log.i("DEBUG", map_groups_childs.get("Insekten").size());   // --> returns 0
Log.i("DEBUG", map_groups_childs.toString());               // --> returns {Insekten=[], Reptilien=[], ...}
}

The use of the same i in the for- and while-loop may seem wrong or confusing, but it is okay. No i is skipped in any way or used twice.

All keys I put in the HashMap are there, but the ArrayList I want to get with (for example) map_groups_childs.get("Insekten") is empty. What am I doing wrong?

Upvotes: 2

Views: 1951

Answers (3)

candied_orange
candied_orange

Reputation: 7308

Even with the edit, your code is still missing huge clues about what is going on. I've made some guesses and if I'm right, you are making this way too hard.

I've inferred the existence of a class Id_triv_cat that has getters named get_name() and get_type().

static class Id_triv_cat {

    String type;
    String name;

    Id_triv_cat( String type, String name )
    {
        this.name = name;
        this.type = type;
    }

    public String get_type()
    {
        return type;
    }
    public String get_name()
    {
        return name;
    }
}

I've also written this code to test your prepareListData() method.

public static void main(String[] args){
    ArrayList<Id_triv_cat> search_results = new ArrayList<Id_triv_cat>();
    search_results.add( new Id_triv_cat("type1", "name1") );
    search_results.add( new Id_triv_cat("type2", "name2") );
    search_results.add( new Id_triv_cat("Insekten", "insekten name1") );
    search_results.add( new Id_triv_cat("Insekten", "insekten name2") );
    search_results.add( new Id_triv_cat("type3", "name3") );
    new Test().myPrepareListData( search_results );
}

And while I could fix your minor defect like a good SE denizen I'm going to risk having all of this migrated to Programmers because your biggest problem is a design problem. Your code is suffering from a lack of clear local identifiers. Instead of making locals you are having a dot fest with the java utility classes that's making your code pointlessly hard to follow.

If, as I suspect, you are trying to build a map from a list of Id_triv_cat's using their type as a key and name as a value then try this:

private void myPrepareListData(ArrayList<Id_triv_cat> search_results) {
    // Each group title is mapped to a list of its respective children
    HashMap<String, ArrayList<String>> my_map_groups_childs = 
        new HashMap<String, ArrayList<String>>(); 

    for (Id_triv_cat search_result : search_results)
    {
        String type = search_result.get_type();
        String name = search_result.get_name();

        if ( my_map_groups_childs.containsKey(type) )
        {
            ArrayList<String> names = my_map_groups_childs.get(type);
            names.add(name);
        }
        else
        {
            ArrayList<String> names = new ArrayList<String>();
            names.add(name);
            my_map_groups_childs.put(type, names);
        }
    }

    Log.i("DEBUG", "my_map_groups_childs = " + my_map_groups_childs);
}

This displays: my_map_groups_childs = {Insekten=[insekten name1, insekten name2], type1=[name1], type3=[name3], type2=[name2]}

See how a few well chosen local's can make life so much easier?

If that's not what you wanted you're going to have to make your question clearer.

And Radiodef is right. You really should use camelCase when you code in Java.

Upvotes: 2

Radiodef
Radiodef

Reputation: 37845

    ...

    map_groups_childs.put(..., temp_childs_list);

    temp_childs_list.clear();
}

Objects are passed as a reference in Java. You are always putting the same List in to the Map and clearing it after every iteration. Thus every value in the Map points to the same List which is empty.

What you probably need is something like this:

for( ... ) {
    List<String> tempChildsList = new ArrayList<>();

    ...

    mapGroupChilds.put(..., tempChildsList);
}

Thus a new List is created on every iteration.

I also agree with @CandiedOrange your code is a mess and probably overly complex. In general the point of abstractions like List and Map is to not access things by counting numerical indexes all the time.

Note that in Java, the convention is that identifiers for variables are camelCase, not under_scored.

Upvotes: 2

candied_orange
candied_orange

Reputation: 7308

Near as I can tell what you need are the 5 lines in the second group below

    HashMap<String, ArrayList<String>> map_groups_childs = new HashMap<String, ArrayList<String>>();
    ArrayList<String> list_group_titles = new ArrayList<String>();
    ArrayList<String> temp_childs_list  = new ArrayList<String>();

    list_group_titles.add("insects");
    temp_childs_list.add("Swallowtail");
    temp_childs_list.add("Small White");
    temp_childs_list.add("Large White");
    temp_childs_list.add("Silverfish");

    int k = 0; 

    Log.i("DEBUG", list_group_titles.get(k)); // --> returns "insects"
    Log.i("DEBUG", temp_childs_list);         // --> returns [Swallowtail, Small White, Large White, Silverfish]

    map_groups_childs.put(list_group_titles.get(k), temp_childs_list);

    Log.i("DEBUG", map_groups_childs.size());                 // --> returns 1 not 10
    Log.i("DEBUG", map_groups_childs.containsKey("insects")); // --> returns true
    Log.i("DEBUG", map_groups_childs.get("insects").size());  // --> returns 4 not 0

Upvotes: 2

Related Questions