Google guava工具类的介绍和使用

Lison , v1.0.0, 2020.12.16

Google guava工具类的介绍和使用

概述

工具类 就是封装平常用的方法,不需要你重复造轮子,节省开发人员时间,提高工作效率。谷歌作为大公司,当然会从日常的工作中提取中很多高效率的方法出来。所以就诞生了guava。

guava的优点:

  • 高效设计良好的API,被Google的开发者设计,实现和使用
  • 遵循高效的java语法实践
  • 使代码更刻度,简洁,简单
  • 节约时间,资源,提高生产力

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:

  • 集合 [collections]
  • 缓存 [caching]
  • 原生类型支持 [primitives support]
  • 并发库 [concurrency libraries]
  • 通用注解 [common annotations]
  • 字符串处理 [string processing]
  • I/O 等等。

使用

引入gradle依赖(引入Jar包)

compile 'com.google.guava:guava:28.0-jre'

引入maven依赖

 
      
          com.google.guava
          guava
          28.2-jre
      

1.集合的创建

// 普通Collection的创建
List list = Lists.newArrayList();
Set set = Sets.newHashSet();
Map map = Maps.newHashMap();

// 不变Collection的创建
ImmutableList iList = ImmutableList.of("a", "b", "c");
ImmutableSet iSet = ImmutableSet.of("e1", "e2");
ImmutableMap iMap = ImmutableMap.of("k1", "v1", "k2", "v2");123456789

创建不可变集合 先理解什么是immutable(不可变)对象

  • 在多线程操作下,是线程安全的
  • 所有不可变集合会比可变集合更有效的利用资源
  • 中途不可改变
ImmutableList immutableList = ImmutableList.of("1","2","3","4");1

这声明了一个不可变的List集合,List中有数据1,2,3,4。类中的 操作集合的方法(譬如add, set, sort, replace等)都被声明过期,并且抛出异常。 而没用guava之前是需要声明并且加各种包裹集合才能实现这个功能

  // add 方法
  @Deprecated @Override
  public final void add(int index, E element) {
    throw new UnsupportedOperationException();
  }12345

当我们需要一个map中包含key为String类型,value为List类型的时候,以前我们是这样写的

Map> map = new HashMap>();
List list = new ArrayList();
list.add(1);
list.add(2);
map.put("aa", list);
System.out.println(map.get("aa"));//[1, 2]123456

而现在

Multimap map = ArrayListMultimap.create();      
map.put("aa", 1);
map.put("aa", 2);
System.out.println(map.get("aa"));  //[1, 2]1234

其他的黑科技集合

MultiSet: 无序+可重复   count()方法获取单词的次数  增强了可读性+操作简单
创建方式:  Multiset set = HashMultiset.create();

Multimap: key-value  key可以重复  
创建方式: Multimap teachers = ArrayListMultimap.create();

BiMap: 双向Map(Bidirectional Map) 键与值都不能重复
创建方式:  BiMap biMap = HashBiMap.create();

Table: 双键的Map Map--> Table-->rowKey+columnKey+value  //和sql中的联合主键有点像
创建方式: Table tables = HashBasedTable.create();

...等等(guava中还有很多java里面没有给出的集合类型)12345678910111213

将集合转换为特定规则的字符串

以前我们将list转换为特定规则的字符串是这样写的:

