结构
   
     
   
    
    
    概述
   
工具类 就是封装平常用的方法,不需要你重复造轮子,节省开发人员时间,提高工作效率。谷歌作为大公司,当然会从日常的工作中提取中很多高效率的方法出来。所以就诞生了guava。
    
    
    guava的优点
   
高效设计良好的API,被Google的开发者设计,实现和使用
遵循高效的java语法实践
使代码更刻度,简洁,简单
节约时间,资源,提高生产力
    
    
    guava的核心库
   
集合 [collections]
缓存 [caching]
原生类型支持 [primitives support]
并发库 [concurrency libraries]
通用注解 [common annotations]
字符串处理 [string processing]
I/O 
     
   
    
    
    引入
   
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>21.0</version>
</dependency>
    
    
    使用
   
    
    
    集合
   
    
    
    集合创建
   
各种以S结尾的工厂类简化了集合的创建。在创建泛型实例的时候,它们使代码更加简洁
//java 7 中
Map<String,List<String>> m=new HashMap<>();
// java 8 普通Collection的创建
List<String> list = Lists.newArrayList("a","b","c");
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();
// 不变Collection的创建
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("e1", "e2");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");
    创建不可变集合 先理解什么是
    
     immutable(不可变)对象
    
在 多线程操作 下,是 线程安全的 
所有不可变集合 会比 可变集合 更有效的利用资源
中途不可改变
ImmutableList<String> immutableList = ImmutableList.of("1","2","3","4");
// add 方法
@Deprecated @Override
public final void add(int index, E element) {
 	throw new UnsupportedOperationException();
}
    这声明了一个
    
     不可变的List集合
    
    ,List中有数据
    
     1,2,3,4
    
    。类中的 操作集合的方法(譬如
    
     add, set, sort, replace
    
    等)都被声明过期,并且抛出异常。 而
    
     没用guava之前是需要声明并且加各种包裹集合才能实现这个功能
    
    
    
    集合转换、查找、过滤、分割
   
    
     将一个集合转换成另外一种类型的集合
    
   
Lists.transform()
List<String> listStr = Lists.newArrayList("1", "2", "3");
//将字符串集合转换为Integer集合
List<Integer> listInteger = Lists.transform(listStr, new Function<String, Integer>() {
          @Nullable
          @Override
          public Integer apply(@Nullable String s) {
              return Integer.valueOf(s);
          }
      });
ImmutableMap<String, Integer> m = ImmutableMap.of("begin", 12, "code", 15);
//Function<F, T> F表示apply()方法input的类型,T表示apply()方法返回类型
Map<String, Integer> m2 = Maps.transformValues(m, input -> {
	    if(input > 12){
	        return input;
	    }else{
	        return input + 1;
	    }
	});
System.out.println(m2);
//{begin=13, code=15} 
//java 8 中
 List<Integer> listInteger2 = listStr.stream().map(Integer::valueOf).collect(Collectors.toList());
    
     查找集合首个匹配的元素
    
   
 List<String> listStr = Lists.newArrayList("hello", "world", "hehe");
  //查找首个以h开头的值    
  String value = Iterables.find(listStr, new Predicate<String>() {
      @Override
      public boolean apply(String input) {
          return input.startsWith("h");
      }
  });
//java 8
String value2 = listStr.stream().findFirst().filter(input -> input.startsWith("h")).get();
    
     过滤集合中所有符合特定条件的元素
    
   
List<String> listWithH = Lists.newArrayList(Collections2.filter(listStr, new Predicate<String>() {
         @Override
         public boolean apply(@Nullable String s) {
             return s.startsWith("h");
         }
     }));
//按照条件过滤
ImmutableList<String> names = ImmutableList.of("begin", "code", "Guava", "Java");
Iterable<String> fitered = Iterables.filter(names, Predicates.or(Predicates.equalTo("Guava"), Predicates.equalTo("Java")));
//java 8
List<String> listWithH2 = listStr.stream().filter(input -> input.startsWith("h")).collect(Collectors.toList());
    
     将一个大的集合分割成小集合,适用于分批查询、插入等场景
    
   
 List<String> listStr = Lists.newArrayList("1", "2", "3","4","5","6","7");
 List<List<String>>  batchList = Lists.partition(listStr,3);
 //被分割成了: [[1, 2, 3], [4, 5, 6], [7]]
    
    
    分组
   
