LogMessage, the second free response question on the 2016 AP Computer Science exam, has you working with strings and ArrayLists.
For the constructor you are given a String parameter message that is guaranteed to contain exactly one :
character. Everything to the left of the colon goes into an instance variable called machineId
and everything after goes into description
.
Using the AP Java subset, this is an indexOf
problem. First you need to find where the colon is in message and then use that number to substring
out everything before and after.
public LogMessage( String message ) {
int pos = message.indexOf(":");
machineId = message.substring(0, pos);
description = message.substring(pos + 1);
}
pos
is the position of the colon.
The other option, if you’re willing to go a bit out of the Java subset, is to use the String split
method. It splits a string into an array of strings based on a regular expression. Since a colon isn’t part of regex, we can just put the colon in quotes.
public LogMessage( String message ) {
String[] spl = message.split(":");
machineId = spl[0];
description = spl[1];
}
Next you’re going to implement a method called containsWord
that returns true
or false
if a keyword is found in description matching a specific set of rules.
keyword
is found in descriptionkeyword
is either
description
and has a space after itdescription
and has a space before itdescription
with a space before and afterFor a solution that stays within the subset, we’re going to use indexOf
and substring
.
public boolean containsWord( String keyword ) {
if (keyword.equals(description))
return true;
else if (description.indexOf(keyword + " ") == 0)
return true;
else if (description.indexOf(" " + keyword + " ") >= 0)
return true;
else if (description.length() > keyword.length()
&& description.indexOf(" " + keyword) == description.length() - keyword.length() - 1)
return true;
return false;
}
I broke this down to 4 cases, any of which should return true
description
and keyword
are exactly the samedescription
starts with keyword
followed by a spacekeyword
is somewhere in description
with spaces both before and afterkeyword
is at the end of description
with a space before itThe last case took a bit more work because it failed when the keyword
and description
were the same length, but not equal. So my last condition checks both of those things.
This is a solution that one of my students shared with me.
public boolean containsWord( String keyword ) {
return (" " + description + " ").indexOf(" " + keyword + " ") >= 0;
}
Their code pads description
with spaces on both ends and looks for keyword
padded with spaces. This is one of those snippets of code that I really like to see from students because it shows they really understand the question and the methods needed to solve it.
This also could have been solved using regular expressions, although that would have been way out of the AP Java subset.
public boolean containsWord( String keyword ) {
return description.matches(".*(\\s|^)" + keyword + "(\\s|$).*");
}
The short explanation is that this looks to see if description
matches anything, followed by either the start of the string or whitespace, followed by keyword
followed by whitespace or the end of the string, followed by anything.
Even if I was really comfortable with regex I still wouldn’t have written this solution during the actual AP exam. I’d be too worried that the grader might not be familiar with regex and would count it incorrect.
And last you’re going through a list of LogMessage
objects and removing those that contain a specific keyword.
public List<LogMessage> removeMessages( String keyword ) {
List<LogMessage> out = new ArrayList<>();
for (int i=messageList.size() - 1; i>=0; i--) {
if (messageList.get(i).containsWord(keyword)) {
out.add(0, messageList.remove(i));
}
}
return out;
}
I created a new List
called out that’s going to contain the LogMessages
that were removed.
I then went backwards through messageList
looking for LogMessages
that contained the keyword
. I like to go backwards when removing from a List
because it keeps the loop from skipping over elements after a removal.
And when it finds one to remove, it gets added at the beginning of out
. It has to be inserted at position zero because of the backwards loop. Otherwise out
would be backwards.