//use java
List list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
String str = "";
for(int i=0; i list = new ArrayList();
list.add("aa");
list.add("bb");
list.add("cc");
String result = Joiner.on("-").join(list);
//result为  aa-bb-cc123456789101112131415161718

把map集合转换为特定规则的字符串

Map map = Maps.newHashMap();
map.put("xiaoming", 12);
map.put("xiaohong",13);
String result = Joiner.on(",").withKeyValueSeparator("=").join(map);
// result为 xiaoming=12,xiaohong=1312345

将String转换为特定的集合

//use java
List list = new ArrayList();
String a = "1-2-3-4-5-6";
String[] strs = a.split("-");
for(int i=0; i list = Splitter.on("-").splitToList(str);
//list为  [1, 2, 3, 4, 5, 6]123456789101112

如果

str="1-2-3-4- 5-  6  ";1

guava还可以使用 omitEmptyStrings().trimResults() 去除空串与空格

String str = "1-2-3-4-  5-  6   ";  
List list = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(str);
System.out.println(list);123

将String转换为map

String str = "xiaoming=11,xiaohong=23";
Map map = Splitter.on(",").withKeyValueSeparator("=").split(str);12

guava还支持多个字符切割,或者特定的正则分隔

String input = "aa.dd,,ff,,.";
List result = Splitter.onPattern("[.|,]").omitEmptyStrings().splitToList(input);12

关于字符串的操作 都是在Splitter这个类上进行的

// 判断匹配结果
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  efg12345678910

集合的过滤

我们对于集合的过滤,思路就是迭代,然后再具体对每一个数判断,这样的代码放在程序中,难免会显得很臃肿,虽然功能都有,但是很不好看。

guava写法

//按照条件过滤
ImmutableList names = ImmutableList.of("begin", "code", "Guava", "Java");
Iterable fitered = Iterables.filter(names, Predicates.or(Predicates.equalTo("Guava"), Predicates.equalTo("Java")));
System.out.println(fitered); // [Guava, Java]

//自定义过滤条件   使用自定义回调方法对Map的每个Value进行操作
ImmutableMap m = ImmutableMap.of("begin", 12, "code", 15);
        // Function F表示apply()方法input的类型,T表示apply()方法返回类型
        Map m2 = Maps.transformValues(m, new Function() {
            public Integer apply(Integer input) {
                if(input>12){
                    return input;
                }else{
                    return input+1;
                }
            }
        });
System.out.println(m2);   //{begin=13, code=15}
12345678910111213141516171819

set的交集, 并集, 差集

HashSet setA = newHashSet(1, 2, 3, 4, 5);  
HashSet setB = newHashSet(4, 5, 6, 7, 8);  

SetView union = Sets.union(setA, setB);    
System.out.println("union:");  
for (Integer integer : union)  
    System.out.println(integer);           //union 并集:12345867

SetView difference = Sets.difference(setA, setB);  
System.out.println("difference:");  
for (Integer integer : difference)  
    System.out.println(integer);        //difference 差集:123

SetView intersection = Sets.intersection(setA, setB);  
System.out.println("intersection:");  
for (Integer integer : intersection)  
    System.out.println(integer);  //intersection 交集:451234567891011121314151617

map的交集,并集,差集

HashMap mapA = Maps.newHashMap();
mapA.put("a", 1);mapA.put("b", 2);mapA.put("c", 3);

HashMap mapB = Maps.newHashMap();
mapB.put("b", 20);mapB.put("c", 3);mapB.put("d", 4);

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}1234567891011121314151617

检查参数

//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);  1234567891011121314151617

免去了很多麻烦!并且会使你的代码看上去更好看。而不是代码里面充斥着 !=null!=""

检查是否为空,不仅仅是字符串类型,其他类型的判断,全部都封装在 Preconditions类里,里面的方法全为静态

其中的一个方法的源码

@CanIgnoreReturnValue
public static  T checkNotNull(T reference) {
    if (reference == null) {
      throw new NullPointerException();
    }
    return reference;
}1234567
方法声明(不包括额外参数) 描述 检查失败时抛出的异常
checkArgument(boolean) 检查boolean是否为true,用来检查传递给方法的参数。 IllegalArgumentException
checkNotNull(T) 检查value是否为null,该方法直接返回value,因此可以内嵌使用checkNotNull。 NullPointerException
checkState(boolean) 用来检查对象的某些状态。 IllegalStateException
checkElementIndex(int index, int size) 检查index作为索引值对某个列表、字符串或数组是否有效。 index > 0 && index < size IndexOutOfBoundsException
checkPositionIndexes(int start, int end, int size) 检查[start,end]表示的位置范围对某个列表、字符串或数组是否有效 IndexOutOfBoundsException

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}1234

强大的Ordering排序器

排序器[Ordering]是Guava流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。

natural()   对可排序类型做自然排序,如数字按大小,日期按先后排序
usingToString() 按对象的字符串形式做字典排序[lexicographical ordering]
from(Comparator)    把给定的Comparator转化为排序器
reverse()   获取语义相反的排序器
nullsFirst()    使用当前排序器,但额外把null值排到最前面。
nullsLast() 使用当前排序器,但额外把null值排到最后面。
compound(Comparator)    合成另一个比较器,以处理当前排序器中的相等情况。
lexicographical()   基于处理类型T的排序器,返回该类型的可迭代对象Iterable的排序器。
onResultOf(Function)    对集合中元素调用Function,再按返回值用当前排序器排序。123456789

