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
}

@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(不可變)集合