Maps.uniqueIndex 根据集合中的唯一键把集合转换为以唯一键为key,以元素为value的Map 
Multimaps.index 根据集合中的相同的值把集合转换为以相同值为key,以List<元素>为value的Map. 相当于一键多值Map
class Apple {
    int id;
    String color;
    public Apple(int id, String color) {
        this.id = id;
        this.color = color;
    }
    public int getId() {
        return id;
    }
    public String getColor() {
        return color;
    }
    @Override
    public String toString() {
        return MoreObjects.toStringHelper(Apple.class).add("id", id).add("color", color).toString();
    }
}
@Test
public void test1() {
    List<Apple> appleList = Lists.newArrayList(new Apple(1, "red"), new Apple(2, "red"), new Apple(3, "green"), new Apple(4, "green"));
    // 以主键为key,生成键值对:Map<id,Apple>
    Map<Integer, Apple> appleMap = Maps.uniqueIndex(appleList, new Function<Apple, Integer>() {
        @Nullable
        @Override
        public Integer apply(@Nullable Apple apple) {
            return apple.getId();
        }
    });
    
   // 相当于根据颜色分类:转为Map<颜色,Collection<Apple>>
   Multimap<String, Apple> multiMap = Multimaps.index(appleList,
            new Function<Apple, String>() {
                @Nullable
                @Override
                public String apply(@Nullable Apple apple) {
                    return apple.getColor();
                }
            });
}
List<Apple> appleList = Lists.newArrayList(new Apple(1, "red"), new Apple(2, "red"), new Apple(3, "green"), new Apple(4, "green"));
Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, apple -> apple));
Map<String, List<Apple>> groupsByColor = appleList.stream().collect(Collectors.groupingBy(Apple::getColor));
    
    
    集合运算工具类
   
    
    
    Sets
   
    
     集合差
    
   
 // s1 - s2
 Set<String> s1 = Sets.newHashSet("1", "2", "3", "4");
 Set<String> s2 = Sets.newHashSet("2", "3", "4", "5");
 // 得到第一个集合中有而第二个集合没有的字符串
 Sets.SetView res = Sets.difference(s1, s2);
 for(Iterator<String> it = res.iterator(); it.hasNext();){
     System.out.println(it.next()); // 1
 }
    
     集合对称差
    
   
Sets.SetView res2 = Sets.symmetricDifference(s1, s2);
for(Object it14 : res2){
   System.out.println(it14); // 1 5
}
    
     集合交
    
   
// s1和s2的交集
Sets.SetView<String> res3 = Sets.intersection(s1, s2);
for(String it14 : res3){
   System.out.println(it14); // 2 3 4
}
    
     集合并
    
   
// 合并s1和s2
Sets.SetView<String> res4 = Sets.union(s1, s2);
for(String it14 : res4){
   System.out.println(it14); // 1 2 3 4 5
}
    
    
    Map
   
MapDifference differenceMap = Maps.difference(mapA, mapB);
differenceMap.areEqual();
Map entriesDiffering = differenceMap.entriesDiffering();
Map entriesOnlyLeft = differenceMap.entriesOnlyOnLeft();
Map entriesOnlyRight = differenceMap.entriesOnlyOnRight();
Map entriesInCommon = differenceMap.entriesInCommon();
System.out.println(entriesDiffering);   // {b=(2, 20)}
System.out.println(entriesOnlyLeft);    // {a=1}
System.out.println(entriesOnlyRight);   // {d=4}
System.out.println(entriesInCommon);    // {c=3} 
    
    
    对JDK集合的有效补充
   
MultiSet: 无序+可重复   count()方法获取单词的次数  增强了可读性+操作简单
创建方式:  Multiset<String> set = HashMultiset.create();
Multimap: key-value  key可以重复  
创建方式: Multimap<String, String> teachers = ArrayListMultimap.create();
BiMap: 双向Map(Bidirectional Map) 键与值都不能重复
创建方式:  BiMap<String, String> biMap = HashBiMap.create();
Table: 双键的Map Map--> Table-->rowKey+columnKey+value  //和sql中的联合主键有点像
创建方式: Table<String, String, Integer> tables = HashBasedTable.create();
...等等(guava中还有很多java里面没有给出的集合类型)
    
    
    灰色地带:Multiset
   
    
     JDK
    
    的集合,提供了
    
     有序且可以重复的List
    
    ,
    
     无序且不可以重复的Set
    
    。那这里其实对于集合涉及到了2个概念,一个order,一个dups。那么List vs Set,and then some ?
    
     
   
Multiset就是无序的,但是可以重复的集合,它就是游离在List/Set之间的“灰色地带”!
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
注意 区分下面
import org.apache.commons.collections4.MultiSet;
import com.google.common.collect.Multiset;
Multiset<String> set = HashMultiset.create();
set.add("a");
set.add("b");
set.add("c");
System.out.println(set.size());
System.out.println(set.count("a"));  //Multiset自带一个有用的功能,就是可以跟踪每个对象的数量
    
    
    Immutable vs unmodifiable
   
    
     JDK
    
    提供的
    
     Collections.unmodifiableXxx
    
    所
    
     返回的集合和源集合
    
    是
    
     同一个对象
    
    ,只不过可以
    
     对集合做出改变的API都被override
    
    ,会
    
     抛出UnsupportedOperationException
    
    也就是说
    
     改变源集合,导致不可变视图(unmodifiable View)也会发生变化
    
    
    
    
    
     不使用guava的情况下避免上面的问题
    
   
