本文由 发布,转载请注明出处,如有问题请联系我们! 发布时间: 2021-08-22☕【Java技术指南】「Guava Collections」实战使用相关Guava不一般的集合框架

加载中

Google Guava Collections 应用详细介绍

介绍

Google Guava Collections 是一个对 Java Collections Framework 提高和拓展的一个开源软件。因为它高品质 API 的完成和对 Java特点的灵活运用,促使其在 Java 小区遭受很高点评。小编关键详细介绍它的基本上使用方法和作用特点

应用详细介绍

  • Google Guava Collections(下列都通称为 Guava Collections)是 Java Collections Framework 的提高和拓展。每一个 Java 开发人员都是会在工作上应用各种各样算法设计,许多 状况下 Java Collections Framework 能够 协助你进行这类工作中。

  • 可是在有一些场所你应用了 Java Collections Framework 的 API,但或是必须写许多 编码来完成一些繁杂逻辑性, 这个时候就可以试着应用 Guava Collections 来协助你进行这种工作中。这种高品质的 API 使你的编码更短,更便于阅 读和改动,工作中更为轻轻松松。

总体目标阅读者

  • 针对了解 Java 开源系统专用工具而言,文中阅读者最少应具有基本的 Java 专业知识,尤其是 JDK5 的特点。
  • 由于 Guava Collections 充足应用了范型,循环系统提高那样的特点。做为 Java Collections Framework 的提高,阅读者务必对 Java Collections Framework 有清楚的了解,包含关键的插口承诺和常见的完成类。
  • 而且 Guava Collections 非常大水平上是协助开发人员进行较为复杂的算法设计的实际操作,因而基本的算法设计和优化算法的专业知识也是清楚了解 Guava Collections 的 必备条件。

项目可行性

  • Guava Collections 是 Google 的技术工程师 Kevin Bourrillion 和 Jared Levy 在知名"20%"時间写的编码。自然做为开源软件也有别的的开发人员奉献了编码。

  • 在撰写的全过程中,Java Collections Framework 的创作者 Joshua Bloch 也参加了编码审批和提意见。

  • 现阶段它早已移到此外一个叫 guava-libraries 的开源软件下边来维护保养。 由于作用类似并且又同为开源软件,大家非常当然会把它和 Apache Commons Collections 来做比较。


结合详细介绍

  • Immutable Collections: 仍在应用 Collections.unmodifiableXXX() ? Immutable Collections 这才算是真真正正的不 可改动的结合 l Multiset: 看一下怎样把反复的原素放进一个结合。

  • Multimaps: 必须在一个 key 相匹配好几个 value 的情况下 , 自身写一个完成较为繁杂,让 Multimaps 来帮助

  • BiMap: java.util.Map 只有确保 key 的不反复,BiMap 确保 value 都不反复 l

  • MapMaker: 非常强劲的 Map 结构类

  • Ordering class: 大伙儿了解用 Comparator 做为电压比较器来对结合排列,可是针对多关键词排列 Ordering class 能够 简单化许多 的编码


Immutable Collections: 真真正正的不能改动的结合
  • 大家都使用过Collections.unmodifiableXXX() 来做一个不能改动的结合。比如你需要结构储存变量定义的Set。
Set<String> set = new HashSet<String>(Arrays.asList(new String[]{"RED", "GREEN"})); 
Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
  • 每一次调 unmodifiableSet.add() 会抛出去个 UnsupportedOperationException。

  • 假如有些人在原先的set上add或是remove元素会怎么样?結果unmodifiableSet也是被 add 或是 remove 原素了。

结构那样一个简易的set写了几句长的编码。下边看一下ImmutableSet 是怎么来做地更安全性和简约 :

ImmutableSet<String> immutableSet = ImmutableSet.of("RED", "GREEN");
  • 并且尝试调 add 方式的情况下,它一样会抛出去 UnsupportedOperationException,关键的是编码的易读性提高了许多,十分形象化地呈现了编码的作用。假如像以前这一编码维护一个set 怎么做呢?**
ImmutableSet<String> immutableSet = ImmutableSet.copyOf(set);

从结构的方法而言,ImmutableSet 结合还给予了 Builder 方式来结构一个结合 :在这个事例里边 Builder 不仅能添加单独原素还能添加不仅有的结合。

