Команда Java проделала огромную работу по устранению барьеров для функционального программирования в Java 8. В частности, изменения в коллекциях java.util делают большую работу по объединению преобразований в очень быстрые потоковые операции. Учитывая, как хорошо они проделали работу, добавив первоклассные функции и функциональные методы к коллекциям, почему они полностью не смогли обеспечить неизменные коллекции или даже неизменные интерфейсы коллекций?
Без изменения какого-либо существующего кода команда Java может в любое время добавить неизменяемые интерфейсы, такие же как изменяемые, минус методы "set" и заставить существующие интерфейсы расширяться от них, например так:
ImmutableIterable
____________/ |
/ |
Iterable ImmutableCollection
| _______/ / \ \___________
| / / \ \
Collection ImmutableList ImmutableSet ImmutableMap ...
\ \ \_________|______________|__________ |
\ \___________|____________ | \ |
\___________ | \ | \ |
List Set Map ...
Конечно, такие операции, как List.add () и Map.put (), в настоящее время возвращают логическое или предыдущее значение для данного ключа, чтобы указать, была ли операция успешной или неудачной. Неизменяемые коллекции должны обрабатывать такие методы как фабрики и возвращать новую коллекцию, содержащую добавленный элемент, что несовместимо с текущей подписью. Но это можно обойти, используя другое имя метода, например, ImmutableList.append () или .addAt () и ImmutableMap.putEntry (). Результирующая многословность будет более чем перевешена преимуществами работы с неизменяемыми коллекциями, а система типов предотвратит ошибки вызова неправильного метода. Со временем старые методы могут устареть.
Победы неизменных коллекций:
- Простота - рассуждения о коде проще, когда базовые данные не меняются.
- Документация - если метод принимает неизменяемый интерфейс коллекции, вы знаете, что он не собирается изменять эту коллекцию. Если метод возвращает неизменную коллекцию, вы знаете, что не можете ее изменить.
- Параллелизм - неизменяемые коллекции можно безопасно разделять между потоками.
Как человеку, который пробовал языки, которые предполагают неизменность, очень трудно вернуться на Дикий Запад с безудержной мутацией. Коллекции Clojure (абстракция последовательностей) уже имеют все, что обеспечивают коллекции Java 8, плюс неизменяемость (хотя, возможно, использование дополнительной памяти и времени из-за синхронизированных списков ссылок вместо потоков). В Scala есть как изменяемые, так и неизменяемые коллекции с полным набором операций, и, хотя эти операции нетерпеливы, вызов .iterator дает ленивое представление (и существуют другие способы их ленивой оценки). Я не понимаю, как Java может продолжать конкурировать без неизменных коллекций.
Может кто-нибудь указать мне на историю или обсуждение этого? Конечно, это где-то публично.
const
коллекции
Collections.unmodifiable*()
. но не относитесь к ним как к неизменным, когда это не так
ImmutableList
в этой диаграмме, люди могут перейти в изменчивый List
? Нет, это очень плохое нарушение LSP.