示例

Person person = new Person("aa",14);  //String name  ,Integer age
Person ps = new Person("bb",13);
Ordering byOrdering = Ordering.natural().nullsFirst().onResultOf(new Function(){
    public String apply(Person person){
        return person.age.toString();
    }
});
byOrdering.compare(person, ps);
System.out.println(byOrdering.compare(person, ps)); //1      person的年龄比ps大 所以输出1123456789

计算中间代码的运行时间

Stopwatch stopwatch = Stopwatch.createStarted();
for(int i=0; i<100000; i++){
    // do some thing
}
long nanos = stopwatch.elapsed(TimeUnit.MILLISECONDS);
System.out.println(nanos);123456

TimeUnit 可以指定时间输出精确到多少时间

文件操作

以前我们写文件读取的时候要定义缓冲区,各种条件判断,各种 $%#$@#

而现在我们只需要使用好guava的api 就能使代码变得简洁,并且不用担心因为写错逻辑而背锅了

File file = new File("test.txt");
List list = null;
try {
    list = Files.readLines(file, Charsets.UTF_8);
} catch (Exception e) {
}

Files.copy(from,to);  //复制文件
Files.deleteDirectoryContents(File directory); //删除文件夹下的内容(包括文件与子文件夹)  
Files.deleteRecursively(File file); //删除文件或者文件夹  
Files.move(File from, File to); //移动文件
URL url = Resources.getResource("abc.xml"); //获取classpath根下的abc.xml文件url123456789101112

Files类中还有许多方法可以用,可以多多翻阅

guava缓存

guava的缓存设计的比较巧妙,可以很精巧的使用。guava缓存创建分为两种,一种是CacheLoader,另一种则是callback方式

CacheLoader:

LoadingCache cahceBuilder=CacheBuilder
                .newBuilder()
                .build(new CacheLoader(){
                    @Override
                    public String load(String key) throws Exception {        
                        String strProValue="hello "+key+"!";                
                        return strProValue;
                    }
                });        
System.out.println(cahceBuilder.apply("begincode"));  //hello begincode!
System.out.println(cahceBuilder.get("begincode")); //hello begincode!
System.out.println(cahceBuilder.get("wen")); //hello wen!
System.out.println(cahceBuilder.apply("wen")); //hello wen!
System.out.println(cahceBuilder.apply("da"));//hello da!
cahceBuilder.put("begin", "code");
System.out.println(cahceBuilder.get("begin")); //code12345678910111213141516

api中已经把apply声明为过期,声明中推荐使用get方法获取值

callback方式:

 Cache cache = CacheBuilder.newBuilder().maximumSize(1000).build();  
            String resultVal = cache.get("code", new Callable() {  
                public String call() {  
                    String strProValue="begin "+"code"+"!";                
                    return strProValue;
                }  
            });  
 System.out.println("value : " + resultVal); //value : begin code!12345678

以上只是guava使用的一小部分,guava是个大的工具类,第一版guava是2010年发布的,每一版的更新和迭代都是一种创新。

jdk的升级很多都是借鉴guava里面的思想来进行的。

Guava工具类学习

一、概述

Guava是对Java API的补充,对Java开发中常用功能进行更优雅的实现,使得编码更加轻松,代码容易理解。Guava使用了多种设计模式,同时经过了很多测试,得到了越来越多开发团队的青睐。Java最新版本的API采纳了Guava的部分功能,但依旧无法替代。本文以Getting Started With Google Guava原文为学习材料,对Guava中常用的API进行学习,尽量覆盖比较有用的API,包括字符串处理,集合类处理,文件IO处理等。

二、字符串连接器Joiner

2.1 连接多个字符串并追加到StringBuilder

        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

2.2 连接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());
        }

最后tmp.txt的内容为:

Tue Dec 20 16:51:09 CST 2016#no string#Tue Dec 20 16:51:09 CST 2016

2.3 将Map转化为字符串

        Map<String, String> testMap = Maps.newLinkedHashMap();
       testMap.put("Cookies", "12332");
        testMap.put("Content-Length", "30000");
        testMap.put("Date", "2016.12.16");
      testMap.put("Mime", "text/html");
       // 用:分割键值对,并用#分割每个元素,返回字符串
        String returnedString = Joiner.on("#").withKeyValueSeparator(":").join(testMap);
        System.out.println(returnedString); // Cookies:12332#Content-Length:30000#Date:2016.12.16#Mime:text/html