Builder<String> builder = ImmutableSet.builder(); 
ImmutableSet<String> immutableSet = builder.add("RED").addAll(set).build();

Guava Collections 还给予了各种各样 Immutable 结合的完成

  • ImmutableList

  • ImmutableSet

 ImmutableSet.of(4, 8, 15, 16, 23, 42);
 ImmutableSet.copyOf(numbers);
  • ImmutableSortedSet
  • ImmutableMap
public static final ImmutableMap<String, Integer>
 ENGLISH_TO_INT = ImmutableMap
 .with("four", 4)
 .with("eight", 8)
 .with("fifteen", 15)
 .with("sixteen", 16)
 .with("twenty-three", 23)
 .with("forty-two", 42)
 .build();

ImmutableMap.of(1, "one", 2, "two");
  • ImmutableSortedMap (one day)

Multiset: 把反复的原素放进结合
  • 你很有可能要说这和 Set 插口的合同矛盾,由于Set插口的 JavaDoc 里边要求不可以放进反复原素。实际上,Multiset 并 沒有完成 java.util.Set 插口,它更好像一个Bag。一般的 Set 如同那样 :[car, ship, bike],而 Multiset 会是那样 :
    [car x 2, ship x 6, bike x 3]。

  • 例如一个 List 里边有各种各样字符串数组,随后你需要统计分析每一个字符串数组在 List 里边发生的频次:

Map<String, Integer> map = new HashMap<String, Integer>(); 
for(String word : wordList){ 
   Integer count = map.get(word); 
   map.put(word, (count == null) ? 1 : count   1); 
}
//count word “the” Integer count = map.get(“the”);
假如用 Multiset 就可以那样 :
HashMultiset<String> multiSet = HashMultiset.create();
multiSet.addAll(wordList); 
//count word “the” Integer count = multiSet.count(“the”);
  • 那样连循环系统都不需要了,并且 Multiset 用的方式叫 count,显而易见比在 Map 里边调 get 有更强的易读性。

  • Multiset 还给予了 setCount 那样设置原素反复频次的方式,尽管你能根据应用 Map 来完成相近的作用,可是程序流程的易读性比 Multiset 差了许多 。

常见完成 Multiset 插口的类有:
  • HashMultiset: 原素储放于HashMap
  • LinkedHashMultiset: 原素储放于 LinkedHashMap,即原素的顺序排列由第一次放进的次序决策
  • TreeMultiset:原素被排列储放于TreeMap
  • EnumMultiset: 原素务必是 enum 种类
  • ImmutableMultiset: 不能改动的 Mutiset
  • 见到这儿你很有可能早已发觉 Guava Collections 全是以 create 或者 of 那样的静态方法来结构目标。这是由于这种结合
  • 类大多数有好几个主要参数的独享构造函数,因为主要参数数量许多 ,顾客编码程序猿应用起來就很不方便。并且以这类方法能够
  • 回到原种类的子种类目标。此外,针对建立范型目标而言,这类方法更为简约。

见到这儿你很有可能早已发觉 Guava Collections 全是以 create 或者 of 那样的静态方法来结构目标。这是由于这种结合类大多数有好几个主要参数的独享构造函数,因为主要参数数量许多 ,顾客编码程序猿应用起來就很不方便。并且以这类方法能够
回到原种类的子种类目标。此外,针对建立范型目标而言,这类方法更为简约。

Multimap: 在 Map 的 value 里边放好几个原素

Multimap便是一个 key 相匹配好几个 value 的算法设计。看起来它很像 java.util.Map 的构造,可是 Muitimap 并不是 Map,沒有完成 Map 的插口。构想你对 Map 调了 2 次主要参数 key 一样的 put 方式,結果便是第 2 次的 value 遮盖
了第 1 次的 value。可是对 Muitimap 而言这一 key 与此同时相匹配了 2 个 value。因此 Map 看起来是 : {k1=v1, k2=v2,...},而 Muitimap 是 :{k1=[v1, v2, v3], k2=[v7, v8],....}。

  • 举个记名投票的事例,全部选举票都放到一个 List 里边,List 的每一个原素包含网络投票人与大选人名字。

我们可以那样写 :