// 下面 揭示了一个概念:Defensive Copies,保护性拷贝
ArrayList<Object> list = Lists.newArrayList("a","b");
List<Object> objects = Collections.unmodifiableList(new ArrayList<>(list));
//  objects.add("a"); //throw java.lang.UnsupportedOperationException
list.add("c");
System.out.println(list); //a b c
    使用
    
     guava 的 Immutable
    
guava提供了很多Immutable集合,比如
ImmutableList/ImmutableSet/ImmutableSortedSet/ImmutableMap/......
ImmutableList<String> list = ImmutableList.of("a", "b", "c");
list.add("c"); //throw java.lang.UnsupportedOperationException
ImmutableList<String> immutableList = ImmutableList.copyOf(list);
immutableList.add("c");    //视图不随着源而改变,guava 设置了只读
System.out.println(list.size() + "\n" + immutableList.size());
    
     ImmutableMap
    
   
ImmutableMap<String, String> map = ImmutableMap.of("name", "zhangsan", "sex", "man");
map.put("wife","no")  //throw java.lang.UnsupportedOperationException
    
    
    可不可以一对多:Multimap
   
    
     JDK
    
    提供的
    
     Map是一个键,一个值,一对一的
    
    ,那么在实际开发中,显然存在
    
     一个KEY多个VALUE
    
    的情况
    
     (比如一个分类下的书本)
    
    ,我们往往这样表达:
    
     Map<k,List<v>>
    
    ,好像有点臃肿!臃肿也就算了,更加不爽的事,我们
    
     还得判断KEY是否存在来决定是否new 一个LIST出来
    
    ,有点麻烦!更加麻烦的事情还在后头,比如遍历,比如删除,so hard…
   
ArrayListMultimap<Object, Object> multimap = ArrayListMultimap.create();
multimap.put("name","zhangsan");
multimap.put("name","lisi");
multimap.put("age","12");
System.out.println(multimap.get("name"));
guava所有的集合都有create方法,这样的好处在于简单,而且我们不必在重复泛型信息了。
get()/keys()/keySet()/values()/entries()/asMap()都是非常有用的返回view collection的方法。
Multimap的实现类有:
ArrayListMultimap/HashMultimap/LinkedHashMultimap/TreeMultimap/ImmutableMultimap/....
// 用ArrayList保存,一键多值,值不会被覆盖
  ArrayListMultimap<String, String> multimap = ArrayListMultimap.create();
  multimap.put("foo", "1");
  multimap.put("foo", "2");
  multimap.put("foo", "3");
  multimap.put("bar", "a");
  multimap.put("bar", "a");
  multimap.put("bar", "b");
  for(String it20 : multimap.keySet()){
      // 返回类型List<String>
      System.out.println(it20 + " : " + multimap.get(it20));
  }
  // 返回所有ArrayList的元素个数的和
  System.out.println(multimap.size());
  
//结果
bar : [a, a, b]
foo : [1, 2, 3]
6
  //这里采用HashTable保存
  HashMultimap<String, String> hashMultimap = HashMultimap.create();
  hashMultimap.put("foo", "1");
  hashMultimap.put("foo", "2");
  hashMultimap.put("foo", "3");
  // 重复的键值对值保留一个
  hashMultimap.put("bar", "a");
  hashMultimap.put("bar", "a");
  hashMultimap.put("bar", "b");
  for(String it20 : hashMultimap.keySet()){
      // 返回类型List<String>
      System.out.println(it20 + " : " + hashMultimap.get(it20));
  }
  // 5
  System.out.println(hashMultimap.size());
//结果
bar : [a, b]
foo : [1, 2, 3]
5
    
    
    可不可以双向:BiMap
   
    
     JDK
    
    提供的MAP让我们可以
    
     find value by key
    
    ,那么能不能通过
    
     find key by value
    
    呢,能不能
    
     KEY和VALUE都是唯一的呢
    
    。这是一个
    
     双向的概念
    
    ,即
    
     forward+backward
    
    在实际场景中有这样的需求吗?比如
    
     通过用户ID找到mail
    
    ,
    
     也需要通过mail找回用户名
    
    。没有guava的时候,我们需要
    
     create forward map
    
    AND
    
     create backward map
    
    ,and now just let guava do that for you.
   
