guava之不可变集合(Immutable collections)

9 篇文章 0 订阅

示例

public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
"red",
"orange",
"yellow",
"green",
"blue",
"purple");

class Foo {
	Set<Bar> bars;
	Foo(Set<Bar> bars) {
		this.bars = ImmutableSet.copyOf(bars);
	}
}

Why

不可变对象有很多好处,包括:

  • 可以安全的被不信任的库使用
  • 线程安全:可用在多线程中,且不存在资源竞争
  • 不可变性,可以节省时间和空间。所有不可变集合的实现都比其可变的实现占用较少的资源,效率也较较高(分析
  • 可以当作常量使用

使用对象的不可变拷贝是一个好的防御式编程技术,Guava为每一个标准的集合类型都提供了简单,方便使用的不可变版本,包括Guava自己的集合类。

JDK提供了Collections.unmodifiableXxx方法,但是在我们看来,它有以下缺点:

  • 笨重并且冗余,在任何想使用防御式拷贝的地方使用非常不友好
  • 不安全,返回的集合仅在没有任何地方持有其引用的时候才真正的不可变
  • 效率低下,这种数据结构所需的开销仍与可变集合相同,包括并发写检查,哈希表所占用的额外空间等

当不需要改变集合或希望将其作为常量的时候,使用防御式拷贝将其拷贝到不可变的集合中是非常好的实践。

注意: Guava的所有不可变集合的实现都不允许null值。我们在Google内部基础代码上作了详细的测试,报告显示仅有5%的时候是允许null元素的存在,其余95%的时候都是在遇到null的时候越快抛出异常越好。如果你需要null值,考虑使用Collections.unmodifiableList等允许null的方法的实现。更详细的信息参见这里

How

有以下几种方式创建一个ImmutableXxx集合:

  • 使用copyOf方法,例如ImmutableSet.copyOf(set)
  • 使用of方法,例如ImmutableSet.of("a", "b", "c")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();

除了有序集合,顺序在构造的时候就已经处理过了,例如: ImmutableSet.of("a", "b", "c", "a", "d", "b") 在迭代的时候的顺序为a->b->c->d。

copyOf比想象中的要智能

ImmuableXxx.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)),拷贝会立即执行,是为了避免持有不需要的hugeList的引用。
  • 不会改变语义,ImmutableSet.copyOf(myImmutableSortedSet)会执行一个拷贝,因为ImmutableSet使用的hashCode()equals()方法与基于Comparator行为的ImmutableSortedSet具有不同的语义。

这些都是为了在防御式编程风格中保持最小的性能开销。

asList

所有的不可变集合都通过asList方法提供了一个ImmutableList视图,所以如果你有数据存在ImmutableSortedSet中,依然可以通过sortedSet.asList().get(k)来获取第k小的元素。

返回的ImmutableList通常(但不总是)是开销固定的视图而不是一个明确的拷贝。意思就是说它通常比一般的List要智能,例如,它使用了后向集合的更高效的contains()方法。

更多

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、付费专栏及课程。

余额充值