//Key is candidate name, its value is his voters 
HashMap<String, HashSet<String>> hMap = new HashMap<String, HashSet<String>>(); 
for(Ticket ticket: tickets){ 
HashSet<String> set = hMap.get(ticket.getCandidate()); 
if(set == null){ 
 set = new HashSet<String>(); 
 hMap.put(ticket.getCandidate(), set); 
} 
set.add(ticket.getVoter());
}

大家再一起来看看 Muitimap 能做些哪些 :

HashMultimap<String, String> map = HashMultimap.create(); 
for(Ticket ticket: tickets){ 
map.put(ticket.getCandidate(), ticket.getVoter()); 
}

就那么简易! Muitimap 插口的关键完成类有:

  • HashMultimap: key 放到 HashMap,而 value 放到 HashSet,即一个 key 相匹配的 value 不能反复
  • ArrayListMultimap: key 放到 HashMap,而 value 放到 ArrayList,即一个 key 相匹配的 value 有次序可反复
  • LinkedHashMultimap: key 放到 LinkedHashMap,而 value 放到 LinkedHashSet,即一个 key 相匹配的 value 有次序不能反复
  • TreeMultimap: key 放到 TreeMap,而 value 放到 TreeSet,即一个 key 相匹配的 value 有顺序排列
  • ImmutableMultimap: 不能改动的 Multimap
BiMap: 双重 Map

**BiMap 完成java.util.Map 插口。它的特性是它的value和它 key一样也是不能反复的,也就是说它的 key 和value是等额的的,假如你往 BiMap 的 value 里边放了反复的原素,便会获得 IllegalArgumentException。 **

举个事例,你很有可能常常会遇到在 Map 里边依据 value 值来推算它的 key 值的逻辑性:

for(Map.Entry<User, Address> entry : map.entreSet()){ 
if(entry.getValue().equals(anAddess)){ 
 return entry.getKey(); 
} 
} 
return null;
  • 假如把 User 和 Address 都放到 BiMap,那麼一句编码就获得結果了: return biMap.inverse().get(anAddess);
  • 这儿的 inverse 方式便是把 BiMap 的 key 结合 value 结合互换,因而 biMap == biMap.inverse().inverse()。
BiMap的常见完成有:
  • HashBiMap: key 结合与 value 结合都是有 HashMap 完成
  • EnumBiMap: key 与 value 都务必是 enum 种类
  • ImmutableBiMap: 不能改动的 BiMap

MapMaker: 非常强劲的 Map 结构专用工具

MapMaker 是用于结构 ConcurrentMap 的java工具。
为何能够 把 MapMaker 称为非常强劲?看过下边的事例你就知道了。最先,它能够 用于结构 ConcurrentHashMap:

//ConcurrentHashMap with concurrency level 8 
ConcurrentMap<String, Object> map1 = new MapMaker().concurrencyLevel(8).makeMap(); 

或是结构用各种各样不一样 reference 做为 key 和 value 的 Map:

//ConcurrentMap with soft reference key and weak reference value 
ConcurrentMap<String, Object> map2 = new MapMaker().softKeys().weakValues().makeMap(); 

或是结构有全自动清除時间到期项的 Map:

//Automatically removed entries from map after 30 seconds since they are created 
ConcurrentMap<String, Object> map3 = new MapMaker() 
.expireAfterWrite(30, TimeUnit.SECONDS)
.makeMap();

或是结构有较大限定数量的 Map:

//Map size grows close to the 100, the map will evict 
//entries that are less likely to be used again 
ConcurrentMap<String, Object> map4 = new MapMaker() 
.maximumSize(100)
.makeMap();

或是给予当 Map 里边不包含所 get 的项,而必须全自动添加到 Map 的作用。这一作用当 Map 做为缓存文件的情况下很有 用 :

//Create an Object to the map, when get() is missing in map 
ConcurrentMap<String, Object> map5 = new MapMaker().makeComputingMap( 
 new Function<String, Object>() { 
 public Object apply(String key) { 
 	return createObject(key); 
}});

这种还并不是最强劲的特点,最厉害的是 MapMaker 能够 给予有着之上全部特点的 Map:

//Put all features together! 
ConcurrentMap<String, Object> mapAll = new MapMaker() 
.concurrencyLevel(8) 
.softKeys() 
.weakValues() 
.expireAfterWrite(30, TimeUnit.SECONDS) 
.maximumSize(100) 
.makeComputingMap( 
 new Function<String, Object>() { 
 public Object apply(String key) { 
 return createObject(key); 
 }});