HashBiMap<Object, Object> bimap = HashBiMap.create();
bimap.put("name","zhangsan");
//bimap.put("student","zhangsan");   //value 相同也会报错 java.lang.IllegalArgumentException: value already present: zhangsan
bimap.put("name","lisi");   //覆盖
bimap.forcePut("student","zhangsan");  // 强制覆盖
bimap.forcePut("age","12");
System.out.println(bimap.inverse().get("zhangsan"));
biMap / biMap.inverse() / biMap.inverse().inverse() 它们是什么关系呢?
你可以稍微看一下BiMap的源码实现,实际上,当你创建BiMap的时候,在内部维护了2个map,一个forward map,一个backward map,并且设置了它们之间的关系。
因此,biMap.inverse() != biMap ;biMap.inverse().inverse() == biMap
    
    
    可不可以多个KEY:Table
   
    数据库除了主键外,还提供了
    
     复合索引
    
    ,而且实际中这样的
    
     多级关系查找
    
    也是比较多的,当然我们可以利用
    
     嵌套的Map来实现:Map<k1,Map<k2,v2>>
    
    。为了让我们的代码看起来不那么丑陋,guava为我们提供了Table。
   
rowKey,columnKey,value
     
   
  // 两个键row key和column key,其实就是map中map, map<Integer, map<Integer, String> > mp
  HashBasedTable<Integer, Integer, String> table = HashBasedTable.create();
  table.put(1, 1, "book");
  table.put(1, 2, "turkey");
  table.put(2, 2, "apple");
  System.out.println(table.get(1, 1)); // book
  System.out.println(table.contains(2, 3)); // false
  System.out.println(table.containsRow(2)); // true
  table.remove(2, 2);
  System.out.println(table.get(2, 2)); // null
	// 获取单独的一个map
	Map<Integer, String> row = table.row(1);
	Map<Integer, String> column = table.column(2);
	System.out.println(row.get(1)); // book
	System.out.println(column.get(1)); // turkey
    
    
    不可变集合类ImmutableListMultimap
   
   // 不可变的集合,都有一个Builder内部类。不可以修改和添加
   Multimap<Integer, String> map = new ImmutableListMultimap.Builder<Integer, String>().put(1, "hello")
           .putAll(2, "abc", "log", "in").putAll(3, "get", "up").build();
   System.out.println(map.get(2)); // [abc, log, in]
    
    
    字符串
   
    
    
    拼接 Joiner
   
    
     Joiner
    
    可以快速地
    
     把多个字符串或字符串数组连接成为用特殊符号连接的字符串
    
List<String> list = Lists.newArrayList("a","b","c");
String value =Joiner.on("-").skipNulls().join(list);
System.out.println(value);
//输出为: a-b-c
    
     joiner.appendTo()
    
    按照
    
     Joiner 规则
    
    追加
   
StringBuilder stringBuilder = new StringBuilder("hello");
// 字符串连接器,以|为分隔符,同时去掉null元素
Joiner joiner1 = Joiner.on("|").skipNulls();
// 构成一个字符串foo|bar|baz并添加到stringBuilder
stringBuilder = joiner1.appendTo(stringBuilder, "foo", "bar", null, "baz");
System.out.println(stringBuilder); // hellofoo|bar|baz
    
     把map集合转换为特定规则的字符串
    
   
Map<String, Integer> map = Maps.newHashMap();
map.put("xiaoming", 12);
map.put("xiaohong",13);
String result = Joiner.on(",").withKeyValueSeparator("=").join(map);
// result为 xiaoming=12,xiaohong=13
    
     连接List元素并写到文件流
    
   
FileWriter fileWriter = null;
try{
    fileWriter = new FileWriter(new File("/home/gzx/Documents/tmp.txt"));
} catch(Exception e){
    System.out.println(e.getMessage());
}
List<Date> dateList = new ArrayList<Date>();
dateList.add(new Date());
dateList.add(null);
dateList.add(new Date());
// 构造连接器:如果有null元素,替换为no string
Joiner joiner2 = Joiner.on("#").useForNull("no string");
try{
    // 将list的元素的tostring()写到fileWriter,是否覆盖取决于fileWriter的打开方式,默认是覆盖,若有true,则是追加
    joiner2.appendTo(fileWriter, dateList);
    // 必须添加close(),否则不会写文件
    fileWriter.close();
} catch(IOException e){
    System.out.println(e.getMessage());
}
    
    
    分割 Splitter
   
    
     Splitter
    
    用来分割字符串
   
String testString = "Monday,Tuesday,,Thursday,Friday,,";
//英文分号分割;忽略空字符串
Splitter splitter = Splitter.on(",").omitEmptyStrings().trimResults();
System.out.println(splitter.split(testString).toString());
//转换为了:[Monday, Tuesday, Thursday, Friday]
    
     将String转换为特定的集合
    
   
