Google Guava參考筆記

Joiner詳細(xì)介紹以及和Java8Collector對(duì)比

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實(shí)現(xiàn)
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詳細(xì)介紹

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##] 兩個(gè)元素

        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
    }

函數(shù)式接口

Function

Function<傳入類型,輸出類型>

public class FunctionExample {
    public static void main(String[] args) {
        //傳進(jìn)去一個(gè)詞,返回一個(gè)這個(gè)詞的長(zhǎng)度<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

提供結(jié)果的函數(shù)接口.只有返回值,沒有輸入?yún)?shù)

public class FunctionExample {
    public static void main(String[] args) {
        //這是一個(gè)提供結(jié)果的函數(shù)接口.
        //(1)只有返回值
        //(2)沒有輸入?yún)?shù)
        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

類似于 結(jié)束時(shí)間 - 開始時(shí)間

public class WatchExample {
    public static void main(String[] args) throws Exception {
        // 創(chuàng)建自動(dòng)start的計(jì)時(shí)器
        Stopwatch watch = Stopwatch.createStarted();
        Thread.sleep(1000L);
        long time = watch.elapsed(TimeUnit.MILLISECONDS);
        // 結(jié)果1003
        System.out.println("代碼執(zhí)行時(shí)長(zhǎng):" + time);

        // 創(chuàng)建非自動(dòng)start的計(jì)時(shí)器
        // 累計(jì)了start到stop的時(shí)間
        Stopwatch watch1 = Stopwatch.createUnstarted();
        Thread.sleep(1000L);
        watch1.start();
        Thread.sleep(1000L);
        watch1.stop();
        watch1.start();
        Thread.sleep(500L);
        time = watch1.elapsed(TimeUnit.MILLISECONDS);
        // 結(jié)果1500
        System.out.println("代碼執(zhí)行時(shí)長(zhǎng):" + time);

        Stopwatch watch2 = Stopwatch.createUnstarted();
        watch2.start();
        Thread.sleep(1000L);
        time = watch2.elapsed(TimeUnit.MILLISECONDS);
        // 結(jié)果1000
        System.out.println("代碼執(zhí)行時(shí)長(zhǎng):" + time);
    }
}

IO Files

對(duì)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的優(yōu)化

Base*coding

EventBus

EventBus是Guava的事件處理機(jī)制,是設(shè)計(jì)模式中的觀察者模式(生產(chǎn)/消費(fèi)者編程模型)的優(yōu)雅實(shí)現(xiàn),在應(yīng)用中可以處理一些異步任務(wù)。對(duì)于事件監(jiān)聽和發(fā)布訂閱模式,EventBus是一個(gè)非常優(yōu)雅和簡(jiǎn)單解決方案,我們不用創(chuàng)建復(fù)雜的類和接口層次結(jié)構(gòu)。
EventBus實(shí)際上是一個(gè)消息隊(duì)列,Event Source發(fā)送一個(gè)消息到EventBus,然后再由EventBus將消息推送到所監(jiān)聽的Listener。
https://blog.csdn.net/wangdong5678999/article/details/80561198

Monitor

Monitor是一個(gè)支持任意布爾條件的同步的抽象,Monitor類是作為ReentrantLock的一個(gè)替代,代碼中使用Monitor比使用ReentrantLock更不易出錯(cuò),可讀性也更強(qiáng),并且也沒有顯著的性能損失,使用Monitor甚至有潛在的性能得到優(yōu)化
https://www.cnblogs.com/hupengcool/p/4250903.html

RateLimiter

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

簡(jiǎn)單Demo:
public class RateLimiterExample {
    // 一秒鐘允許多少個(gè)操作
    private final static RateLimiter limiter = RateLimiter.create(0.5); // 一秒鐘允許0.5個(gè)操作,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


限流桶實(shí)現(xiàn)

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()
                );
    }
}

令牌桶實(shí)現(xiàn)

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算法的緩存實(shí)現(xiàn)
軟引用SoftReference介紹以及簡(jiǎn)單用法cache
理解StrongReference,SoftReference, WeakReference的區(qū)別 SoftReference:當(dāng)快OOM時(shí)才進(jìn)行回收。 WeakReference:只要調(diào)用GC就會(huì)被回收。

Cache簡(jiǎn)單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 {
                // 數(shù)據(jù)庫(kù)加載
                return getFromDatabase(key);
            }
        });
第一次調(diào)用加載數(shù)據(jù)庫(kù)中的數(shù)據(jù),第二次調(diào)用走緩存
employeeCache.get("key");
employeeCache.getUnchecked("key");

Guava庫(kù)學(xué)習(xí):學(xué)習(xí)Guava Cache(四)CacheBuilderSpec

Collections

FluentIterable

主要用于過濾集合

Lists

Guava提供了能夠推斷范型的靜態(tài)工廠方法
用工廠方法模式,我們可以方便地在初始化時(shí)就指定起始元素
通過為工廠方法命名,我們可以提高集合初始化大小的可讀性
java代碼之美(9)---guava之Lists、Maps

Sets
Maps,BiMap,MultiMap
Table,Range

當(dāng)我們需要多個(gè)索引的數(shù)據(jù)結(jié)構(gòu)的時(shí)候,通常情況下,我們只能用這種丑陋的Map<FirstName, Map<LastName, Person>>來實(shí)現(xiàn)。為此Guava提供了一個(gè)新的集合類型-Table集合類型,來支持這種數(shù)據(jù)結(jié)構(gòu)的使用場(chǎng)景。Table支持“row”和“column”,而且提供多種視圖。

Range,RangeMap

Guava學(xué)習(xí)筆記:Guava新集合-Table等

Immutable Collections,Sorted Collections

java代碼之美(4)---guava之Immutable(不可變)集合


Google Guava 快速入門
Guava庫(kù)學(xué)習(xí)
Java--代碼之美

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容