三、 字符串分割器Splitter

3.1 将字符串分割为Iterable

        // 分割符为|,并去掉得到元素的前后空白
        Splitter sp = Splitter.on("|").trimResults();
        String str = "hello | world | your | Name ";
        Iterable<String> ss = sp.split(str);
        for(String it : ss){
            System.out.println(it);
        }

结果为:

hello
world
your
Name

3.2 将字符串转化为Map

        // 内部类的引用,得到分割器,将字符串解析为map
        Splitter.MapSplitter ms = Splitter.on("#").withKeyValueSeparator(':');
        Map<String, String> ret = ms.split(returnedString);
        for(String it2 : ret.keySet()){
           System.out.println(it2 + " -> " + ret.get(it2));
        }

结果为:

Cookies -> 12332
Content-Length -> 30000
Date -> 2016.12.16
Mime -> text/html

四、 字符串工具类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

五、字符匹配器CharMatcher

5.1 空白一一替换

        // 空白回车换行对应换成一个#,一对一换
        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

5.2 连续空白缩成一个字符

        // 将所有连在一起的空白回车换行字符换成一个#,倒塌
        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#

5.3 去掉前后空白和缩成一个字符

        // 在前面的基础上去掉字符串的前后空白,并将空白换成一个#
        String trimRet = CharMatcher.WHITESPACE.trimAndCollapseFrom(tabString, '#');
        System.out.println(trimRet);// hello#world#you#are#here

5.4 保留数字

        String letterAndNumber = "1234abcdABCD56789";
        // 保留数字
        String number = CharMatcher.JAVA_DIGIT.retainFrom(letterAndNumber);
        System.out.println(number);// 123456789

六、 断言工具类Preconditions

        // 检查是否为null,null将抛出异常IllegalArgumentException,且第二个参数为错误消息。
        trimRet = null;
        //Preconditions.checkNotNull(trimRet, "label can not be null");
        int data = 10;
        Preconditions.checkArgument(data < 100, "data must be less than 100");

七、对象工具类 Objects

7.1 Objects的toStringHelper和hashCode方法

        // Book用Objects的相关方法简化toString(),hashCode()的实现。
        // 用ComparisonChain简化compareTo()(Comparable接口)方法的实现。
        Book book1 = new Book();
        book1.setAuthor("Tom");
        book1.setTitle("Children King");
        book1.setIsbn("11341332443");
       System.out.println(book1);
        System.out.println(book1.hashCode());
        Book book2 = new Book();
        book2.setAuthor("Amy");
       book2.setTitle("Children King");
        book2.setIsbn("111");
        System.out.println(book2);
        System.out.println(book2.hashCode());
        System.out.println(book1.compareTo(book2));

结果为:

Book{author=Tom, title=Children King, isbn=11341332443, price=0.0}
268414056
Book{author=Amy, title=Children King, isbn=111, price=0.0}
-1726402621
1

7.2 Objects的firstNonNull方法

        // 如果第一个为空,则返回第二个,同时为null,将抛出NullPointerException异常

        String someString = null;

        String value = Objects.firstNonNull(someString, "default value");
        System.out.println(value); // deafult value

Book.java

class Book implements Comparable<Book>{
    private String author;

    private String title;

    private String publisher;

    private String isbn;