//use java
List<String> list = new ArrayList<String>();
String a = "1-2-3-4-5-6";
String[] strs = a.split("-");
for(int i=0; i<strs.length; i++){
	list.add(strs[i]);
}
//use guava
String str = "1-2-3-4-5-6";
List<String> list = Splitter.on("-").splitToList(str);
//list为  [1, 2, 3, 4, 5, 6]
    
     使用 omitEmptyStrings().trimResults() 去除空串与空格
    
   
String str = "1-2-3-4-  5-  6   ";  
List<String> list = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(str);
System.out.println(list);
    
     将String转换为map
    
   
String str = "xiaoming=11,xiaohong=23";
Map<String,String> map = Splitter.on(",").withKeyValueSeparator("=").split(str);
    
     特定的正则分隔
    
   
String input = "aa.dd,,ff,,.";
List<String> result = Splitter.onPattern("[.|,]").omitEmptyStrings().splitToList(input);
    
    
    CharMatcher
   
    
     匹配
    
    
    
     CharMatcher
    
    常用来
    
     从字符串里面提取特定字符串
    
    
    比如想
    
     从字符串中得到所有的数字
    
String value = CharMatcher.DIGIT.retainFrom("some text 2046 and more");
//value=2046
    
     替换
    
   
// 空白回车换行对应换成一个#,一对一换
String stringWithLinebreaks = "hello world\r\r\ryou are here\n\ntake it\t\t\teasy";
String s6 = CharMatcher.BREAKING_WHITESPACE.replaceFrom(stringWithLinebreaks,'#');
System.out.println(s6); // hello#world###you#are#here##take#it###easy
    
     连续空白缩成一个字符
    
   
// 将所有连在一起的空白回车换行字符换成一个#,倒塌
String tabString = "  hello   \n\t\tworld   you\r\nare             here  ";
String tabRet = CharMatcher.WHITESPACE.collapseFrom(tabString, '#');
System.out.println(tabRet); // #hello#world#you#are#here#
    
     去掉前后空白和缩成一个字符
    
   
// 在前面的基础上去掉字符串的前后空白,并将空白换成一个#
String trimRet = CharMatcher.WHITESPACE.trimAndCollapseFrom(tabString, '#');
System.out.println(trimRet);// hello#world#you#are#here
    
     inRange
    
   
// 判断匹配结果
boolean result = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).matches('K'); //true
// 保留数字文本  CharMatcher.digit() 已过时   retain 保留
//String s1 = CharMatcher.digit().retainFrom("abc 123 efg"); //123
String s1 = CharMatcher.inRange('0', '9').retainFrom("abc 123 efg"); // 123
// 删除数字文本  remove 删除
// String s2 = CharMatcher.digit().removeFrom("abc 123 efg");    //abc  efg
String s2 = CharMatcher.inRange('0', '9').removeFrom("abc 123 efg"); // abc  efg
    
    
    Strings 工具类
   
System.out.println(Strings.isNullOrEmpty("")); // true
System.out.println(Strings.isNullOrEmpty(null)); // true
System.out.println(Strings.isNullOrEmpty("hello")); // false
// 将null转化为""
System.out.println(Strings.nullToEmpty(null)); // ""
// 从尾部不断补充T只到总共8个字符,如果源字符串已经达到或操作,则原样返回。类似的有padStart
System.out.println(Strings.padEnd("hello", 8, 'T')); // helloTTT
    
    
    Function
   
    
    
    利用Functions将Map转化为Function
   
    
     Function
    
    的功能是
    
     将一个类型转化为另一个类型
    
 Map<String, Person> mp = Maps.newHashMap();
 mp.put(person1.getName(), person1);
 mp.put(person2.getName(), person2);
 mp.put(person3.getName(), person3);
 mp.put(person4.getName(), person4);
 
 // 将map转化为Function
 Function<String, Person> lookup = Functions.forMap(mp);
 // 如果键值不存在,则会抛出异常。lookup内部已经有元素
 Person tmp = lookup.apply("Betty");
 System.out.println(tmp == person3); // true
public void testConverte1() {
    ArrayList<String> strings = Lists.newArrayList("helloworld", "deadtodead", "newbirth");
    Function<String, String> function = new Function<String, String>() {
        @Nullable
        @Override
        public String apply(@Nullable String s) {
            return s.length()<=4 ? s : s.substring(0,4);
        }
    };
    Function<String, String> function1 = new Function<String, String>() {
        @Nullable
        @Override
        public String apply(@Nullable String s) {
            return s.toUpperCase();
        }
    };
    Function<String, String> compose = Functions.compose(function, function1);
    Collection<String> transform = Collections2.transform(strings, compose);
    transform.forEach(t-> System.out.println(t));
}
    好处在于在
    
     集合遍历操作中提供自定义Function的操作
    
    ,比如
    
     transform转换
    
    。我们再也不需要一遍遍的遍历集合,显著的简化了代码
    
     
   
    
    
    断言 Predicate
   
    
     Predicate
    
    最常用的功能就是
    
     运用在集合的过滤当中
    
    
     
   
