=== 1. Comparator.comparing(StockPrice::ticker) - record accessor, no "get" prefix ===
StockPrice[ticker=AAPL, price=189.5, volume=42000000]
StockPrice[ticker=MSFT, price=410.2, volume=18000000]
StockPrice[ticker=NVDA, price=118.75, volume=210000000]

=== 2. Natural order via StockPrice.compareTo (price only) ===
StockPrice[ticker=NVDA, price=118.75, volume=210000000]
StockPrice[ticker=AAPL, price=189.5, volume=42000000]
StockPrice[ticker=MSFT, price=410.2, volume=18000000]

=== 3. Two DIFFERENT records, same price: compareTo==0 but equals()==false ===
StockPrice[ticker=AAPL, price=150.0, volume=1000000].compareTo(StockPrice[ticker=MSFT, price=150.0, volume=2000000]) = 0
StockPrice[ticker=AAPL, price=150.0, volume=1000000].equals(StockPrice[ticker=MSFT, price=150.0, volume=2000000]) = false

=== 4. That inconsistency reaches a TreeSet: natural order (price-only compareTo) ===
treeSet.add(appleAt150) -> true (first element)
treeSet.add(msftAt150)  -> false  (TreeSet used compareTo==0 to call this a duplicate)
treeSet now contains 1 element(s): [StockPrice[ticker=AAPL, price=150.0, volume=1000000]]
-> MSFT silently never entered the set, even though msftAt150.equals(appleAt150) is false

=== 5. Fix: a Comparator that is consistent with equals (ticker, then price, then volume) ===
treeSet.add(msftAt150) -> true  (now distinguishes the two records)
treeSet now contains 2 element(s): [StockPrice[ticker=AAPL, price=150.0, volume=1000000], StockPrice[ticker=MSFT, price=150.0, volume=2000000]]
