十倍效率开发神器-Guava

Guava

什么是Guava?

Guava是谷歌开源的工具库,里面包含了一些新的集合类型、并发工具类、I/O、缓存、字符串操作等等。

引入依赖:

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>30.1.1-jre</version>
</dependency>

3.1 集合操作

  1. 不可变集合:用不可变的集合进行防御性编程
  2. 新集合类型:Multimap、SortedMultiset等
  3. 强大的集合工具类
  4. 扩展工具类:让实现和扩展集合类变得更容易,比如创建Collection的装饰器

使用示例:

  public static void testCollection(){
        //不能进行新增,会抛出UnsupportedOperationException
        ImmutableSet<String> immutableSet = ImmutableSet.of("red", "orange", "yellow", "blue", "blue", "green");
        System.out.println(immutableSet);

        //同个key的值放入不会覆盖
        ArrayListMultimap arrayListMultimap = ArrayListMultimap.create();
        arrayListMultimap.put("a",1);
        arrayListMultimap.put("a",2);
        System.out.println(arrayListMultimap.get("a"));

        //集合工具类
        ArrayList<String> list = Lists.newArrayList("aa", "bb", "cc");
        String aa = Iterables.find(list, x -> x.equals("aa"));
        System.out.println(aa);

        List<Integer> integers = Ints.asList(1, 2, 3, 4, 5, 6, 7, 8);
        List<Integer> reverse = Lists.reverse(integers);
        //分成3个一组
        List<List<Integer>> partition = Lists.partition(integers, 3);

        Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
        Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");

        //获取两个set里共有的
        Sets.SetView<String> intersection = Sets.intersection(primes, wordsWithPrimeLength); // contains "two", "three", "seven"
        System.out.println(intersection);

        //转list为map
        User user = new User();
        user.setName("liu");
        user.setId(1);
        User user2 = new User();
        user2.setName("wang");
        user2.setId(2);
        ArrayList<User> users = Lists.newArrayList(user, user2);
        ImmutableMap<Integer, User> integerUserImmutableMap = Maps.uniqueIndex(users, u -> u.getId());
        System.out.println(integerUserImmutableMap);

        //快速创建map
        ImmutableMap.<String,Object>of("type","aa");


    }

3.2 本地缓存

实现了JVM缓存,支持多种缓存过期策略

3.2.1 创建方式:

创建方式1:使用CacheLoader

public static void testCache() throws InterruptedException, ExecutionException {
        CacheLoader<Integer,User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }
        };
        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().maximumSize(1000)
                .expireAfterWrite(30, TimeUnit.SECONDS)
                .build(cacheLoader);
    }

创建方式2:使用Callable

 Cache<Integer,User> objectCache = CacheBuilder.newBuilder().maximumSize(1000)
                .expireAfterWrite(30, TimeUnit.SECONDS)
                .build();
        User user = objectCache.get(1, ()  -> new User(1, "王二"));
3.2.2 缓存回收
  1. 指定大小回收
 CacheLoader<Integer,User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }
        };
        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().
        //指定大小是3个
        maximumSize(3)
                .expireAfterWrite(30, TimeUnit.SECONDS)
                .build(cacheLoader);

        cache.put(1,new User(1,"a"));
        cache.put(2,new User(2,"a"));
        cache.put(3,new User(3,"a"));
        cache.put(4,new User(4,"a"));
        //getIfPresent方法不会重新加载创建cache
        System.out.println(cache.getIfPresent(  1));
        System.out.println(cache.getIfPresent(2));
        System.out.println(cache.getIfPresent(3));
        System.out.println(cache.getIfPresent(4));

打印结果:

null
User(id=2, name=a)
User(id=3, name=a)
User(id=4, name=a)

最早插入的会被回收

  1. 缓存时间回收
   CacheLoader<Integer,User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }
        };
        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().maximumSize(3)
                .expireAfterWrite(3, TimeUnit.SECONDS)
                .build(cacheLoader);
        cache.put(1,new User(1,"a"));
        Thread.sleep(2000);
        System.out.println(cache.getIfPresent(  1));
        Thread.sleep(2000);
        System.out.println(cache.getIfPresent(1));

打印结果为空

  • expireAfterWrite(time),上次写入多长时间后过期
  • expireAfterAccess(time),上次写或读操作多长时间后过期

上面的示例中,用expireAfterWrite的话,第二次打印结果为null,用expireAfterAccess的话第二次的打印结果有值

3.2.3 显示的清除缓存
  • Cache.invalidate(key) :清除指定单个key
  • Cache.invalidateAll(keys):清除指定多个key
  • Cache.invalidateAll() :清除所有
3.2.4 移除缓存监听器
 CacheLoader<Integer,User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }
        };

        RemovalListener<Integer, User> removalListener = new RemovalListener<Integer, User>() {
            public void onRemoval(RemovalNotification<Integer, User> removal) {
                System.out.println("移除值:"+removal);
            }
        };

        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().maximumSize(3)
                .expireAfterWrite(3, TimeUnit.SECONDS)
                .removalListener(removalListener)
                .build(cacheLoader);
        cache.put(1,new User(1,"a"));
        cache.invalidate(1);
3.2.5 刷新值

刷新值和清除值是不一样的,刷新可能是异步的,在刷新的时候,旧值还能返回给前端。而且还能覆写reload方法来自定义刷新值的逻辑

 CacheLoader<Integer,User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }
        };


        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().maximumSize(3)
                .build(cacheLoader);
        cache.put(1,new User(1,"a"));
        Thread.sleep(4000);
        @Nullable User u1 = cache.getIfPresent(1);
        Thread.sleep(4000);
        @Nullable User u2 = cache.getIfPresent(1);
        Thread.sleep(4000);
        @Nullable User u3 = cache.getIfPresent(1);
        System.out.println(u1==u2);
        System.out.println(u2==u3);

