Google Guava参考笔记

Joiner详细介绍以及和Java8Collector对比

Joiner
    @Test
    public void testJoiner(){
        // 字符串处理Joiner
        final List<String> list = Arrays.asList("a","b","c",null);
//        System.out.println(Joiner.on("#").join(list)); //NullPointerException
        System.out.println(Joiner.on("#").useForNull("default").join(list)); //a#b#c#default
        System.out.println(Joiner.on("#").skipNulls().join(list)); //a#b#c

        final Map<String,String> map = ImmutableMap.of("h1","v1","h2","v2");
        System.out.println(Joiner.on("#").withKeyValueSeparator("=").join(map)); //h1=v1#h2=v2
    }

Joiner.on("#").useForNull("default").appendTo()也可以写到StringBuilder、StringBuffer、FileWriter等里面

JAVA8中的Collectors实现
String collect = list.stream().filter(item -> item != null && !item.isEmpty()).collect(Collectors.joining("#")); 
System.out.println(collect);//a#b#c

String collect = list.stream()
                .map(item -> item == null || item.isEmpty() ? "default" : item)
                .filter(item -> !item.isEmpty())
                .collect(Collectors.joining("#")); //a#b#c
System.out.println(collect); //a#b#c#default

Guava Splitter详细介绍

Splitter
    @Test
    public void testSplit(){
        String str = "a#b#c#  #e##";
        System.out.println(Splitter.on("#").splitToList(str)); //[a, b, c,   , e, , ]
        System.out.println(Splitter.on("#").omitEmptyStrings().splitToList(str)); //[a, b, c,   , e]
        System.out.println(Splitter.on("#").trimResults().omitEmptyStrings().splitToList(str)); //[a, b, c, e]
        System.out.println(Splitter.fixedLength(4).splitToList(str)); //[a#b#, c#  , #e##]
        System.out.println(Splitter.on("#").limit(2).splitToList(str)); //[a, b#c#  #e##] 两个元素

        String str2 = "a1=a;b1=b";
        //Map
        System.out.println(Splitter.on(";").withKeyValueSeparator("=").split(str2)); //{a1=a, b1=b}
    }

还可以支持正则切分


正则

Preconditions&Objects&assert断言介绍

Preconditions
    @Test
    public void testPreconditions(){
        List<String> list = null;
        checkNotNullWithMsg(list); //java.lang.NullPointerException: this is null
    }

    private void checkNotNullWithMsg(List<String> list){
        Preconditions.checkNotNull(list,"this is null");
    }
Objects
Objects.requireNonNull(null); //java.lang.NullPointerException
...
assert
List<String> list = null;
assert list != null; //java.lang.AssertionError
assert list != null : "this is msg"; //java.lang.AssertionError: this is msg
...

ComparisonChain比较器

    @Test
    public void testObjects(){
        Guava g1 = new Guava("1","2",new Date());
        Guava g2 = new Guava("2","2",new Date());
        Guava g3 = new Guava("3","2",new Date());
        System.out.println(g1.compareTo(g2)); // -1
        System.out.println(g3.compareTo(g2)); // 1
    }
    static class Guava implements Comparable<Guava>{
        private final String factory;
        private final String version;
        private final Date date;

        public Guava(String factory, String version, Date date) {
            this.factory = factory;
            this.version = version;
            this.date = date;
        }

        @Override
        public int compareTo(Guava o) {
            return ComparisonChain.start().compare(this.factory,o.factory)
                    .compare(this.version,o.version)
                    .compare(this.date,o.date).result();
        }
    }

Strings&Charsets&CharMatcher介绍

    @Test
    public void testStrings(){
        System.out.println(Strings.emptyToNull("")); //null
        System.out.println(Strings.nullToEmpty(null)); //""
        System.out.println(Strings.nullToEmpty("h")); //h
        System.out.println(Strings.commonPrefix("d1","d2")); //d
        System.out.println(Strings.repeat("d1",3)); //d1d1d1
    }
Strings方法
    @Test
    public void testCharsets(){
        Charset charset = Charset.forName("UTF-8");
        Charset charset2 = Charsets.UTF_8;
    }
    @Test
    public void testCharMatcher(){
        System.out.println(CharMatcher.is('A').countIn("Alex A a b")); //2
        System.out.println(CharMatcher.breakingWhitespace().collapseFrom("Alex     A a b", '*')); //Alex*A*a*b
        System.out.println(CharMatcher.javaDigit().or(CharMatcher.whitespace()).removeFrom("Alex     A a b 1 231"));//AlexAab
    }

函数式接口

Function

Function<传入类型,输出类型>

public class FunctionExample {
    public static void main(String[] args) {
        //传进去一个词,返回一个这个词的长度<String(传入类型),Integer(输出类型)>
        Function<String, Integer> getLength = new Function<String, Integer>() {
            @Override
            public Integer apply(String input) {
                Preconditions.checkNotNull(input, "check is null");
                return input.length();
            }
        };

        Integer testLength = getLength.apply("test");
        System.out.println(testLength);
//        Functions

    }
}