//use java
if(list!=null && list.size()>0)
'''
if(str!=null && str.length()>0)
'''
if(str !=null && !str.isEmpty())
//use guava
if(!Strings.isNullOrEmpty(str))
//use java
if (count <= 0) {
    throw new IllegalArgumentException("must be positive: " + count);         
}    
//use guava
Preconditions.checkArgument(count > 0, "must be positive: %s", count);  
    
    
     
   
    
    
    Predicate单个判断
   
   Predicate<Person> agePre = new Predicate<Person>(){
       @Override
       public boolean apply(Person person) {
           return person.getAge() < 32;
       }
   };
   Predicate<Person> namePre = new Predicate<Person>(){
       @Override
       public boolean apply(Person person) {
           return person.getName().equals("Betty");
       }
   };
   // 判断是否符合条件
   System.out.println(agePre.apply(person2)); // false
   System.out.println(namePre.apply(person3)); // true
    
    
    Predicates的and运算
   
  // 利用Predicates工具类,同时满足两个条件成一个predicate
  Predicate<Person> both = Predicates.and(agePre, namePre);
  System.out.println(both.apply(person1)); // false 
    
    
    Predicates的or运算
   
  //至少一个满足组成一个Predicate
  Predicate<Person> orPre = Predicates.or(agePre, namePre);
  System.out.println(orPre.apply(person2)); // false
    
    
    Predicates的compose运算
   
   // 通过键name获得值Person,然后检查Person的age < 32,即agepre.apply(lookup.apply(name)) == true?
   // lookup内部已经有集合
   Predicate<String> two = Predicates.compose(agePre, lookup);
   System.out.println(two.apply("Wilma")); // true
    
    
    文件操作 Files
   
    
    
    写文件流
   
  // 写文件流
  File writeFile = new File("/home/gzx/Documents/write.txt");
  try {
      // 不必打开或关闭文件流,会自动写盘
      Files.write("hello world!", writeFile, Charsets.UTF_8); // 重新写
      Files.append("你的名字", writeFile, Charsets.UTF_8); // 追加
  } catch (IOException e) {
      e.printStackTrace();
  }
    
    
    读取文件流
   
以前写文件读取要定义缓冲区,各种条件判断,使用 guava 后就简单多了
File file = new File("test.txt");
List<String> list = null;
try {
	list = Files.readLines(file, Charsets.UTF_8);
} catch (Exception e) {
}
    
    
    读输入字节流ByteSource和写输出字节流ByteSink
   
	// source是源的意思,封装输入流
	ByteSource byteSource = Files.asByteSource(writeFile);
	try {
	    byte[] contents1 = byteSource.read();
	    byte[] contents2 = Files.toByteArray(writeFile); // 两个方法的作用相同
	    for(int i = 0; i < contents1.length; i++){
	        assert(contents1[i] == contents2[i]);
	        System.out.print(contents1[i] + " ");
	    }
	} catch (IOException e) {
	    e.printStackTrace();
	}
	
	// sink是目的地的意思,封装输出流,流会自动关闭
	File tmpFile = new File("/home/gzx/Documents/hello.txt"); // acd
	ByteSink byteSink = Files.asByteSink(tmpFile);
	try {
	    byteSink.write(new byte[]{'a', 'c', 'd', '\n'});
	} catch (IOException e) {
	    e.printStackTrace();
	}
    
    
    编码工具类BaseEncoding
   
  FilepdfFile = new File("/home/gzx/Documents/google.pdf");
  BaseEncoding baseEncoding = BaseEncoding.base64();
  try {
      byte[] content = Files.toByteArray(pdfFile);
      String encoded = baseEncoding.encode(content); // 将不可打印的字符串转化为可以打印的字符串A-Za-z0-9/+=,pdf不是纯文本文件
      System.out.println("encoded:\n" + encoded);
      System.out.println(Pattern.matches("[A-Za-z0-9/+=]+", encoded));
      // 获得对应的加密字符串,可以解密,可逆的,得到原来的字节
      byte[] decoded = baseEncoding.decode(encoded);
      for(int i = 0; i < content.length; i++){
          assert(content[i] == decoded[i]);
      }
  } catch (IOException e) {
      e.printStackTrace();
  }
    
    
    移动复制重命名删除等
   
 // 文件操作:复制,移动,重命名
 File originFile = new File("/home/gzx/Documents/Program/Java/abc.java");
 File copyFile = new File("/home/gzx/Documents/test.java");
 File mvFile = new File("/home/gzx/Documents/abc.java");
 try {
     Files.copy(originFile, copyFile);  //复制文件
     Files.move(copyFile, mvFile); // 重命名
 }
 catch(IOException e){
     e.printStackTrace();
 }
