Guava学习之Collections——Immutable Collections

Immutable Collections

Example

public static final ImmutableSet<String> COLOR_NAMES 
   = ImmutableSet.of( "red", "orange", "yellow", "green", "blue", "purple"); 
class Foo { 
   final ImmutableSet<Bar> bars; 
   Foo(Set<Bar> bars) { 
      this.bars = ImmutableSet.copyOf(bars); // 保护性拷贝! 
   } 
}

 

Why?

Immutable 类有着很多优势,包括:

  • 不被信任的库实现了安全。
  • 线程安全: 能够在无竞争条件风险下被许多线程使用。
  • 不需要支持变化并且在此前提下节省时间与空间。所有 immutable collection 的实现对内存的操作都比可变类更加有效率. (analysis)
  • 可以期望它保持不变当做常量使用。

制作对象的不可变副本是一种很好的防错性程序设计。Guava 提供简易的 immutable版本与标准 Collection 类型, 包含 Guava's 自己的 Collection 改进.

 

JDK 也提供的 Collections.unmodifiableXXX 方法, 但在我们看来:

  • 笨拙冗长;不能在你想做防御性拷贝的任何地方使用。
  • 不安全: 如果没有任何对象拥有原始集合的拷贝返回的集合才是真正的 immutable
  • 效率低: 数据结构仍然具有可变集合的所有开销,包括并发修改检查、哈希表中的额外空间等。

当你不想修改集合,或者想将该集合当做常量,一种较好的做法是做防御性拷贝进immutable collection中

重要: 任何 Guava immutable collection实现都拒绝null值. 我们对谷歌的内部代码基础做了详尽的研究,它表明在5%的情况下允许null在集合中存储,而其他95%的情况最好遇到null后快速失败。如果你想使用null,考虑一下使用Collections.unmodifiableList ,细节请访问这里 here.

 

How?

创建ImmutableXXX 集合的方式有很多:

  • 使用 copyOf 方法,例如, ImmutableSet.copyOf(set)
  • 使用 of 方法, 例如, ImmutableSet.of("a", "b", "c") or ImmutableMap.of("a", 1, "b", 2)
  • 使用 Builder, 例如,
public static final ImmutableSet<Color> GOOGLE_COLORS 
    = ImmutableSet.<Color>builder()              
                  .addAll(WEBSAFE_COLORS) 
                  .add(new Color(0, 191, 255)) 
                  .build();

除了sorted collections, 顺序由插入时间决定. 例如,

ImmutableSet.of("a", "b", "c", "a", "d", "b")

将按顺序对其元素进行迭代 "a", "b", "c", "d".

 

copyOf 比你想象的更智能

值得记住的是,ImmutableXXX.copyOf试图避免在安全的时候复制数据——确切的细节是未指定的,但实现通常是“聪明的”。例如,

ImmutableSet<String> foobar = ImmutableSet.of("foo", "bar", "baz");
thingamajig(foobar);
void thingamajig(Collection<String> collection) { 
    ImmutableList<String> defensiveCopy = ImmutableList.copyOf(collection); ... 
}

在上面的代码中, ImmutableList.copyOf(foobar) 将聪明的只返回foobar.asList()是ImmutableSet的一个固定时间视图。

作为一般的启发, ImmutableXXX.copyOf(ImmutableCollection) 尝试避免线性时间拷贝。

  • 有可能在固定的时间内使用底层数据结构。例如, ImmutableSet.copyOf(ImmutableList) 不能在固定的时间内完成。
  • 将引起内存泄漏 -- 例如, 现有 ImmutableList<String> hugeList, 对它进行 ImmutableList.copyOf(hugeList.subList(0, 10))操作, 执行一个显式拷贝,以避免在不需要的HugListor中意外引用。
  • 它不会改变语义 -- 因此 ImmutableSet.copyOf(myImmutableSortedSet) 将执行显式拷贝, 因为 ImmutableSet使用的hashCode() 与 equals 有着与ImmutableSortedSet不同的比较器语义。

这有助于最小化防御编程风格的性能开销。

 

asList

所有的immutable collections 都通过asList()提供ImmutableList 视图, 例如 -- 即使你利用even if ImmutableSortedSet排序了数据, 你依旧可以使用sortedSet.asList().get(k)来获取第k个最小的元素。

ImmutableList 的返回是流式的-- 不总是,但经常 -- 一个固定的开销视图,而不是一个显式拷贝。也就是说,它通常比你的List 更聪明。 -- 例如, 其使用有效的contains方法去备份集合。

Details

Where?

InterfaceJDK or Guava?Immutable Version
CollectionJDKImmutableCollection
ListJDKImmutableList
SetJDKImmutableSet
SortedSet/NavigableSetJDKImmutableSortedSet
MapJDKImmutableMap
SortedMapJDKImmutableSortedMap
MultisetGuavaImmutableMultiset
SortedMultisetGuavaImmutableSortedMultiset
MultimapGuavaImmutableMultimap
ListMultimapGuavaImmutableListMultimap
SetMultimapGuavaImmutableSetMultimap
BiMapGuavaImmutableBiMap
ClassToInstanceMapGuavaImmutableClassToInstanceMap
TableGuavaImmutableTable

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值