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 trialAndrew D.
2,937 PointsTrouble 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
Courses Plus Student 7,254 PointsHi 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();
Andrew D.
2,937 PointsHey 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.
2,937 PointsNevermind! Silly me, forgot to import java.util.*
Alex Davis III
12,138 PointsCould you explain how the "categoryCounts.get(category)" part works?
"Integer count = categoryCounts.get(category);"
kabir k
Courses Plus Student 18,036 PointsHi 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;
Unsubscribed User
5,239 PointsNo 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
Courses Plus Student 7,254 PointsHi,
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.
Unsubscribed User
5,239 PointsWith 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
Courses Plus Student 7,254 PointsIf 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.
Unsubscribed User
5,239 PointsAhh 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
Courses Plus Student 7,254 PointsYour 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.
Unsubscribed User
5,239 PointsAllright - Thanks for your help, and for being so indulgent with me, Jon :)
Rami Shublaq
3,387 Pointspackage 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;
}
}
piyush arora
5,735 Pointspiyush arora
5,735 PointsHi 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
Courses Plus Student 7,254 PointsJon Kussmann
Courses Plus Student 7,254 PointsYes, 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
7,052 PointsCiaran McNally
7,052 PointsThanks for this Jon, this challenge was a bit of a curve ball.