Files.deleteDirectoryContents(File directory); //删除文件夹下的内容(包括文件与子文件夹)  
Files.deleteRecursively(File file); //删除文件或者文件夹  
URL url = Resources.getResource("abc.xml"); //获取classpath根下的abc.xml文件url
...
    
    
    获取文件哈希码
   
 try {
     // File,HashFunction
     HashCode hashCode = Files.hash(originFile, Hashing.md5());
     System.out.println(originFile.getName() + " : " + hashCode);
 } catch (IOException e) {
     e.printStackTrace();
 }
abc.java : 66721c8573de09bd17bafac125e63e98
    
    
    提醒处理null的类Optional
   
 Optional<Person> optional = Optional.fromNullable(person1); // 允许参数为null
 System.out.println(optional.isPresent()); // true
 System.out.println(optional.get() == person1); // 如果是person1 == null,get将抛出IllegalStateException, true
 Optional<Person> optional2 = Optional.of(person1); // 不允许参数为null。如果person1 == null, 将抛出NullPointerException
 System.out.println(optional2.isPresent()); // true
    
    
    线程
   
com.google.common.util.concurrent目录下是各种线程工具类
    
     ListenableFuture
    
    :
    
     可以监听的Future
    
    ,它是
    
     对java原生Future的扩展增强
    
    。
    
    
     MoreExecutors
    
    : 提供了很多
    
     静态方法
    
    。其中
    
     listeningDecorator
    
    方法
    
     初始化ListeningExecutorService方法
    
    ,使用此实例
    
     submit方法即可初始化ListenableFuture对象
    
    。
    
    
     ListeningExecutorService
    
    的
    
     invokeAny
    
    继承自Jdk原生类,
    
     率先返回线程组中首个执行完毕的
    
    。
    
    
     ListeningExecutorService
    
    的
    
     invokeAll
    
    
     并行执行
    
    线程组,
    
     等待所有线程执行完毕
    
    ,适用于
    
     批量处理
    
public final List<String> list = Lists.newArrayList("a", "b", "c", "d", "e", "f");
 @Test
 public void testGuava() {
     ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
     List<Callable<String>> allThread = Lists.newArrayList();
     for (final String value : list) {
         Callable<String> callable = new Callable<String>() {
             @Override
             public String call() {
                 return value + " 休息了 " + sleepRandom();
             }
         };
         allThread.add(callable);
     }
     try {
         //1. 返回首个执行完毕的值
         //  String date = listeningExecutorService.invokeAny(allThread);
         // 2. 并行执行完所有线程
         List<Future<String>> valueList = listeningExecutorService.invokeAll(allThread);
         for (Future<String> future : valueList) {
             System.out.println(future.get());
         }
     } catch (Exception e) {
         e.printStackTrace();
     } finally {
         listeningExecutorService.shutdown();
     }
 }
java 8 中
 @Test
 public void testJava8() throws Exception {
     ExecutorService executor = Executors.newFixedThreadPool(10);
     List<CompletableFuture> futures = list.stream()
             .map(value -> CompletableFuture.completedFuture(value).thenApplyAsync(s -> s + " 休息了 " + sleepRandom(), executor))
             .collect(Collectors.toList());
     //1. 返回首个执行完毕的值
     // CompletableFuture valueFuture = CompletableFuture.anyOf(futures.toArray(new CompletableFuture[futures.size()]));
     // 2. 并行执行完所有线程
     CompletableFuture valueFutureList = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
     futures.stream().forEach(f -> {
         try {
             System.out.println(f.get());
         } catch (Exception e) {
         }
     });
 }
    
    
    缓存
   
    
    
    其他
   
Lists并没有提供filter方法,不过你可以使用Collections2.filter
    
    
    计算中间代码的运行时间 Stopwatch
   
import com.google.common.base.Stopwatch;
import java.util.concurrent.TimeUnit;
public class Test9 {
    public static void main(String[] args) throws InterruptedException {
        // 创建stopwatch并开始计时
        Stopwatch stopwatch = Stopwatch.createStarted();
        Thread.sleep(1980);
        // 以秒打印从计时开始至现在的所用时间,向下取整
        System.out.println(stopwatch.elapsed(TimeUnit.SECONDS)); // 1
        // 停止计时
        stopwatch.stop();
        System.out.println(stopwatch.elapsed(TimeUnit.SECONDS)); // 1
        // 再次计时
        stopwatch.start();
        Thread.sleep(100);
        System.out.println(stopwatch.elapsed(TimeUnit.SECONDS)); // 2
        // 重置并开始
        stopwatch.reset().start();
        Thread.sleep(1030);
        // 检查是否运行
        System.out.println(stopwatch.isRunning()); // true
        long millis = stopwatch.elapsed(TimeUnit.MILLISECONDS); // 1034
        System.out.println(millis);
        // 打印
        System.out.println(stopwatch.toString()); // 1.034 s
    }
}
    
    
    MoreObjects
   
    这个方法是在
    
     Objects过期后官方推荐使用的替代品
    
    ,该类最大的好处就是
    
     不用大量的重写 toString
    
    ,用一种很优雅的方式实现重写,或者在某个场景定制使用
   
