List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); List<String> immutableList = Collections.unmodifiableList(list);
使用com.google.common.collect.ImmutableList示例:
List<String> immutableList = ImmutableList.of("1","2","3");
com.google.common.collect.ImmutableFoo都是通过调用静态的of方法生成新的不变集合,该方法的参数是个可变数组。因为ImmutableFoo只提供读操作并自己维护数据,所以性能方面会比java.util中集合类有所提高。另外要说的是,不变集合并不能左右其包含的元素是否可变,所以不变集合中的元素最好也是不变的。
Multiset & Multimap
java.util.Set是个无序且元素不重复的集合。而Multiset是个无序但添加元素可重复的集合,对添加的重复元素,以计数表示多少。Multiset的实现也是支持多种类型的(比如Hash、LinkedList等)下面是使用片断:
Multiset<String> set = HashMultiset.create(); set.add("kafka0102"); set.add("kafka0102"); System.out.println(set.count("kafka0102"));//输出2 set.setCount("kafka0102", 5); System.out.println(set.count("kafka0102"));//输出5
这个Multiset还是有很多应用场景的,比如统计用户访问计数,没有Multiset,就需要使用如Map来做,每次累加都需要先取出原有的计数值再加一后放回去,自然不如Multiset使用的方便。
Multimap也是很方便实用的集合,对于形如Multimap<K,V>的map,它相当于Map<K,Collection<V>>。如果实用Map来实现Multimap的功能,可想又是对Map的value进行三部曲操作。Multimap的实现也是支持多种类型的(比如Hash、LinkedList等)。使用Multimap的示例代码如下:
Multimap<String,String> map = HashMultimap.create(); map.put("kafka0102","1"); map.put("kafka0102","2"); System.out.println(map.get("kafka0102"));//输出[2, 1]
BiMap
BiMap(bidirectional map)是个双向的map。java.util.Map是个正向Map,也就是根据key查value,如果需要根据value查key,或者需要反向得到Map<V,K>,BiMap就是很好的选择,否则就需要两个Map来做。它的具体实现类有:EnumBiMap, EnumHashBiMap, HashBiMap, ImmutableBiMap。示例代码如下:
BiMap<String,String> map = HashBiMap.create(); map.put("kafka0102","1"); System.out.println(map.get("kafka0102")); System.out.println(map.inverse().get("1");//输出反向数据没有提供单独的函数,而是需要调用inverse().get()
MapMaker
MapMaker是对ConcurrentMap的builder,它使得ConcurrentMap的key和value能是弱引用或软引用类型。特别的,它提供的makeComputingMap方法能根据key计算出value来,当没有对key来put value时,生成的ConcurrentMap能根据Function计算出value并和key关联上,后续的访问就不需要再次计算。代码示例如下:
ConcurrentMap<String, Integer> map = new MapMaker() .concurrencyLevel(32).softKeys().weakValues().expiration(30, TimeUnit.MINUTES) .makeComputingMap( new Function<String, Integer>() { public Integer apply(String key) { return Integer.parseInt(key); } ); System.out.println(map.get("123"));//输出123 map.put("123", 124); System.out.println(map.get("123"));//输出124
google collections还提供一些实用的类,具体可参考它的API doc和http://publicobject.com/2007/09/series-recap-coding-in-small-with.html。该文虽行止于此,也很建议大家有时间研究下google collections的实现,这种基础库看起来简单但要实现的优雅、高效是需要很见功夫的。