Supplier

提供结果的函数接口.只有返回值,没有输入参数

public class FunctionExample {
    public static void main(String[] args) {
        //这是一个提供结果的函数接口.
        //(1)只有返回值
        //(2)没有输入参数
        Supplier<String> supplier = new Supplier<String>() {
            @Overrider
            public String get() {
                System.out.println(111);
                return "test";
            }
        };
        String s = supplier.get();
        System.out.println(s);
        //Suppliers
    }
}
Predicate

提供test()方法,输出boolean

public class FunctionExample {
    public static void main(String[] args) {
        Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean apply(String input) {
                return Objects.equals("test",input);
            }
        };
        boolean test1 = predicate.equals(predicate); // true
        boolean test2 = predicate.test("test2"); // false
        boolean test3 = predicate.equals("test"); //false
        boolean test4 = predicate.test("test");//true
        
        //Predicates...

    }
}

StopWatch

类似于 结束时间 - 开始时间

public class WatchExample {
    public static void main(String[] args) throws Exception {
        // 创建自动start的计时器
        Stopwatch watch = Stopwatch.createStarted();
        Thread.sleep(1000L);
        long time = watch.elapsed(TimeUnit.MILLISECONDS);
        // 结果1003
        System.out.println("代码执行时长:" + time);

        // 创建非自动start的计时器
        // 累计了start到stop的时间
        Stopwatch watch1 = Stopwatch.createUnstarted();
        Thread.sleep(1000L);
        watch1.start();
        Thread.sleep(1000L);
        watch1.stop();
        watch1.start();
        Thread.sleep(500L);
        time = watch1.elapsed(TimeUnit.MILLISECONDS);
        // 结果1500
        System.out.println("代码执行时长:" + time);

        Stopwatch watch2 = Stopwatch.createUnstarted();
        watch2.start();
        Thread.sleep(1000L);
        time = watch2.elapsed(TimeUnit.MILLISECONDS);
        // 结果1000
        System.out.println("代码执行时长:" + time);
    }
}

IO Files

对InputStream,OutputStream等的一些封装,提供了很多API,
官方文档:https://guava.dev/releases/27.0.1-jre/api/docs/com/google/common/io/Files.html

CharSource和CharSink

ByteSource和ByteSink

Closer使用

try...catch...finally的优化

Base*coding

EventBus

EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现,在应用中可以处理一些异步任务。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。
EventBus实际上是一个消息队列,Event Source发送一个消息到EventBus,然后再由EventBus将消息推送到所监听的Listener。
https://blog.csdn.net/wangdong5678999/article/details/80561198

Monitor

Monitor是一个支持任意布尔条件的同步的抽象,Monitor类是作为ReentrantLock的一个替代,代码中使用Monitor比使用ReentrantLock更不易出错,可读性也更强,并且也没有显著的性能损失,使用Monitor甚至有潜在的性能得到优化
https://www.cnblogs.com/hupengcool/p/4250903.html

RateLimiter

常用的限流算法有漏桶算法和令牌桶算法
https://www.jianshu.com/p/8f548e469bbe
https://blog.csdn.net/fanrenxiang/article/details/80949079

简单Demo:
public class RateLimiterExample {
    // 一秒钟允许多少个操作
    private final static RateLimiter limiter = RateLimiter.create(0.5); // 一秒钟允许0.5个操作,2秒钟1次操作
    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(10);
        IntStream.range(0,10).forEach( i -> {
            service.submit(RateLimiterExample::testLimiter);
        });
    }
    private static void testLimiter(){
        System.out.println(Thread.currentThread() + "waiting " + limiter.acquire());
    }
}
---大约两秒打印一次
Thread[pool-1-thread-1,5,main]waiting 0.0
Thread[pool-1-thread-2,5,main]waiting 1.874738
Thread[pool-1-thread-3,5,main]waiting 3.872905
Thread[pool-1-thread-5,5,main]waiting 5.871703
Thread[pool-1-thread-4,5,main]waiting 7.871677
Thread[pool-1-thread-6,5,main]waiting 9.871123
Thread[pool-1-thread-7,5,main]waiting 11.870788
Thread[pool-1-thread-8,5,main]waiting 13.870773
Thread[pool-1-thread-9,5,main]waiting 15.870581
Thread[pool-1-thread-10,5,main]waiting 17.869938


限流桶实现

public class Bucket
{

    private final ConcurrentLinkedQueue<Integer> container = new ConcurrentLinkedQueue<>();

    private final static int BUCKET_LIMIT = 1000;

    private final RateLimiter limiter = RateLimiter.create(10);

    private final Monitor offerMonitor = new Monitor();
    private final Monitor pollMonitor = new Monitor();

