JAVA
Guava工具集
  • By刘立博
  • 2021-06-21 20:48:01
  • 912人已阅读

通过Optional特性避免Null

大多数情况下,使用null表明的是某种缺失的情况.Guava引入Optional<T>表明可能为null的T类型引用,Optional实例可能包含非null引用(引用存在),也可能什么也不包括(引用缺失),正是受到Guava启发,Java8将Optional类做为一个新特性引入进Java8的类库.

 

创建Optional

        //创建空Optional对象
        Optional<Object> empty = Optional.empty();
        //使用任意值创建Optional对象
        Optional<String> aaa = Optional.ofNullable("value");
        //使用非空值创建Optional对象
        Optional<String> bbb = Optional.of("aaa");

 

判断Optional对象引用是否缺失

 

        empty.isPresent();

 

当Optional对象引用存在时执行

 

        aaa.ifPresent(System.out::println);

 

当Optional对象引用缺失时执行

        //返回一个对象
        System.out.println(empty.orElse("empty 引用缺失1"));

        //执行匿名函数
        empty.orElseGet(()->{
            System.out.println("empty 引用缺失2");
            return "empty";
        });

        //抛出异常
        try {
            empty.orElseThrow(()-> new Exception("empty 引用缺失3"));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

 

 

不可变集合

 

创建对象的不可变拷贝是一项很好的防御性编程技巧

Guava为所有的JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本

 

不可变对象的优点

当对象被不可信的库调用时,不可变形式是安全的

不可变对象被多个线程调用时,不存在竟态条件问题

不可变集合不需要考虑变化,因此可以节省时间和空间

不可变对象因为固定不变,可以作为常量来安全使用

 

JDK提供的方法

        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(1);
        list.add(2);

        //将可变列表转为不可变列表
        List<Integer> integers = Collections.unmodifiableList(list);

 

Guava提供的方法

        //通过已经存在的集合创建
        ImmutableSet<Integer> copyList = ImmutableSet.copyOf(list);

        //通过初始值创建
        ImmutableSet<Integer> immutableSet = ImmutableSet.of(1,2,3);

        //以builder方式创建
        ImmutableSet<Object> build = ImmutableSet.builder().add(1).add(2).add(3).build();

新集合类型

 

Guava引入了很多JDK没有的、但明显有用的新集合类型,这些新类型是为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念.

 

Multiset两种视角

(1)没有元素顺序限制的ArrayList<E>

 

Add(E) : 添加单个元素

Iterator(): 返回一个迭代器,包含Multiset所有元素(包括重复元素)

Size(): 返回所有元素总个数(包括重复元素)

 

(2)Map<E,Integer>,键为元素,值为计数

 

Count(Object): 返回给定元素计数

entrySet(): 返回Set<Multiset.Entry<E>>和Map的entrySet类似

elementSet():返回所有不重复元素的Set<E>和Map的keySet类似

 

Multiset和Map的区别

 

元素计数只能是正数

Multiset.size()返回集合大小

Multiset.iterator()会迭代重复元素

multiset支持直接设置元素的计数

没有元素,multiset.count(E)为0

 

一个栗子:Multiset实现文字计数

    @Test
    public void testMultiset()
    {
        String text =
            "关关雎鸠,在河之洲。窈窕淑女,君子好逑。" +
            "参差荇菜,左右流之。窈窕淑女,寤寐求之。" +
            "求之不得,寤寐思服。悠哉悠哉,辗转反侧。" +
            "参差荇菜,左右采之。窈窕淑女,琴瑟友之。" +
            "参差荇菜,左右芼之。窈窕淑女,钟鼓乐之。";

        HashMultiset<Character> result = HashMultiset.create();

        char[] chars = text.toCharArray();
        result.addAll(Chars.asList(chars));

        Set<Multiset.Entry<Character>> entries = result.entrySet();

        for (Multiset.Entry<Character> entry : entries) {
            System.out.println(entry.getElement()+"--"+result.count(entry.getElement()));
        }
        System.out.println("size:"+result.size());
    }



流--1
。--10
参--3
求--2
荇--3
采--1
窈--4
...

size:100

 

集合工具类

Guava为集合提供了许多工具方法,这也是Guava最流行和成熟的部分之一,常见集合工具类如:Lists、Sets、Maps等

 

使用Lists工具类操作List集合

    //分组
    @Test
    public void partition()
    {
        ArrayList<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5, 6);
        List<List<Integer>> partition = Lists.partition(integers, 3);
        System.out.println(partition);
    }


    //反转
    @Test
    public void reverse()
    {
        LinkedList<Integer> list = Lists.newLinkedList();
        list.add(1);
        list.add(2);
        list.add(3);

        List<Integer> reverse = Lists.reverse(list);
        System.out.println(reverse);

    }

 

使用Sets工具类操作Set集合

    private static final Set set1 = Sets.newHashSet(1,2);
    private static final Set set2 = Sets.newHashSet(2,3,4);

    //并集
    @Test
    public void testSets()
    {
        Set<Integer> union = Sets.union(set1, set2);
        System.out.println(union);
    }

    //交集
    @Test
    public void intersection()
    {
        Set<Integer> intersection = Sets.intersection(set1, set2);
        System.out.println(intersection);
    }



    //差集
    @Test
    public void difference()
    {
        Set<Integer> intersection = Sets.difference(set1,set2);
        System.out.println(intersection);
    }



    //拆分
    @Test
    public void powerSet()
    {
        Set<Set<Integer>> set = Sets.powerSet(set1);
        System.out.println(JSON.toJSONString(set));
    }

I/O操作

对字节流和字符流提供的工具方法

 

ByteStreams:提供对InputStream、OutputStream的操作

CharStreams:提供对Reader、Writer的操作

 

对源(source)和汇(sink)的抽象

源是可读的:ByteSource、CharSource

汇是可写的:ByteSink、CharSink

 

一个栗子:复制文件

    @Test
    public void ioTest() throws IOException
    {
        CharSource charSource = Files.asCharSource(new File("source.txt"), Charsets.UTF_8);
        CharSink charSink = Files.asCharSink(new File("target.txt"), Charsets.UTF_8);
        charSource.copyTo(charSink);
    }