Explain the NavigableSet navigation methods (floor, ceiling, lower, higher) and how they differ.
answer
- floor ≤ , ceiling ≥ (inclusive)
- lower < , higher > (strict)
- Target need not be in the set
- All four return null when nothing qualifies
- pollFirst/pollLast remove the ends; descendingSet reverses
basics
~20 sThey find the nearest element to a given value. ceiling returns the smallest element >= the value; floor the largest <= it; higher is strictly greater; lower is strictly less. They return null if no such element exists.
solid answer
~40 sTreeSet implements NavigableSet, which adds nearest-neighbour lookups. Given a target value: floor(x) returns the greatest element <= x; ceiling(x) returns the least element >= x; lower(x) returns the greatest element strictly < x; higher(x) returns the least element strictly > x. The 'floor/ceiling' pair is inclusive of an exact match, while 'lower/higher' are strict (exclusive). Each runs in O(log n) by walking the red-black tree. All four return null when no qualifying element exists — and note the target itself need not be a member of the set. NavigableSet also gives pollFirst/pollLast (retrieve-and-remove the ends), descendingSet/descendingIterator for reverse traversal, and the range views headSet/tailSet/subSet, all of which can take inclusive/exclusive boundary flags. These methods make TreeSet ideal for problems like 'find the closest price at or below budget'.
go deeper
Can roughly say these find nearby elements and that ceiling is the next-up value.
States the exact ≤/≥/strict semantics of floor/ceiling/lower/higher and that they return null when empty.
Connects them to O(log n) tree descents, knows pollFirst/pollLast and descendingSet, and applies them to range/proximity problems.
Chooses TreeSet over alternatives based on the access pattern (ordered + nearest-neighbour) and reasons about API ergonomics like null-returning navigation vs Optional.
## Setup A **NavigableSet** is a `SortedSet` with extra methods for finding elements *near* a given value. `TreeSet` is the standard implementation. Because the elements are kept sorted in a balanced tree, the set can answer 'what's the nearest element to X?' in **O(log n)** by descending the tree. ## The four nearest-neighbour methods Imagine the sorted set `{10, 20, 30, 40}` and a target value `t`: | Method | Meaning | Inclusive of exact match? | |---|---|---| | `floor(t)` | greatest element **≤ t** | yes | | `ceiling(t)` | least element **≥ t** | yes | | `lower(t)` | greatest element **< t** (strictly) | no | | `higher(t)` | least element **> t** (strictly) | no | Worked examples on `{10,20,30,40}`: - `floor(25)` → 20, `ceiling(25)` → 30 (25 isn't present; we get the neighbours). - `floor(30)` → 30, `ceiling(30)` → 30 (exact match, inclusive). - `lower(30)` → 20, `higher(30)` → 40 (strict, so they skip 30 itself). - `floor(5)` → **null** (nothing is ≤ 5), `higher(40)` → **null** (nothing > 40). **Key points:** (1) the target `t` does **not** have to be in the set; (2) all four return **null** when no element qualifies — always null-check the result. ## Memory aid - **Floor** = the floor is *below* you → largest value not above the target. - **Ceiling** = the ceiling is *above* you → smallest value not below the target. - **lower / higher** = the *strict* versions (never equal to the target). ## Related NavigableSet members - `first()` / `last()` — smallest / largest element (from SortedSet). - `pollFirst()` / `pollLast()` — return **and remove** the smallest/largest; great for using a TreeSet as a priority structure. - `descendingSet()` — a reverse-order **view** of the same set; `descendingIterator()` iterates high→low. - `headSet`, `tailSet`, `subSet` — range views (covered separately), each with inclusive/exclusive flags in the NavigableSet overloads. ## Why it matters These turn a TreeSet into a tool for **range and proximity queries**: 'cheapest item at or above my minimum', 'last event before timestamp T', 'next available slot after now'. A HashSet cannot do any of this. ## Complexity Each navigation call is **O(log n)** — one root-to-leaf descent. Returning a range *view* is O(log n) to locate the boundary; iterating it is proportional to the number of elements visited.
- On TreeSet {10,20,30}, what do ceiling(20) and higher(20) return?ceiling(20) returns 20 (inclusive of the exact match); higher(20) returns 30 (strictly greater, so it skips 20).
- How would you pop the smallest element off a TreeSet efficiently?Use pollFirst(), which returns and removes the least element in O(log n); pollLast() does the same for the greatest.
saying these in an interview costs you the question
- Mixing up floor (≤) and ceiling (≥)
- Thinking lower/higher are inclusive
- Assuming the target must already be in the set
- Forgetting these can return null and dereferencing it (NPE)
- Believing HashSet offers these (it doesn't)