欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Google Guava集合4:创建方法和只读特性 googleguavacollectioncreateimmutable

程序员文章站 2022-07-13 09:14:18
...
Google guava 集合的创建特性和只读特性

现在,让我们一起看看guava集合的创建模式,再看看guava提供的一些只读的集合类型。

如果你还不了解guava集合,那么可以参考我之前写的文档:

Guava集合1:MultiMap
http://vipcowrie.iteye.com/blog/1517338
Guava集合2:BiMap
http://vipcowrie.iteye.com/blog/1521092
Guava集合3:MultiSet
http://vipcowrie.iteye.com/blog/1517196

创建方法:
  所有的Guava的集合实现都包含一些静态的创建方法,这些方法执行你期望的操作,并且也提供一些更加准确的创建方法。

这里演示两种创建ArrayListMultimap的方法:

Multimap<String,String> multimap1 = new ArrayListMultimap<String,String>();

Multimap<String,String> multimap2 = ArrayListMultimap.create();


第一种方法看起来很臃肿,因为我们写了两遍泛型的定义,不烦么?JDK没有提供类似的方法,即定义集合的时候必须写两遍泛型定义的问题SUN公司没有考虑到。

Google guava提供了补救的方法,com.google.common.collect.Lists(Sets,Maps)提供了一些静态的方法供程序员便捷的创建JDK的集合类,一般此类方法的
命名规则就是:xxx.newXxxtype(),下面是一些例子:

List<String> myList1 = new ArrayList<String>(); //old way
List<String> myList2 = Lists.newArrayList(); //guava way
Set<String> mySet1 = new HashSet<String>(); //old way
Set<String> mySet2 = Sets.newHashSet(); //guava way


因为newXxx方法都是静态的,所以可以通过static import的方式更加简化,例如:

import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;

//elsewhere in code

List<String> myList2 = newArrayList();
Set<String> mySet2 = newHashSet();


静态引用虽然简单,但是不推荐使用,因为别人读起来可能比较麻烦。好,下面介绍一下只读的集合。

所谓只读的集合,就是那些一旦创建就不能修改的集合,这个在某些场景下可能很有用。Guava为大多数的集合接口提供只读的实现,例如:ImmutableList,ImmutableSet和ImmutableMap等等。这里我举一个定义常量的例子,例如:

private static final Set<String> farmAnimals = new HashSet<String>(Arrays.asList("Cow","Pig","Sheep"));


看起来很复杂是不是,这个集合有一个问题,虽然是final的,但是里面的元素还是可能被修改的,这可能带来很多问题。jdk的集合有一个方法:Collection.unmodifiableSet(Set s),是否可以用这个方法解决问题呢:

private static final Set<String> farmAnimals = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("Cow","Pig","Sheep")));


这个能确实达到效果,即不可修改farmAnimals的元素,但是有两个问题,一个是这个创建代码太长,另外一个就是Collections.unmodifiableSet实际上是返回了一个只读的视图,如果有其他对象持有内部的hashset的引用,那么一样可以修改里面的元素。所以,还有一个更好的办法:

private static final Set<String> farmAnimals =ImmutableSet.of("Cow","Pig","Sheep");


看起来比较简洁吧,另外还有一些方法来创建只读的集合,例如:
// use copyOf()...
public void doStuffWithList(List<Object> unsafeList) {
List<Object> safeList = ImmutableList.copyOf

(unsafeList);
}

// use a builder...
public Map<String,Integer> makeImmutableMap() {

ImmutableMap.Builder<String,Integer> mapBuilder = new 

ImmutableMap.Builder<String,Integer>();

Entry<String,Integer> entry = null;

while((entry = getEntry()) != null) {

mapBuilder.put(entry.getKey(), entry.getValue());

}
return builder.build();
}


还有很多方法。这个只读的集合在多线程的环境中很有用,因为这样就不用考虑使用同步机制来保证集合的完整性了。

但是只读的集合也有劣势,包括:
1)只读:只读本身就是一个劣势,如果你希望后面再修改的话,只能再创建一个集合的拷贝了
2)仍然可能被修改:集合的对象虽然不能被增删,但是对象本身如果有的属性可以修改,那么对象也可以直接被引用者修改,所以,你如果真的要一个只读集合的话,那么请你确保里面的对象也是只读的。