七、Guava 工具集

Google Guava 工具集简介

Guava工程包含了若干被Google的Java项目广泛依赖的核心库,例如:集合、缓存、原生类型支持、并发库、通用注解、字符串处理、I/O等等。
所有这些工具每天都在被Google的工程师应用在产品服务中。

使用和避免null

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

实例

/**
 * @author fangliu
 * @date 2020-02-15
 * @description 学习Java8中的optional使用方法
 */
public class OptionalTest {
    @Test
    public  void test() throws Throwable {
        /**
         * 三种创建Optional
         */
        // 创建空的Optional对象
        Optional.empty();
        // 使用非null值创建Optional对象
        Optional.of("Optional");
        // 使用任意值创建Optional对象
        Optional optional = Optional.ofNullable(null);
        /**
         * 判断是否引用缺失的方法(建议不直接使用)
         */
        optional.isPresent();
        /**
         * optional引用存在时执行
         * 类似的方法:map filter flatMap
         */
        optional.ifPresent(System.out::println);

        /**
         * 当optional引用缺失时执行
         * orElse():如果有值则将其返回,否则返回指定的其它值。
         * orElseGet():如果有值则将其返回,否则调用函数并将其返回调用结果。
         * 由于orElseGet()不是每次都会调用传入的方法,所以orElseGet()方法在性能上要优于orElse()方法。
         */
        optional.orElse(get("引用缺失"));
        optional.orElseGet(()->{
            // 自定义引用缺失时的返回值
            System.out.println("自定义引用缺失");
            return "自定义引用缺失";
        });

        optional.orElseThrow(()->{
            throw  new RuntimeException("引用缺失异常");
        });
    }
    public static int get(String name) {
        System.out.println(name);
        return 1;
    }
}

不可变对象的优点

  • 当对象被不可信的库调用时,不可变形式是安全的
  • 不可变对象被多个线程调用时,不存在竞态条件问题
  • 不可变集合不需要考虑变化,因此可以节省时间和空间
  • 不可变对象因为有固定不变,可以作为常量来安全使用

JDK提供的unmodifiableXXX方法

  • 笨重而且累赘
  • 不安全
  • 低效

实例

/**
 * @author fangliu
 * @date 2020-02-16
 * @description 不可变集合用法
 */
public class ImmutableTest {
    public static void test(List<Integer> list){
        list.remove(0);
    }
    @Test
    public  void test(){
        List<Integer> list= new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        // 通过Collections的unmodifiableList方法让list不可变
        List<Integer> newList = Collections.unmodifiableList(list);
        test(newList);
        System.out.println(list);
    }
}

Guava提供的不可变集合的三种创建方式

  • copyOf方法:ImmutableSet.copyOf(set)
  • of方法:ImmutableSet.of("a","b","c")
  • Builder工具:ImmutableSet.builder().build()

    public void immutable(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        /**
         * 构造不可变集合对象三种方式
         */
        // 通过已经存在的集合创建
        ImmutableSet.copyOf(list);
        // 通过初始值,直接创建不可变集合
        ImmutableSet immutableSet = ImmutableSet.of(1,2,3,4,5);
        //以builder方式创建
        ImmutableSet.builder()
                .add(1)
                .addAll(Sets.newHashSet(2,3,4))
                .add(5)
                .build();

    }

新集合类型

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

Set 无序不可重复集合
List 有序可重复集合
Multiset 无序可重复集合

实例

/**
 * @author fangliu
 * @date 2020-02-16
 * @description 使用Multiset统计一首古诗的文字出现频率
 */
public class MultisetTest {
    private static final String text =
            "择一城终老,遇一人白首。挽一帘幽梦,许一世倾城。写一字决别,言一梦长眠。我倾尽一生,囚你无期。 " +
            "择一人深爱,等一人终老。痴一人情深,留一世繁华。断一根琴弦,歌一曲离别。我背弃一切,共度朝夕。";
    private static final String text1 =
            "三生有幸遇见你 纵使悲凉也是情;" +
            "一世无缘却相逢,即便欣喜也无果!";
    @Test
    public void handle (){
        // multiset创建
        Multiset<Character> multiset = HashMultiset.create();
        // string 转化成char数组
        char[] chars = text.toCharArray();
        // 遍历数组,添加到multiset中
        Chars.asList(chars)
                .stream()
                .forEach(charItem->multiset.add(charItem));
        System.out.println("size:"+multiset.size());
        System.out.println("count:"+multiset.count('人'));
    }

}

集合工具类

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

实例

/**
 * @author fangliu
 * @date 2020-02-16
 * @description Guava集合使用
 */
public class CollectionsTest {
    /**
     * Sets工具类的常用方法
     * 并集/交集/差集/分解集合中的所有子集/求两个集合的笛卡尔积
     * <p>
     * Lists工具类的常用方式
     * 反转/拆分
     */
    private static final Set set1 = Sets.newHashSet(1, 2, 3, 4);

    private static final Set set2 = Sets.newHashSet(4, 5, 6);

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

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

    // 差集
    @Test
    public void difference() {
        // 属于set1并且不属于set2
        Set<Integer> set = Sets.difference(set1, set2);
        System.out.println(set);
        // 相对差集:set1、set2差集之外的值
        set = Sets.symmetricDifference(set1, set2);
        System.out.println(set);
    }

    // 分解集合中的所有子集
    @Test
    public void powerSet() {
        // 属于set1并且不属于set2
        Set<Set<Integer>> set = Sets.powerSet(set1);
        System.out.println(JSON.toJSONString(set));
    }

    // 求两个集合的笛卡尔积
    @Test
    public void cartesianProduct() {
        // 属于set1并且不属于set2
        Set<List<Integer>> set = Sets.cartesianProduct(set1, set2);
        System.out.println(JSON.toJSONString(set));
    }

    // 拆分
    @Test
    public void partition() {
        List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
        // 几个为一组拆分
        List<List<Integer>> partition = Lists.partition(list, 2);
        System.out.println(JSON.toJSONString(partition));
    }

    // 反转
    @Test
    public void reverse() {
        List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
        List<Integer> reverse = Lists.reverse(list);
        System.out.println(JSON.toJSONString(reverse));
    }
}

IO综述

  • ByteStreams:提供对InputStream/OutputStream的操作
  • CharStreams:提供对Reader/Writer的操作

源(Source)与汇(Sink)的抽象

  • 源是可读的:ByteSource/CharSource
  • 汇是可写的:ByteSink/CharSink

实例

/**
 * @author fangliu
 * @date 2020-02-16
 * @description 源(Source)与汇(Sink)对文件进行常用操作
 */
public class IOTest {
    @Test
    public void copyFile() throws IOException {
        /**
         * 创建对应的Source和Sink
         */
        CharSource charSource = Files.asCharSource(
                new File("SourceText.txt"), Charsets.UTF_8);
        CharSink charSink = Files.asCharSink(
                new File("TargetText.txt"),Charsets.UTF_8
        );
        /**
         * 拷贝
         */
        charSource.copyTo(charSink);
    }
}
posted @ 2020-11-18 20:56  柳小白  阅读(257)  评论(0编辑  收藏  举报