Person person = new Person("aa",11);
String str = MoreObjects.toStringHelper("Person").add("age", person.getAge()).toString();
System.out.println(str);  
//输出Person{age=11}
    
     firstNonNull
    
   
// 如果第一个为空,则返回第二个,同时为null,将抛出NullPointerException异常
String someString = null;
String value = Objects.firstNonNull(someString, "default value");
System.out.println(value); // deafult value
    
    
    区间工具类Range
   
   // 闭区间
   Range<Integer> closedRange = Range.closed(30, 33);
   System.out.println(closedRange.contains(30)); // true
   System.out.println(closedRange.contains(33)); // true
   // 开区间
   Range<Integer> openRange = Range.open(30, 33);
   System.out.println(openRange.contains(30)); // false
   System.out.println(openRange.contains(33)); // false
   Function<Person, Integer> ageFunction = new Function<Person, Integer>(){
       @Override
       public Integer apply(Person person) {
           return person.getAge();
       }
   };
   // Range实现了Predicate接口,这里的第一个参数是Predicate,第二个参数是Function
   // ageFunction必须返回整数
   Predicate<Person> agePredicate = Predicates.compose(closedRange, ageFunction);
   System.out.println(agePredicate.apply(person1)); // person1.age == 30 true
    
    
    Ordering排序器
   
可以用来为构建复杂的比较器,以完成集合排序的功能
natural()	对可排序类型做自然排序,如数字按大小,日期按先后排序
usingToString()	按对象的字符串形式做字典排序[lexicographical ordering]
from(Comparator)	把给定的Comparator转化为排序器
reverse()	获取语义相反的排序器
nullsFirst()	使用当前排序器,但额外把null值排到最前面。
nullsLast()	使用当前排序器,但额外把null值排到最后面。
compound(Comparator)	合成另一个比较器,以处理当前排序器中的相等情况。
lexicographical()	基于处理类型T的排序器,返回该类型的可迭代对象Iterable<T>排序器
onResultOf(Function)	对集合中元素调用Function,再按返回值用当前排序器排序
Person person = new Person("aa",14);  //String name  ,Integer age
Person ps = new Person("bb",13);
Ordering<Person> byOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Person,String>(){
    @OverWirte
	public String apply(Person person){
		return person.age.toString();
	}
});
int res = byOrdering.compare(person, ps);
System.out.println(res); //1      person的年龄比ps大 所以输出1
    
    
    组合多个比较器
   
  // 按照名字排序
  Comparator<Person> nameCmp = new Comparator<Person>(){
      @Override // 两个对象,而Comparable是this和一个对象
      public int compare(Person o1, Person o2) {
          return o1.getName().compareTo(o2.getName());
      }
  };
  
  // 组合两个比较器,得到第一二排序关键字
  // 年龄相同时按照名字排序
  Ordering order = Ordering.from(ageCmp).compound(nameCmp);
  Collections.sort(list, order);
  for(Iterator<Person> iter = list.iterator(); iter.hasNext(); ){
      System.out.println(iter.next());
  }
Person{name='Wilma', sex='F', age=30}
Person{name='Betty', sex='F', age=32}
Person{name='Fred', sex='M', age=32}
Person{name='Barney', sex='M', age=33} 
    
    
    获取最小几个和最大几个
   
  Ordering order2 = Ordering.from(nameCmp);
  
  // 最小的两个,无序
  System.out.println("least 2...");
  List<Person> least = order2.leastOf(personList, 2);
  for(int i = 0; i < 2; i++){
      System.out.println(least.get(i));
  }
  
  // 最大的三个,无序
  System.out.println("greatest 3....");
  List<Person> great = order2.greatestOf(personList, 3);
  for(int i = 0; i < 3; i++){
      System.out.println(great.get(i));
  }
least 2...
Person{name='Barney', sex='M', age=33}
Person{name='Betty', sex='F', age=32}
greatest 3....
Person{name='Wilma', sex='F', age=30}
Person{name='Fred', sex='M', age=32}
Person{name='Betty', sex='F', age=32} 
 