    public void submit(Integer data)
    {
        if (offerMonitor.enterIf(offerMonitor.newGuard(() -> container.size() < BUCKET_LIMIT)))
        {
            try
            {
                container.offer(data);
                System.out.println(currentThread() + " submit data " + data + ",current size:" + container.size());
            } finally
            {
                offerMonitor.leave();
            }
        } else
        {
            throw new IllegalStateException("The bucket is full.");
        }
    }


    public void takeThenConsume(Consumer<Integer> consumer)
    {
        if (pollMonitor.enterIf(pollMonitor.newGuard(() -> !container.isEmpty())))
        {
            try
            {
                System.out.println(currentThread() + " waiting " + limiter.acquire());
                consumer.accept(container.poll());
            } finally
            {
                pollMonitor.leave();
            }
        }
    }
}

public class BucketTest
{

    public static void main(String[] args)
    {
        final Bucket bucket = new Bucket();
        final AtomicInteger DATA_CREATOR = new AtomicInteger(0);

        IntStream.range(0, 5).forEach(i ->
        {
            new Thread(() ->
            {
                for (; ; )
                {
                    int data = DATA_CREATOR.getAndIncrement();
                    bucket.submit(data);
                    try
                    {
                        TimeUnit.MILLISECONDS.sleep(200L);
                    } catch (Exception e)
                    {
                        if (e instanceof IllegalStateException)
                        {
                            System.out.println(e.getMessage());
                        }
                    }
                }       //25

                //10

                //5:2
            }).start();
        });


        IntStream.range(0, 5)
                .forEach(i -> new Thread(() ->
                        {
                            for (; ; )
                            {
                                bucket.takeThenConsume(x -> System.out.println(currentThread() + " W " + x));
                            }
                        }).start()
                );
    }
}

令牌桶实现

public class TokenBucket
{

    private AtomicInteger phoneNumbers = new AtomicInteger(0);

    private final static int LIMIT = 100;

    private RateLimiter rateLimiter = RateLimiter.create(10);

    private final int saleLimit;

    public TokenBucket()
    {
        this(LIMIT);
    }

    public TokenBucket(int limit)
    {
        this.saleLimit = limit;
    }

    public int buy()
    {
        Stopwatch started = Stopwatch.createStarted();
        boolean success = rateLimiter.tryAcquire(10, TimeUnit.SECONDS);
        if (success)
        {
            if (phoneNumbers.get() >= saleLimit)
            {
                throw new IllegalStateException("Not any phone can be sale, please wait to next time.");
            }
            int phoneNo = phoneNumbers.getAndIncrement();
            handleOrder();
            System.out.println(currentThread() + " user get the Mi phone: " + phoneNo + ",ELT:" + started.stop());
            return phoneNo;
        } else
        {
            started.stop();
            throw new RuntimeException("Sorry, occur exception when buy phone");
        }
    }

    private void handleOrder()
    {
        try
        {
            TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}

public class TokenBucketExample
{

    public static void main(String[] args)
    {
        final TokenBucket tokenBucket = new TokenBucket();
        for (int i = 0; i < 200; i++)
        {
            new Thread(tokenBucket::buy).start();
        }
    }
}

ListenableFuture

FutureCallBack

JDK8:CompletableFuture

Cache

Google Guava 快速入门 —— Cache 缓存工具
自定义LRU算法的缓存实现
软引用SoftReference介绍以及简单用法cache
理解StrongReference,SoftReference, WeakReference的区别 SoftReference:当快OOM时才进行回收。 WeakReference:只要调用GC就会被回收。

Cache简单Demo
LoadingCache<String, Object> employeeCache = CacheBuilder.newBuilder()
        .maximumSize(100) // 最多可以缓存100条记录
        .expireAfterAccess(30, TimeUnit.MINUTES) // 缓存将在访问30分钟后过期
        .build(new CacheLoader<String, Object>() {
            @Override
            public Object load(String key) throws Exception {
                // 数据库加载
                return getFromDatabase(key);
            }
        });
第一次调用加载数据库中的数据,第二次调用走缓存
employeeCache.get("key");
employeeCache.getUnchecked("key");

Guava库学习:学习Guava Cache(四)CacheBuilderSpec

Collections

FluentIterable

主要用于过滤集合

Lists

Guava提供了能够推断范型的静态工厂方法
用工厂方法模式,我们可以方便地在初始化时就指定起始元素
通过为工厂方法命名,我们可以提高集合初始化大小的可读性
java代码之美(9)---guava之Lists、Maps

Sets
Maps,BiMap,MultiMap
Table,Range

当我们需要多个索引的数据结构的时候,通常情况下,我们只能用这种丑陋的Map<FirstName, Map<LastName, Person>>来实现。为此Guava提供了一个新的集合类型-Table集合类型,来支持这种数据结构的使用场景。Table支持“row”和“column”,而且提供多种视图。

Range,RangeMap

Guava学习笔记:Guava新集合-Table等

Immutable Collections,Sorted Collections

java代码之美(4)---guava之Immutable(不可变)集合


Google Guava 快速入门
Guava库学习
Java--代码之美

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容