Є кілька випадків, коли ви вважаєте за краще використовувати незмінні карти, списки, набори чи інші типи колекцій.
Перший і, мабуть, найважливіший випадок використання - це кожен раз, коли ви повертаєте результат запиту чи обчислення, що повертає набір (або список чи карту) результатів, слід віддавати перевагу використанню змінних структур даних.
У цьому випадку я вважаю за краще повертати незмінні версії цих версій, оскільки це відображає фактичну незмінність набору результатів обчислення набагато чіткіше - незалежно від того, що ви робите з даними пізніше, набір результатів, отриманих у вашому запиті, не повинен змінити.
Другий випадок загального використання - це коли вам потрібно надати аргумент як вхід до методу чи послуги. Якщо ви не очікуєте, що колекція входів буде модифікована службою чи методом (що зазвичай є дуже поганою ідеєю дизайну), передача в незмінну колекцію замість змінної може бути розумним і безпечним вибором у багатьох випадках.
Я вважаю це конвенцією "передачі цінності" .
Більш загально - розумна практика використовувати незмінні структури даних, коли дані перетинають модуль або межі обслуговування. Це значно спрощує міркування про відмінності між (незмінним) входом / виходом та зміненим внутрішнім станом.
Як дуже корисний побічний ефект цього - підвищена безпека та безпека потоків ваших модулів / служб та забезпечує більш чітке розділення проблем.
Ще однією вагомою причиною використання Collections.empty*()
методів є їх помітна відсутність багатослівності. У епоху перед Java7, якщо у вас була загальна колекція, вам довелося розповсюджувати примітки загального типу всюди.
Просто порівняйте ці дві декларації:
Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();
проти:
Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();
Останній чітко виграє «читання» двома важливими способами:
- У першій декларації вся інстанція порожньої карти закопується в шум декларацій загального типу, що робить по суті тривіальне оголошення набагато більш виразним, ніж потрібно.
- Окрім помітної відсутності анотації загального типу з правого боку, друга версія чітко говорить про те, що карта ініціалізується на порожню карту. Крім того - знаючи, що цей метод повертає непорушну карту, мені зараз легше знайти, куди
fooBarMap
призначається інше непорожнє значення, просто за допомогою пошуку /fooBarMap =/
.