打印结果都为false,说明值被刷新了

覆写reload的例子:

static final ExecutorService executor = Executors.newFixedThreadPool(4);
    public static void testRefresh() throws InterruptedException {

        CacheLoader<Integer, User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }

            @Override
            public ListenableFuture<User> reload(Integer key, User oldValue) throws Exception {
                if(key<0){
                   return Futures.immediateFuture(oldValue);
                }else {
                    ListenableFutureTask<User> task = ListenableFutureTask.create(()-> new User(key,"name"));
                    executor.execute(task);
                    return task;
                }
            }
        };


        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().maximumSize(3)
                //3秒钟刷新一次
                 .refreshAfterWrite(3, TimeUnit.SECONDS)
                .build(cacheLoader);
        cache.put(1,new User(1,"a"));
        cache.put(-1,new User(1,"a"));
        @Nullable User u1 = cache.getIfPresent(1);
        Thread.sleep(4000);
        @Nullable User u2 = cache.getIfPresent(1);
        System.out.println(u1==u2);
        Thread.sleep(4000);
        @Nullable User u3 = cache.getIfPresent(-1);
        Thread.sleep(4000);
        @Nullable User u4 = cache.getIfPresent(-1);
        System.out.println(u3==u4);
    }
3.2.6 其他特性

统计方法
cache.stats(),需要构建的时候加上recordStats()

  CacheLoader<Integer,User> cacheLoader=new CacheLoader<Integer, User>() {
            @Override
            public User load(Integer key) throws Exception {
                return new User(key,"王二");
            }
        };


        LoadingCache<Integer, User> cache = CacheBuilder.newBuilder().recordStats().maximumSize(3)
                .build(cacheLoader);
        cache.put(1,new User(1,"aa"));
        cache.getIfPresent(1);
        cache.getIfPresent(1);
        cache.getIfPresent(2);
        //加载新值所用的平均时间,以纳秒为单位
        System.out.println(cache.stats().averageLoadPenalty());
        //命中次数
        System.out.println(cache.stats().hitCount());
        //load次数
        System.out.println(cache.stats().loadCount());

3.3 Strings工具类

public static void testString(){
        Joiner joiner = Joiner.on(";").skipNulls();;
        String join = joiner.join("a", "b", null, "c");
        System.out.println(join); //a;b;c

        Iterable<String> split = Splitter.on(',')
                .trimResults()
                .omitEmptyStrings()
                .split("foo,bar,,   qux");
        System.out.println(split);  //[foo, bar, qux]

        //是否能匹配
        boolean b = CharMatcher.is('a').matchesAnyOf("abc");
        System.out.println(b);  //true
        //出现的次数
        int countIn = CharMatcher.is('a').countIn("abca");
        System.out.println(countIn);  //2
        //匹配指定的值
        String s = CharMatcher.is('a').retainFrom("bdaswa");  
        System.out.println(s);  //aa
    }

3.4 I/O处理类

CharSource charSource = Files.asCharSource(new File("d://1.txt"), Charset.forName("UTF-8"));
        ImmutableList<String> strings = charSource.readLines();

3.5 并发工具类

public static void testFuture() throws ExecutionException, InterruptedException {
        ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
        ListenableFuture<User> explosion = service.submit(
                new Callable<User>() {
                    public User call() throws InterruptedException {
                        Thread.sleep(2000);
                       return new User(1,"xxxx");
                    }
                });
        System.out.println("不阻塞,继续执行");
        Futures.addCallback(
                explosion,
                new FutureCallback<User>() {
                    // we want this handler to run immediately after we push the big red button!
                    public void onSuccess(User explosion) {
                        System.out.println("success:"+explosion);
                    }
                    public void onFailure(Throwable thrown) {
                        System.out.println("failure:"+thrown);
                    }
                },
                service);
    }

3.6 反射

public class LogHandler implements InvocationHandler {
        Object target;  // 被代理的对象,实际的方法执行者

        public LogHandler(Object target) {
            this.target = target;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object result = method.invoke(target, args);  // 调用 target 的 method 方法
            after();
            return result;  // 返回方法的执行结果
        }
        // 调用invoke方法之前执行
        private void before() {
            System.out.println(String.format("log start time [%s] ", new Date()));
        }
        // 调用invoke方法之后执行
        private void after() {
            System.out.println(String.format("log end time [%s] ", new Date()));
        }
}
    
    public  void testReflection(){
        GoodsService goodsService = Reflection.newProxy(GoodsService.class,new LogHandler(new GoodsServiceImpl()));
        goodsService.updatePrice(1,2.0);
    }

3.7 事件总线 EventBus

发布-订阅模式的组件通信,进程内模块间解耦

@Data
@AllArgsConstructor
public class UserEvent {

    private User user;

    private String remark;


}
public class UserHandler {

    @Subscribe
    public void handle(UserEvent userEvent){
        System.out.println("取到user:"+userEvent.getUser());
    }
}
static EventBus eventBus=new EventBus();
//异步的
//static EventBus eventBus=new AsyncEventBus(Executors.newSingleThreadExecutor());
    static {
        //eventBus会去找注册进去的类 @Subscribe标记的方法
        eventBus.register(new UserHandler());
    }

    public static void testEvent(){
        eventBus.post(new UserEvent(new User(1,"ab"),"测试"));
    }
posted @ 2021-06-21 22:03  女友在高考  阅读(333)  评论(0编辑  收藏  举报