    private double price;

    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;

    }

    public String getTitle() {
        return title;

    }

    public void setTitle(String title) {

        this.title = title;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {

        this.publisher = publisher;

    }

    public String getIsbn() {
       return isbn;

    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public double getPrice() {
        return price;

    }

    public void setPrice(double price) {
        this.price = price;
    }

    // 定义第一二关键字

    @Override
    public int compareTo(Book o) {
        return ComparisonChain.start().compare(this.title, o.title).compare(this.isbn, o.isbn).result();
    }
    public String toString(){
        return Objects.toStringHelper(this).omitNullValues().add("author", author).add("title", title)
                .add("publisher", publisher).add("isbn", isbn).add("price", price).toString();

    }
    public int hashCode(){
        return Objects.hashCode(author, title, publisher, isbn, price);

    }



}

八、整体迭代接口FluentIterable

8.1 使用Predicate整体过滤

        Person person1 = new Person("Wilma", 30, "F");

        Person person2 = new Person("Fred", 32, "M");

        Person person3 = new Person("Betty", 32, "F");

        Person person4 = new Person("Barney", 33, "M");

        List<Person> personList = Lists.newArrayList(person1, person2, person3, person4);

        // 过滤年龄大于等于32的person

        Iterable<Person> personsFilteredByAge =

                FluentIterable.from(personList).filter(new Predicate<Person>() {

                    @Override
                    public boolean apply(Person input) {
                        return input.getAge() > 31;

                    }
                });


        // Iterable有一个iterator方法,集合类都有一个Iterator方法

        for(Iterator<Person> it = personsFilteredByAge.iterator(); it.hasNext();){

            System.out.println(it.next());

        }

        System.out.println(Iterables.contains(personsFilteredByAge, person2));

结果为:

Person{name=‘Fred’, sex=‘M’, age=32}
Person{name=‘Betty’, sex=‘F’, age=32}
Person{name=‘Barney’, sex=‘M’, age=33}
true

8.2 使用Function整体替换,将List转化为List

        // 将List 转化为 List,数据源为personList。整体迭代。

        List<String> transformPersonList = FluentIterable.from(personList).transform(
                new Function<Person, String>(){
                    @Override
                    public String apply(Person person) {
                        // 不定参数,返回String类型
                        return Joiner.on("#").join(person.getName(), person.getSex(), person.getAge());
                    }
                }

        ).toList();


        for(int i = 0; i < transformPersonList.size(); i++){

            System.out.println(transformPersonList.get(i));



        }

结果为:

Wilma#F#30
Fred#M#32
Betty#F#32
Barney#M#33

Person.java

class Person{

    private String name;
    private String sex;
  	private int age;
	public Person(String name, int age, String sex){
    this.name = name;
  	this.sex = sex;
    this.age = age;
  }
    public String getName() {
        return name;
    }

    public void setName(String name) {
	  this.name = name;
    }

    public String getSex() {
	return sex;
 }


    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }


    public void setAge(int age) {
        this.age = age;
    }



    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +

                '}';
    }

}

九、 集合运算工具类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
        }

十、Function和Predicate

利用Functions将Map转化为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的功能是将一个类型转化为另一个类型
        Function<String, Person> lookup = Functions.forMap(mp);
        // 如果键值不存在,则会抛出异常。lookup内部已经有元素
        Person tmp = lookup.apply("Betty");
        System.out.println(tmp == person3); // true

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(agePre.apply(person3)); // false
        System.out.println(namePre.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
        System.out.println(both.apply(person3)); // 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

Map工具类Maps

        // 将List 转化为Map,其中键值对是person.name -> Person
        Map<String, Person> myMp = Maps.uniqueIndex(personList.iterator(), new Function<Person, String>(){
            // name作为person的键
            @Override
            public String apply(Person person) {
                return person.getName();
            }
        });
        for(String name : myMp.keySet()){
            System.out.println(myMp.get(name));
        }

结果为:

Person{name=‘Wilma’, sex=‘F’, age=30}
Person{name=‘Fred’, sex=‘M’, age=32}
Person{name=‘Betty’, sex=‘F’, age=32}
Person{name=‘Barney’, sex=‘M’, age=33}

十二、一键多值类Multimap

数组存储多值类ArrayListMultimap

        // 用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
            System.out.println(it20 + " : " + multimap.get(it20));
        }
        // 返回所有ArrayList的元素个数的和
        System.out.println(multimap.size());

结果为:

bar : [a, a, b]
foo : [1, 2, 3]
6

HashTable存储多值类 HashMultimap

        //这里采用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
            System.out.println(it20 + " : " + hashMultimap.get(it20));
        }
        // 5
       System.out.println(hashMultimap.size());

结果为:

bar : [a, b]
foo : [1, 2, 3]
5

十三、多键类Table

两个键操作

        // 两个键row key和column key,其实就是map中map, map > 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
        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

十四、 可以通过value获取key的HashBiMap

