Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java Java Data Structures Exploring the Java Collection Framework Maps

Andrew D.
Andrew D.
2,937 Points

Trouble With Challenge

Hey guys.. having a little trouble wrapping up this challenge. I keep getting the following error:

./com/example/Blog.java:27: error: for-each not applicable to expression type for(String category : post.getCategory()) { ^ required: array or java.lang.Iterable found: String Note: JavaTester.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 1 error

The getCategory function returns a string.. and I'm searching it with a String variable names category, so I'm a little confused why I'm getting the error.

My code is below. Thank you to anyone who can point me in the right direction :-)

public Map<String, Integer> getCategoryCounts() {
 Map<String, Integer> categoryCounts = new HashMap<String, Integer>();
    for (BlogPost post : mPosts) {
      for(String category : post.getCategory()) {
        Integer count = categoryCounts.get(category);
        if (count == null) {
        count = 0;
      }
        count++;
        categoryCounts.put(category, count);
      }
    }
       return categoryCounts;
  }

5 Answers

Jon Kussmann
PLUS
Jon Kussmann
Courses Plus Student 7,254 Points

Hi Andrew,

You do not actually need that second for loop. the getCategory() method returns a String, not a collection of Strings.

Try this instead:

  String category = post.getCategory();

Hi Jon, Is this because each BlogPost has only one category unlike Treets which had multiple hashTags...That is why there is no need for a second loop here?

Jon Kussmann
Jon Kussmann
Courses Plus Student 7,254 Points

Yes, I believe that is correct. It is "getCategory()" and not "getCategories()". It's good to keep your variables and methods as descriptive as possible.

Ciaran McNally
Ciaran McNally
7,052 Points

Thanks for this Jon, this challenge was a bit of a curve ball.

Andrew D.
Andrew D.
2,937 Points

Hey Jon, still can't seem to get it to work. Is that what you meant?

public Map<String, Integer> getCategoryCounts() {
   Map<String, Integer> categoryCounts = new HashMap<String, Integer>();
    for (BlogPost post : mPosts) {
        String category = post.getCategory();
        Integer count = categoryCounts.get(category);
        if (count == null) {
        count = 0;
      }
        count++;
        categoryCounts.put(category, count);
    }
       return categoryCounts;
  }
Andrew D.
Andrew D.
2,937 Points

Nevermind! Silly me, forgot to import java.util.*

Could you explain how the "categoryCounts.get(category)" part works?

"Integer count = categoryCounts.get(category);"

kabir k
PLUS
kabir k
Courses Plus Student 18,036 Points

Hi Andrew,

Don't forget to include the imports for both the Map interface and HashMap implementation with your other imports at the top of your Blog.java file

import java.util.HashMap;
import java.util.Map;

No matter how I read this last correct answer of code, I can't see what use there is of the "count++" line. The Map.get method gets the Integer value for the key. Which means it can either be existing or not - returning either 1 or null. So if it's null, count is set to 0, and then incremented with 1, before added to the HashMap?

Meaning, if there is no category at all, it will be presented as if there were 1? Likewise, if Map.get returns 1, count gets incremented to 2 ? - that would be 2 categories for one post ?

There is obviously something i've missed :)?!

Jon Kussmann
Jon Kussmann
Courses Plus Student 7,254 Points

Hi,

Meaning, if there is no category at all, it will be presented as if there were 1? Likewise, if Map.get returns 1, count gets incremented to 2 ? - that would be 2 categories for one post ?

That means for that category, there are 2 posts that correspond to it. For example the category "sports", there are 2 posts that talk about sports.

If the category does not exist yet, then we make the count 0 and increment it to 1, we don't automatically make it 1 so that we can use the same "count++" for cases where the case does exist already. It's sort of reusing that part of the code.

With the understanding I have right now, my code would be like this:

 public Map<String, Integer> getCategoryCounts(){
    Map<String, Integer> categoryCount = new HashMap<String, Integer>();
    for(BlogPost post: mPosts){
      String category = post.getCategory();
      Integer count = categoryCount.get(category);
      if(count == null){
        count = 0;
      } else {
       count = 1; 
      }
      categoryCount.put(category, count);
    }
    return categoryCount;
  }

This is just trying to explain to you clever guys, how I got wrong, or in which way!

Edit: Didn't see your post there, Jon :)!

Jon Kussmann
Jon Kussmann
Courses Plus Student 7,254 Points

If the count doesn't exist (is null) you are making the count 0. That looks good.

Else, you are making it 1. What if the count is 2? Then you are setting it back to 1 again.

If count is null, set the count to 0.

Then for all cases, increment the count by 1.

If the count was originally null, it will now be 1.

If it was 1, it will now be 2.

If it was 2, it will now be 3 and so on.

Ahh now I get it.

So the "String category = post.getCategory();" return the category from the current post 'selected'.

And the "Integer count = categoryCount.get(category);" gets the current count, 'saved' in the Map.

The thing I misunderstood, is that the count variable is add to the existing count with the same key in the Map, for each loop. But instead the Map.put methods replaces the key, and therefore 'overwrites' with an entirely new value/count.

Is this correctly understood ?

Jon Kussmann
Jon Kussmann
Courses Plus Student 7,254 Points

Your reasoning looks good to me. I don't think it rewrites the category and the count in the Map. I think it just finds the category and replaces the count only.

Allright - Thanks for your help, and for being so indulgent with me, Jon :)

Rami Shublaq
Rami Shublaq
3,387 Points
package com.example;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.HashMap;
import java.util.Map;

public class Blog {
  List<BlogPost> mPosts;

  public Blog(List<BlogPost> posts) {
    mPosts = posts;
  }

  public List<BlogPost> getPosts() {
    return mPosts;
  }

  public Set<String> getAllAuthors() {
    Set<String> authors = new TreeSet<>();
    for (BlogPost post: mPosts) {
      authors.add(post.getAuthor());
    }
    return authors;
  }

  public Map<String, Integer> getCategoryCounts() {
    Map<String, Integer> categoryCounts = new HashMap<String, Integer>();
    for(BlogPost post : getPosts()) {
      String category = post.getCategory();
      Integer count = categoryCounts.get(category);
      if(count == null) {
          count = 0;
      }
      count++;
      categoryCounts.put(category, count);
    }
    return categoryCounts;
  }
}