Part (a).
public int insertInOrder(Order o)
{
int index = 0;
while (index < orders.size() && orders.get(index).getMinutes() <= o.getMinutes())
{
index++;
}
orders.add(index, o);
return index;
}
Part (b).
public ArrayList<String> lateCustomers(int limit)
{
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < orders.size(); i++)
{
Order o = orders.get(i);
if (o.getMinutes() > limit)
{
names.add(o.getCustomer());
}
}
return names;
}
Part (a) is a scan that stops, not a scan that finishes. The while loop walks
index forward as long as two things are true: there is still an element to
look at, and that element belongs in front of o. The moment either fails,
index is exactly the slot o should occupy, and
add(index, o) puts it there and shifts everything from that slot onward one
place to the right. The order of the two tests joined by && is not a
style choice: && short-circuits, so index < orders.size()
must come first or the call orders.get(index) will run on an index past the
end. Part (b) is the plainest possible build-a-new-list traversal: declare the result
before the loop, look at every order once, append a name when the test passes, return the
result after the loop. A driver that builds the example log, makes each call in turn and
prints each order as customer/minutes produces exactly the table values:
start -> [Ortiz/22, Chen/35, Ortiz/41]
insertInOrder(Chen/35) -> 2
orders now -> [Ortiz/22, Chen/35, Chen/35, Ortiz/41]
insertInOrder(Nawaz/50) -> 4
orders now -> [Ortiz/22, Chen/35, Chen/35, Ortiz/41, Nawaz/50]
lateCustomers(30) -> [Chen, Chen, Ortiz, Nawaz]
lateCustomers(41) -> [Nawaz]
lateCustomers(90) -> []
orders unchanged by (b) -> [Ortiz/22, Chen/35, Chen/35, Ortiz/41, Nawaz/50]
empty insertInOrder(Pike/15)-> 0
empty orders now -> [Pike/15]
Where each of the 9 points is earned
- Traversal (1): the
while in part (a) starts at 0 and is guarded by index < orders.size(), so on an empty log it never runs (index stays 0) and on the 50-minute insertion it stops with index equal to 4, the size of the list. The for in part (b) runs i from 0 through 4 on the five-element list.
- Accessing elements with
get (1): part (a) uses orders.get(index).getMinutes() and part (b) pulls the element into Order o once and then asks it for both its minutes and its customer. Neither touches customer or minutes directly, which would not compile outside Order.
- Comparison logic (1):
<= in part (a) is what makes the tie land after the existing 35-minute order and return 2 instead of 1; > limit in part (b) is what keeps the 41-minute order out of lateCustomers(41) while leaving Nawaz in.
- Accumulation (1):
names is created before the loop, so it survives every pass, and names.add(o.getCustomer()) runs only inside the if, which is why lateCustomers(30) returns four names, keeping the repeated Chen, and lateCustomers(90) returns an empty list.
- Correct insertion without skipping or disturbing order (1): a single
orders.add(index, o) does the whole job. The list is never rebuilt, nothing is removed, and the elements at and after index shift right, so Ortiz/41 moves from index 2 to index 3 and the list is still sorted.
- Return (1): part (a) returns
index after the insertion, so the caller learns where the order landed; part (b) returns names after the loop rather than returning on the first match, which is why all four late names come back instead of only the first.
- Uses the given classes as specified (1): only
size(), get(int), add(int, Order) and add(String) are used, each on a list with the right type parameter, and both Order accessors do all the reading.
- Java that would compile (1): both headers are copied from the question,
int index is declared before the while so it is still in scope at the return, names is declared as ArrayList<String> and created with new, and every path out of each method returns a value of the declared type.
- Design and encapsulation (1):
lateCustomers calls no mutator on orders, so the postcondition "orders is unchanged" holds, as the last driver line confirms; insertInOrder performs exactly one insertion; neither method prints; and neither walks the list twice when one pass does the work.
Common ways to lose points. The first is the comparison that decides the
tie. Writing the scan as orders.get(index).getMinutes() < o.getMinutes()
stops one slot too early on a tie: on the example list that call returns 1 instead of 2
and leaves the new order in front of the 35-minute order already there. The list
is still sorted, so the bug is easy to miss, but the returned index is wrong and the
specification's "after any order with the same minutes" is broken. The second is dropping
the index < orders.size() guard, or putting it after the get.
Inserting Nawaz/50 then crashes with
java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3, and
inserting into an empty log crashes with
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0:
both of the edge cases the question spells out.
The third is reaching for an enhanced for loop in part (a). An
ArrayList may not be structurally modified while a
for (Order cur : orders) loop is iterating over it, so a version that calls
orders.add(index, o) inside the loop and keeps going throws
java.util.ConcurrentModificationException at run time. The enhanced
for also hides the index, and the index is the value you have to return, so
it is the wrong tool here twice over. The fourth is answering part (b) by emptying
orders of the on-time orders and reading off what is left. That is where the
forward-removal skip from the sibling question bites: a
for (int i = 0; i < orders.size(); i++) loop that removes at
i steps over the element that slides into the vacated slot, so on the final
list it reports [Chen, Ortiz, Nawaz] for limit 40 instead of the
correct [Ortiz, Nawaz], and the same idea written with an enhanced
for throws ConcurrentModificationException instead. Even when
such a version somehow produces the right names, it destroys the caller's log, which
costs the design point outright: the question says to return a new list, so build a new
list. Finally, printing the index or the names instead of returning them, or returning
null when nothing qualifies, both fail the return point even though the
traversal above them is correct.