guava学习

guava介绍

guava是google推出的一个java集合框架,对java.util.collection包进行了再次的封装, 提供了更加便捷的结合工具
例如Lists,Maps,multiset, multimap, bimap,table等等


multiset可以理解为在set的基础上对相同的元素进行了统计(count), 有elementSet方法列出不同的key的set集合

multilist就是Map<Object>,List<Object>> 相同的key的元素会被放到一个List中去, 不需要些复杂的泛型机构

bimap 简单的理解为可以通过调用inverse方法后, 通过value来索引key (倒转了索引的顺序)‘’‘

table (x, y)-->value ; 简单的理解就是一个坐标系, 根据x轴和y轴可以定位到某个元素;
package com.derbysoft.guava;

import com.google.common.collect.*;

import java.util.Collection;
import java.util.Map;

/**
 * @author thunderstorm.shen on 2020/1/2
 */
public class CollectionTest {

    public static void main(String[] args) {
        multiset();

        multimap();

        bimap();

        table();


    }

    /**
     * <table width="600px" border="1px"  cellspacing="0" cellpadding="0" style="text-align: center; border-color: red">
     * <tr>
     *     <td></td>
     *     <td>A</td>
     *     <td>B</td>
     *     <td>C</td>
     * </tr>
     * <tr>
     *     <td>001</td>
     *     <td>java</td>
     *     <td>python</td>
     *     <td></td>
     * </tr>
     * <tr>
     *     <td>002</td>
     *     <td>c++</td>
     *     <td></td>
     *     <td></td>
     * </tr>
     * <tr>
     *     <td>003</td>
     *     <td></td>
     *     <td>groovy</td>
     *     <td></td>
     * </tr>
     * <tr>
     *     <td>004</td>
     *     <td></td>
     *     <td></td>
     *     <td>android</td>
     * </tr>
     *
     * </table>
     */
    private static void table() {
        Table<String, String, String> table = HashBasedTable.create();
        table.put("001", "A", "java");
        table.put("001", "B", "python");
        table.put("002", "A", "c++");
        table.put("003", "B", "groovy");
        table.put("004", "C", "android");

        Map<String, String> row = table.row("001");
        System.out.println("001 row : " + row);

        Map<String, String> column = table.column("A");
        System.out.println("A column: " + column);


        Collection<String> values = table.values();
        System.out.println("values : " + values);

        System.out.println(table);
    }

    private static void bimap() {
        BiMap<String, String> biMap = HashBiMap.create();
        biMap.put("0001", "tom");
        biMap.put("0002", "jack");
        biMap.put("0003", "bob");
        //bimap inverse 之后可以从value来索引key
        System.out.println(biMap.inverse().get("tom"));
    }

    private static void multimap() {
        Multimap<String, String> multimap = ArrayListMultimap.create();
        multimap.put("lower", "a");
        multimap.put("lower", "b");
        multimap.put("lower", "c");
        multimap.put("lower", "d");

        multimap.put("upper", "1");
        multimap.put("upper", "2");
        multimap.put("upper", "3");
        multimap.put("upper", "4");

        System.out.println(multimap);

        System.out.println(multimap.get("lower"));
        System.out.println(multimap.get("upper"));

        Map<String, Collection<String>> map = multimap.asMap();
        for (String key : map.keySet()) {
            System.out.println(key + " " + map.get(key));

        }
    }

    private static void multiset() {
        Multiset<String> multiset = HashMultiset.create();
        multiset.add("a");
        multiset.add("a");
        multiset.add("b");
        multiset.add("b");
        multiset.add("c");
        multiset.add("c");
        multiset.add("d");

        System.out.println(multiset.size());
        System.out.println(multiset.elementSet());
        System.out.println(multiset);
    }
}

还有一个是对future进行了封装, 在futrue的基础上添加了监听器, callback成功和失败的回调函数;

for example: addListener方法对ListenableFutrue添加了一个Runnable任务进行监听;
             addCallback方法 是通过Futures静态方法来为ListenableFuture添加了一个FutrueCallback
package com.derbysoft.guava;

import com.derbysoft.common.util.ThreadUtils;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.*;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.util.StopWatch;

import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * refer github : https://github.com/google/guava/wiki/ListenableFutureExplained
 * guava guide: https://www.tutorialspoint.com/guava/guava_overview.htm
 *
 * @author thunderstorm.shen
 *         Created by thunderstorm.shen on 2019/12/31.
 */
public class ThreadPoolListener {

    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 8, 100,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
        ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(threadPoolExecutor);
        List<String> list = Lists.newArrayList("java", "c++", "php");

        addListener(threadPoolExecutor, listeningExecutorService, list);
        addCallback(listeningExecutorService, list);

        ThreadUtils.sleep(5, TimeUnit.SECONDS);
        listeningExecutorService.shutdownNow();


    }

    private static void addCallback(ListeningExecutorService listeningExecutorService, List<String> list) {
        for (String s : list) {
            ListenableFuture<String> future = listeningExecutorService.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    ThreadUtils.sleep(2, TimeUnit.SECONDS);
                    return s.toUpperCase();
                }
            });

            Futures.addCallback(future, new FutureCallback<String>() {
                @Override
                public void onSuccess(@Nullable String result) {
                    System.out.println("onSuccess : " + result + " " + Thread.currentThread().getName());
                }

                @Override
                public void onFailure(Throwable t) {
                    System.out.println("task is failed ");
                }
            }, listeningExecutorService);
        }
    }

    private static void addListener(ThreadPoolExecutor threadPoolExecutor, ListeningExecutorService listeningExecutorService, List<String> list) {
        final AtomicInteger num = new AtomicInteger(list.size());
        StopWatch stopWatch = new StopWatch("guava-listener");
        stopWatch.start();
        for (String s : list) {
            ListenableFuture<String> future = listeningExecutorService.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    ThreadUtils.sleep(2, TimeUnit.SECONDS);
                    return s.toUpperCase();
                }
            });

            future.addListener(new Runnable() {
                @Override
                public void run() {
                    try {
                        num.getAndDecrement();
                        System.out.println(future.get());
                        System.out.println(num.get());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }, listeningExecutorService);
        }

        if (num.get() == 0) {
            threadPoolExecutor.shutdown();
            stopWatch.stop();
            System.out.println(stopWatch.prettyPrint());
        }
    }

}

guava还提供了一种cache的方法, 可以设置expire时间, cache的capacity容量可以从DB加载数据缓存到内存里面去;    
package com.derbysoft.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @author thunderstorm.shen on 2020/1/2
 */
public class CacheTest {
    public static void main(String[] args) throws ExecutionException {
        LoadingCache<String, MemoryCache> cache = CacheBuilder.newBuilder().maximumSize(100)
                .expireAfterAccess(30, TimeUnit.MINUTES)
                .build(new CacheLoader<String, MemoryCache>() {
                    @Override
                    public MemoryCache load(String key) throws Exception {
                        return new MemoryCache(key, UUID.randomUUID().toString());
                    }
                });

        System.out.println(cache.get("java"));
        cache.refresh("java");
    }


    static class MemoryCache {

        private String key;

        private Object value;

        public MemoryCache(String key, Object value) {
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public Object getValue() {
            return value;
        }

        public void setValue(Object value) {
            this.value = value;
        }

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer("MemoryCache{");
            sb.append("key='").append(key).append('\'');
            sb.append(", value=").append(value);
            sb.append('}');
            return sb.toString();
        }
    }
}