Ordering class: 灵便的多字段名排列电压比较器

要对结合排列或是求最高值极小值,首先推荐 java.util.Collections 类,但关键是要给予 Comparator 插口的完成。假定有 个待排列的 List,而 Foo 里边有两个排列关键词 int a, int b 和 int c:

Collections.sort(list, new Comparator<Foo>(){ 
@Override 
public int compare(Foo f1, Foo f2) { 
 	int resultA = f1.a – f2.a; 
 	int resultB = f1.b – f2.b; 
 	return resultA == 0 ? (resultB == 0 ? f1.c – f2.c : resultB) : resultA;
}});

这看起来有点儿眼花,假如用一串 if-else 也罢不上哪儿去。看一下 ComparisonChain 能保证哪些 :

Collections.sort(list, new Comparator<Foo>(){ 
@Override 
return ComparisonChain.start() 
 .compare(f1.a, f2.a) 
 .compare(f1.b, f2.b) 
 .compare(f1.c, f2.c).result();
 }});

假如排列关键词要用自定电压比较器,compare 方式也是有接纳 Comparator 的轻载版本号。例如 Foo 里边每一个排列关键词都早已拥有分别的 Comparator,那麼运用 ComparisonChain 能够 :

Collections.sort(list, new Comparator<Foo>(){ 
@Override 
return ComparisonChain.start() 
 .compare(f1.a, f2.a, comparatorA) 
 .compare(f1.b, f2.b, comparatorB) 
 .compare(f1.c, f2.c, comparatorC).result(); 
 }});

Ordring 类还给予了一个组成 Comparator 目标的方式。并且 Ordring 自身完成了 Comparator 插口因此 它能立即作 为 Comparator 应用:

Ordering<Foo> ordering = Ordering.compound(Arrays.asList(comparatorA, comparatorB, comparatorc)); 
Collections.sort(list, ordering);
过滤装置(stream-filter)

运用 Collections2.filter() 方式过虑结合中不满足条件的原素。例如过虑一个 List 里边低于 10 的
原素 :

Collection<Integer> filterCollection = 
 Collections2.filter(list, new Predicate<Integer>(){ 
@Override 
public boolean apply(Integer input) { 
 return input >= 10; 
}});
  • 自然,你能自身写一个循环系统来完成这一作用,可是那样不可以确保以后低于 10 的原素不被放进结合。

  • filter 的强劲之 处取决于回到的 filterCollection 依然有抵触低于 10 的原素的特点,假如调 filterCollection.add(9) 便会获得一个IllegalArgumentException。


转化器(Stream-map)

运用 Collections2.transform() 方式来变换结合中的原素。例如把一个 Set 里边全部原素都转化成 带文件格式的 String 来造成新的 Collection:

Collection<String> formatCollection = 
 Collections2.transform(set, new Function<Integer, String>(){ 
@Override 
public String apply(Integer input) { 
 return new DecimalFormat("#,###").format(input); 
}} );

汇总

之上详细介绍了 Guava Collections 的一些基本上的作用特点。你能从 guava-libraries 的官网免费下载它的 jar 包和它别的的有关文本文档。假如你应用 Maven 来管理方法你的新项目依赖包,Maven 中间库也给予了它版本号的依靠。最后希望Guava Collections 使你的程序编写工作中更轻轻松松,更有快乐。

应用

这一开源软件公布的 jar 包能够 在它的官网内(http://code.google.com/p/guava-libraries/downloads/list)寻找。

其免费下载的 zip 库中带有 Guava Collections 的 jar 包 guava-r09.jar 以及依赖包 guava-r09-gwt.jar,javadoc,源码,readme 等文档。应用时只需将 guava-r09.jar 和依赖包 guava-r09-gwt.jar 放进 CLASSPATH 中就可以。

假如您应用 Maven 做为搭建专用工具得话能够 在 pom.xml 内添加:

<dependency> 
<groupId>com.google.guava</groupId> 
<artifactId>guava</artifactId> 
<version>xxx</version> 
</dependency> 
極限便是为了更好地超过而存有的

评论(0条)

刀客源码 游客评论