Club Members FRQ Solution

When you sit for your Computer Science AP exam in May, you’ll most likely see a free response question where you have to work with an array or ArrayList of some class that you’ve never seen before. And it’s likely that you may have multiple classes interacting with each other.

In 2021, that was the Club Member free response.

What you’re give is a class called MemberInfo with all the parts that you need, and you’ll be implementing methods in a class called ClubMembers that works with an ArrayList of MemberInfo objects.

If you haven’t already, be sure to take a look at the full PDF for the ClubMember problem. We’ll include pieces of it here, but you do want to make sure you’ve seen the whole thing.

MemberInfo

You’re given the MemberInfo class. The methods are defined, but not implemented. But, you don’t really have to know or care how they’re implemented. It’s okay to just have this class be a black box.

public class MemberInfo {
    public MemberInfo(String name, int gradYear, boolean hasGoodStanding) {
        // Implementation not shown
    }
    public int getGradYear() {
        // Implementation not shown
    }
    public boolean inGoodStanding() {
        // Implementation not shown
    }
}

This gives us enough information to work with this class. Since the constructor is shown, it’s likely that we’ll be calling it somewhere in our implementation. Same with the getGradYear and inGoodStanding methods. Generally, College Board doesn’t go through the effort of including methods in problems that won’t get used anywhere.

ClubMembers

Now, let’s take a look at what you’re given for the ClubMembers class.

public class ClubMembers {
    private ArrayList<MemberInfo> members;
    public void addMembers(String[] names, int gradYear) {
        // Part A
    }
    public ArrayList<MemberInfo> removeMembers(int year) {
        // Part B
    }
}

We’ve only got two methods to worry about here, and we’ll take a look at them in the next sections where we’ll look at the solutions.

Part A - addMembers

For Part A we’re implementing the addMembers method which gets an String array containing student names and an int representing the graduation year. The problem does tell you that these students will be added to the members ArrayList in the same order that they appear in names and that all students are in good standing to start.

There are two things that you’re being tested on in this problem. One, that you’re able to iterated through an array of String references and do something with the values. And two, that you can add instances of a class you’ve never seen before to an ArrayList, only knowing the constructor for that class.

public void addMembers(String[] names, int gradYear) {
    for (int i=0; i<names.length; i++) {
        MemberInfo member = new MemberInfo(names[i], gradYear, true);
        members.add(member);
    }
}

This is a little more verbose than it needs to be, but I wanted to start with a version that is a little more clear to understand.

We’re looping through the array names and creating a new MemberInfo object for each name. We’re then adding that object to the members ArrayList.

The first shortening we can do here is to get rid of the throw away variable member. It’s not really necessary here.

public void addMembers(String[] names, int gradYear) {
    for (int i=0; i<names.length; i++) {
        members.add(new MemberInfo(names[i], gradYear, true));
    }
}

Here, instead of making a new variable we just instantiate the MemberInfo object and add it to the members ArrayList in the same line.

And we can make it a little shorter by using a for each loop instead of a normal for loop.

public void addMembers(String[] names, int gradYear) {
    for (String name : names) {
        members.add(new MemberInfo(name, gradYear, true));
    }
}

All three of these do the exact same thing and end up with the same results.

Part B - removeMembers

The second part has us implementing a method, removeMembers, that removes members from the members ArrayList based on their graduation year. At the same time, any member that is still in good standing gets added to a new ArrayList that is returned by the method.

We’re going to start with just the removal part and come back and build the new list in a bit.

public ArrayList<MemberInfo> removeMembers(int year) {
    for (int i=members.size() - 1; i>=0; i--) {
        MemberInfo member = members.get(i);
        if (member.getGradYear() == year) {
            members.remove(i);
        }
    }
}

Note that I’m going backwards here. I do that any time that I’m potentially removing values from a list because if you go forward, it’s possible to skip values. If you’re interested, I’ve done a YouTube video explaining this in more detail. Going backwards will introduce an issue that we’ll have to work around when we come back and create the list to return though.

public ArrayList<MemberInfo> removeMembers(int year) {
    ArrayList<MemberInfo> removed = new ArrayList<MemberInfo>();
    for (int i=members.size() - 1; i>=0; i--) {
        MemberInfo member = members.get(i);
        if (member.getGradYear() == year) {
            if (member.inGoodStanding()) {
                removed.add(0, member);
            }
            members.remove(i);
        }
    }
    return removed;
}

Note that once we pull a member out of the members ArrayList, we check to see if they’re graduating in the year we’re looking for. If they are, we check to see if they’re in good standing. If they are, we add them to the removed ArrayList. But, even if they’re not in good standing they’re removed from members.

Now, this may not actually matter after looking at the rubric. But I’m assuming that you probably want the list of removed members in the same order as they were in members. So, the line removed.add(0, member); adds each member to the beginning of the returned list so the order is maintained. The rubric doesn’t say anything about the order though, so it’s unlikely that it would matter if you used removed.add(member); and thethe removed list ended up being backwards. And the example given only has one member in the list, so you can’t tell from the example.

If you’d prefer to go forward through the list as you remove, you can do that with one addition.

public ArrayList<MemberInfo> removeMembers(int year) {
    ArrayList<MemberInfo> removed = new ArrayList<MemberInfo>();
    for (int i=0; i<members.size(); i++) {
        MemberInfo member = members.get(i);
        if (member.getGradYear() == year) {
            if (member.inGoodStanding()) {
                removed.add(member);
            }
            members.remove(i);
            i--;
        }
    }
    return removed;
}

Notice the i-- after we remove an element. That takes care of backtracking so that we don’t skip over any elements.

One thing you couldn’t do is to use a for each loop to iterate through members. If you did, and you tried to remove an element, you’d get a ConcurrentModificationException. This is because the ArrayList is being modified while you’re looping through it and Java doesn’t like that.

This site contains affiliate links. If you click an affiliate link and make a purchase we may get a small commission. It doesn't affect the price you pay, but it is something we must disclose.