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

Matt Malone
Matt Malone
11,437 Points

Not sure how to get category counts when category is just a string (not a collection).

In this exercise, I wrote the following method. I know that 'length' is not the proper method for the string returned from 'post.getCategory', but my goal here is to get the number of categories for each BlogPost.

public Map<String, Integer> getCategoryCounts() { Map<String, Integer> categoryCounts = new HashMap<String, Integer>(); for (BlogPost post : mPosts) { categoryCounts.put(post.getCategory(), post.getCategory().length); } return categoryCounts; }

I cannot understand from the code how each BlogPost would have more than one category. Category is just a string -- not a collection. I'm confused from the code that I've been given here. How can I find the length of "one or more category" if mCategory is just a simple string?

com/example/BlogPost.java
package com.example;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class BlogPost implements Comparable<BlogPost>, Serializable {
  private String mAuthor;
  private String mTitle;
  private String mBody;
  private String mCategory;
  private Date mCreationDate;

  public BlogPost(String author, String title, String body, String category, Date creationDate) {
    mAuthor = author;
    mTitle = title;
    mBody = body;
    mCategory = category;
    mCreationDate = creationDate;
  }

  public int compareTo(BlogPost other) {
    if (equals(other)) {
      return 0;
    }
    return mCreationDate.compareTo(other.mCreationDate);
  }

  public String[] getWords() {
    return mBody.split("\\s+");
  }

  public List<String> getExternalLinks() {
    List<String> links = new ArrayList<String>();
    for (String word : getWords()) {
      if (word.startsWith("http")) {
        links.add(word);
      }
    }
    return links;
  }

  public String getAuthor() {
    return mAuthor;
  }

  public String getTitle() {
    return mTitle;
  }

  public String getBody() {
    return mBody;
  }

  public String getCategory() {
    return mCategory;
  }

  public Date getCreationDate() {
    return mCreationDate;
  }
}
com/example/Blog.java
package com.example;

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

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 : mPosts) {
      categoryCounts.put(post.getCategory(), post.getCategory().length);
    }
    return categoryCounts;
  }

}

3 Answers

michaelcodes
michaelcodes
5,604 Points

Awesome! I'm glad I could help. You can mark this question as solved by selecting a "best answer". I always encourage other people to try and answer questions too. Explaining something is one of the best ways to help retain it, so it helps out both parties!

Take care and happy coding :)

michaelcodes
michaelcodes
5,604 Points

Hello! When I was doing this challenge I also found it pretty complicated, but I will do my best to explain. Here is end result code I came up with, with the explanation for it below:

  public Map<String, Integer> getCategoryCounts() {
    Map<String, Integer> catToCount = new HashMap<String,Integer>();

    for(BlogPost bp : getPosts()) {
      Integer count = catToCount.get(bp.getCategory());
      if(count == null) {
       count = 0; 
      }
      count++;
      catToCount.put(bp.getCategory(), count);
    }
    return catToCount;
  }

First to answer your question: It is not that each blogpost has more than one category, but rather you are looping through all existing blogposts and creating a HashMap that contains a list of categories from all blogposts, and how many times those categories appear.

We start off by declaring a new HashMap called catToCount (Category to Count ratio). Then we must loop through all of the blogposts to get each category. We do this by creating a for loop that says: For each instance of blogpost contained within the List of all blogposts. We create an integer called count, which will store the amount of times each category is found. So we set count to be the corresponding value in the hashmap when we call "catToCount.get(bp.getCategory())" Because the first iteration the value should be null, we put in an if statement to account for this. We correct the issue of count containing null by setting it to 0.

Since we know that we are about to add a category, we increment the count variable by 1, then add both the category and the count for it to the HashMap with the put method. This will continue to loop through, checking if there is a current count for the category (if it it exists), then adding 1 (for the one we are about to add) then adding the category to our HashMap. Any new categories will have an initial null value, which will be set to 0.

Hope this helps!

Matt Malone
Matt Malone
11,437 Points

Thanks for your help on this! I have a few questions related to the code you'd provided here:

Why would catToCount.get(bp.getCategory()) be an integer...or even null?

(a) Wouldn't the value of the key -- bp.getCategory() -- be a string? Category is a string, isn't it?

(b) Regarding null, even with the first loop of the for loop, wouldn't bp immediately call the getCategory() method and thus provide a string for the count variable?

michaelcodes
michaelcodes
5,604 Points

Hello again! Ill try to answer these questions the best I can

1) So when we set up the HashMap we specify it is a map of <String, Integer>, upon first setting up this Map it contains nothing at all (null).

Map<String, Integer> catToCount = new HashMap<String,Integer>();
//Array is empty {null, null}

2) The category is in fact a String value, so when we call .get on (bp.getCategory()) it is going into the HashMap and attempting to match up our category<String> with the <Integer> part of the map. It wants to return the associated integer value with our String, but Since the map was just initialized with no values, Category will match up with null.

For Example: say one of the categories was "Swimming". when we call the .get it will match it up as so: {"Swimming", null}.

3) You are correct that even on the first loop it will obtain a category (String) from the getPosts(). The null comes in when we try to match the String to an Integer in our hashmap. As In the above example, the first time looping through the HashMap will pair up the String category with a null value.

We catch this null value, turn it to zero, then add "1" and put it in the HashMap, as the code would continue catToCount.put(bp.getCategory(), count); would add:

{"Swimming", 1}

If you have any more questions don't hesistate to ask! Good luck and happy coding!

EDIT: one last thing to clarify this question: "Why would catToCount.get(bp.getCategory()) be an integer...or even null?"

When you call .get on Map Arrays, it is attempting to return the associated value. So if the Map was declared as a <String, String>, it would take in the first String with the .get method, and attempt to return the second string (the String value that is paired up with the first)

Matt Malone
Matt Malone
11,437 Points

Thanks! That makes much more sense!