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())来解决。由此产生的冗长性将远远超过使用不可变集合的好处所抵消,并且类型系统将防止调用错误方法的错误。随着时间的流逝,旧的方法可能会被弃用。
永恒收藏的胜利:
- 简单性-当基础数据不变时,关于代码的推理就更简单了。
- 文档-如果某个方法采用不可变的集合接口,则您将知道它不会修改该集合。如果某个方法返回一个不可变的集合,则说明您无法对其进行修改。
- 并发-不可变集合可以在线程之间安全地共享。
作为尝过假定不变性的语言的人,很难回到猖mutation的突变的狂野西部。Clojure的集合(序列抽象)已经具有Java 8集合提供的所有功能以及不可变性(尽管由于同步的链表而不是流,因此可能会使用额外的内存和时间)。Scala具有可变的集合和不可变的集合,具有完整的操作集,尽管这些操作很急切,但调用.iterator可以提供一个惰性视图(还有其他惰性评估它们的方法)。我看不出没有不可变的集合,Java如何能够继续竞争。
有人可以指出我的历史或讨论吗?当然,它在某个地方是公开的。
const
收藏
Collections.unmodifiable*()
的用途。但不要将它们视为不可变的
ImmutableList
在该图中采用,人们可以传递可变的List
?不,这是一个非常糟糕的违反LSP的。