value不可以有相同的key

        BiMap<String, String> biMap = HashBiMap.create();
       // value可以作为Key,即value不可以有多个对应的值
        biMap.put("hello", "world");
        biMap.put("123", "tell");
        biMap.put("123", "none"); // 覆盖tell
        // biMap.put("abc", "world"); 失败
        // 下面是强制替换第一对
        biMap.forcePut("abc", "world");
        System.out.println(biMap.size()); // 2
        System.out.println(biMap.get("hello"));// null
        System.out.println(biMap.get("abc")); // world
        System.out.println(biMap.get("123")); // none

键值对互换得到新的BiMap

        // 键值对互换
        BiMap<String, String> inverseMap = biMap.inverse();
        System.out.println(inverseMap.get("world")); // abc
        System.out.println(inverseMap.get("tell")); // null
        System.out.println(inverseMap.get(null)); // null

、不可变集合类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]

区间工具类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

逆置比较器

        // 自定义比较器,嵌入式的比较器,匿名类。注意这里有两个person参数,与Comparable的区别
       Comparator<Person> ageCmp = new Comparator<Person>(){
            // Ints是Guava提供的,递增
            @Override
            public int compare(Person o1, Person o2) {
                return Ints.compare(o1.getAge(), o2.getAge());
            }
        };
        List<Person> list = Lists.newArrayList(person1, person2, person3, person4);
        // 将比较器转化为Ordering,得到比较器ageCmp的相反比较器,递减
        Collections.sort(list, Ordering.from(ageCmp).reverse());
        for(Iterator<Person> iter = list.iterator(); iter.hasNext(); ){
            System.out.println(iter.next());|
        }

结果为:

Person{name=‘Barney’, sex=‘M’, age=33}
Person{name=‘Fred’, sex=‘M’, age=32}
Person{name=‘Betty’, sex=‘F’, age=32}
Person{name=‘Wilma’, sex=‘F’, age=30}

组合多个比较器

        // 按照名字排序
        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}

十八、 文件工具类Files

复制移动重命名文件

        // 文件操作:复制,移动,重命名
        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();
       }

获取文件哈希码

        try {

           // File,HashFunction
            HashCode hashCode = Files.hash(originFile, Hashing.md5());
            System.out.println(originFile.getName() + " : " + hashCode);
        } catch (IOException e) {
            e.printStackTrace();
        }

结果为:abc.java : 66721c8573de09bd17bafac125e63e98

读取文件流,将文件行转化为List

        // 读文件流
        int lineNumber = 1;
        try {
            // 读出所有的行到list中,去掉\n
            List<String> list2 = Files.readLines(mvFile, Charsets.UTF_8);
            for(Iterator<String> it = list2.iterator(); it.hasNext();){
                System.out.println("line " + lineNumber + ":" + it.next());
                lineNumber++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

结果为:

line 1:public class test{
line 2: static String str;
line 3: public static void main(String[] args){
line 4:
line 5: System.out.println(str);
line 6: }
line 7:}

将文件行进行处理,再得到List

        // LineProcessor处理每一行,得到返回值
        /*
           内容:
            Linux命令行大全,人民邮电出版社

            Linux内核完全注释,机械工业出版社

            Linux命令行和shell脚本编程大全,人民邮电出版社



         */

       File bookFile = new File("/home/gzx/Documents/book.txt");
        try {
            // 只取书名
            List<String> list3 = Files.readLines(bookFile, Charsets.UTF_8, new TitleLineProcessor());
            for(Iterator<String> it = list3.iterator(); it.hasNext();){
                System.out.println(it.next());
            }
        } catch (IOException e) {
            e.printStackTrace();
       }

结果为:

Linux命令行大全
Linux内核完全注释
Linux命令行和shell脚本编程大全

写文件流

        // 写文件流
        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();
        }

write.txt的内容为

hello world!你的名字

TitleLineProcessor.java

class TitleLineProcessor implements LineProcessor<List<String>>{
    private final static int INDEX = 0;
    private final static Splitter splitter = Splitter.on(",");
    private List<String> titles = new ArrayList<String>();
    // 每一行都会调用这个函数,进而追加成一个list
    @Override
    public boolean processLine(String s) throws IOException {
        // 获取第一项,并追加到titles
        titles.add(Iterables.get(splitter.split(s), INDEX));
        return true;
    }
    // 最终的结果
    @Override
    public List<String> getResult() {
        return titles;
    }
}

读输入字节流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

        File pdfFile = 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();
        }

提醒处理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

小结

细节请翻看 guava 文档 https://github.com/google/guava/wiki

你可能感兴趣的:(java)