2020 AP CSA Sample Q1 - Gizmo (ArrayList of Objects)

Topic: ArrayList operations with objects, traversal, and detecting adjacent pairs

Skills Tested: ArrayList traversal, calling object methods, counting with conditions, comparing adjacent elements

Curriculum Alignment: Unit 4 (Data Collections - ArrayList)

Allotted Time: 25 minutes (plus 5 minutes to submit)

¹ Note: This is a sample question from the 2020 at-home exam format. Part (c) asks for a written description rather than code.

Question

The Gizmo class represents gadgets that people purchase. Some Gizmo objects are electronic and others are not.

Provided Gizmo Class

public class Gizmo
{
    /** Returns the name of the manufacturer of this Gizmo. */
    public String getMaker()
    { /* implementation not shown */ }

    /** Returns true if this Gizmo is electronic, and false otherwise. */
    public boolean isElectronic()
    { /* implementation not shown */ }

    /** Returns true if this Gizmo is equivalent to the Gizmo object
     *  represented by the parameter, and false otherwise.
     */
    public boolean equals(Object other)
    { /* implementation not shown */ }

    // There may be instance variables, constructors, and methods not shown.
}

OnlinePurchaseManager Class

public class OnlinePurchaseManager
{
    /** An ArrayList of purchased Gizmo objects, instantiated in the constructor. */
    private ArrayList purchases;

    /** Returns the number of purchased Gizmo objects that are electronic and are
     *  manufactured by maker, as described in part (a).
     */
    public int countElectronicsByMaker(String maker)
    { /* to be implemented in part (a) */ }

    /** Returns true if any pair of adjacent purchased Gizmo objects are equivalent, and
     *  false otherwise, as described in part (b).
     */
    public boolean hasAdjacentEqualPair()
    { /* to be implemented in part (b) */ }

    // There may be instance variables, constructors, and methods not shown.
}

Part (a): Write countElectronicsByMaker

Write the countElectronicsByMaker method. The method examines the ArrayList instance variable purchases to determine how many Gizmo objects purchased are electronic AND are manufactured by maker.

Example Data

Index isElectronic() getMaker()
0 true "ABC"
1 false "ABC"
2 true "XYZ"
3 false "lmnop"
4 true "ABC"
5 false "ABC"
Method Call Return Value
opm.countElectronicsByMaker("ABC") 2
opm.countElectronicsByMaker("lmnop") 0
opm.countElectronicsByMaker("XYZ") 1
opm.countElectronicsByMaker("QRP") 0

Part (b): Write hasAdjacentEqualPair

When purchasing items online, users occasionally purchase two identical items in rapid succession without intending to (e.g., by clicking a purchase button twice). A vendor may want to check a user's purchase history to detect such occurrences.

Write the hasAdjacentEqualPair method. The method detects whether two adjacent Gizmo objects in purchases are equivalent, using the equals method of the Gizmo class.

  • If an adjacent equivalent pair is found, return true
  • If no such pair is found, OR if purchases has fewer than two elements, return false

Part (c): Design Discussion

A programmer would like to add a method getCheapestGizmoByMaker, which returns the least expensive Gizmo purchased by an individual from a given maker.

Write a description of how you would change the Gizmo and OnlinePurchaseManager classes to support this modification. (No code required)

Part (a) Solution: countElectronicsByMaker

✔ Try It Yourself First! Attempt to write your solution before viewing the answer below.

Solution Code

public int countElectronicsByMaker(String maker)
{
    int count = 0;
    
    for (int i = 0; i < purchases.size(); i++)
    {
        Gizmo g = purchases.get(i);
        
        if (g.isElectronic() && g.getMaker().equals(maker))
        {
            count++;
        }
    }
    
    return count;
}

Alternative using enhanced for loop:

public int countElectronicsByMaker(String maker)
{
    int count = 0;
    
    for (Gizmo g : purchases)
    {
        if (g.isElectronic() && g.getMaker().equals(maker))
        {
            count++;
        }
    }
    
    return count;
}

Explanation

  1. Initialize counter: Start with count = 0.
  2. Iterate through purchases: Use either indexed or enhanced for loop.
  3. Check both conditions: Must be electronic AND from the specified maker.
  4. Increment if match: Only count if both conditions are true.
  5. Return final count.
¡ Key Insight: Use .equals() for String comparison! The condition g.getMaker().equals(maker) compares the string content, while g.getMaker() == maker would compare object references (and likely fail).

Part (b) Solution: hasAdjacentEqualPair

✔ Try It Yourself First! Attempt to write your solution before viewing the answer below.

Solution Code

public boolean hasAdjacentEqualPair()
{
    // Need at least 2 elements to have an adjacent pair
    if (purchases.size() < 2)
    {
        return false;
    }
    
    for (int i = 0; i < purchases.size() - 1; i++)
    {
        if (purchases.get(i).equals(purchases.get(i + 1)))
        {
            return true;
        }
    }
    
    return false;
}

Alternative (size check built into loop):

public boolean hasAdjacentEqualPair()
{
    for (int i = 0; i < purchases.size() - 1; i++)
    {
        if (purchases.get(i).equals(purchases.get(i + 1)))
        {
            return true;
        }
    }
    return false;
}
¡ Practice Tip: The alternative works because if purchases.size() is 0 or 1, then purchases.size() - 1 is -1 or 0, and the loop condition i < purchases.size() - 1 is immediately false, so the loop doesn't execute.

Explanation

  1. Check minimum size: Need at least 2 elements for adjacent pairs (optional but clear).
  2. Loop through adjacent pairs: Stop at size() - 1 because we compare i with i + 1.
  3. Use equals method: The problem specifies using Gizmo's equals method.
  4. Return true immediately: As soon as we find a match, return true.
  5. Return false if no match: Only after checking all pairs.
¡ Adjacent Pair Pattern: When comparing adjacent elements, always loop to size() - 1 (not size()) to avoid an IndexOutOfBoundsException when accessing i + 1.

Part (c): Design Discussion

This part asks you to describe (not code) how to add getCheapestGizmoByMaker.

Sample Response:

To implement getCheapestGizmoByMaker, I would make the following changes:

Changes to the Gizmo class:

  • Add a private instance variable private double price to store the price of the gizmo
  • Add a public accessor method public double getPrice() that returns the price
  • Modify the constructor to accept and initialize the price parameter

Changes to the OnlinePurchaseManager class:

  • Add the method header: public Gizmo getCheapestGizmoByMaker(String maker)
  • This method would iterate through purchases, track the minimum price seen for gizmos from the specified maker, and return the Gizmo with the lowest price

Common Mistakes to Avoid

Part (a) Common Errors:

  • Using == instead of .equals(): For String comparison, always use .equals()
  • Only checking one condition: Must check electronic AND maker, not just one
  • Using || instead of &&: Both conditions must be true
  • Forgetting to return: Must return the count at the end

Part (b) Common Errors:

  • Loop bound error: Using purchases.size() instead of purchases.size() - 1
  • Comparing non-adjacent elements: Must compare i with i + 1
  • Using == instead of .equals(): For object comparison, use .equals()
  • Not handling empty/single-element list: Should return false for lists with fewer than 2 elements
  • Returning too late: Should return true immediately when a pair is found

Official College Board Resources

Last updated:

Related Practice: ArrayList Operations

Similar FRQs:

Study Guide:

Daily Practice:

Contact form