guava学习

Guava是Google出品的一套Java核心库。相较于Java中自带的一些库来说,使用很方便。推荐使用。
以下示例引用的是guava-18.0.jar

1.Guava对JDK集合的扩展

1.简化集合的创建
 Map<String, Map<String, String>> map1 = Maps.newHashMap();
List<List<Map<String, String>>> arrayList = Lists.newArrayList();
List<String> exactly100 = Lists.newArrayListWithCapacity(100);
List<String> linkedList = Lists.newLinkedList();
Set<String> Set = Sets.newHashSet();
Map<String, String> map2 = Maps.newHashMap();
Integer[] intArrays = ObjectArrays.newArray(Integer.class, 10);
 2.简化集合的初始化
Set<String> set = Sets.newHashSet("one", "two", "three");
List<String> list1 = Lists.newArrayList("one", "two", "three");
Set<String> set2 = Sets.newHashSet(new String("a"), new String("b"));
Set<String> set1 = ImmutableSet.of("one", "two", "three");// 不可变集合
// 或则调用ImmutableSet.copyOf(set)来创建 不可变集合
Map<String, String> map3 = ImmutableMap.of("ON", "TRUE", "OFF", "FALSE");
// map3.put("a", "c")-----抛出java.lang.UnsupportedOperationException
// Builder工具创建 不可变集合
ImmutableSet<String> set4 = ImmutableSet.<String> builder()
		.add(new String("a")).add(new String("b")).add(new String("a"))
		.build();
System.out.println(set4);// [a, d]
// 对有序不可变集合来说,排序是可以在构造集合的时候完成
Set<String> set5 = ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
System.out.println(set5);// [a, b, c, d]

// asList视图,所有不可变集合都有一个asList()方法提供ImmutableList视图
System.out.println(set4.asList().get(1));// b
3.新的集合类型
3.1 MultiMap
key可以重复的map,子类有ListMultimap和SetMultimap,对应的通过key分别得到list和set
 customersByType = ArrayListMultimap.create();
customersByType.put("abc", new String("aaa"));
customersByType.put("abc", new String("bbb"));
customersByType.put("abc", new String("ccc"));
customersByType.put("abc", new String("ddd"));
customersByType.put("abcd", new String("eee"));
customersByType.put("abcde", new String("fff"));
// 以集合形式返回键所对应的值视图,即使没有任何对应的值,也会返回空集合
System.out.println(customersByType.get("abc"));// aaa bbb ccc ddd
// ListMultimap.get(key)返回List,SetMultimap.get(key)返回Set。
3.2 MultiSet(场景:统计一个词在文档中出现了多少次)
不是集合,可以增加重复的元素,并且可以统计出重复元素的个数
// Multiset元素的顺序是无关紧要的:Multiset {a, a, b}和{a, b, a}是相等的
Multiset<Integer> multiSet = HashMultiset.create();
multiSet.add(10);
multiSet.add(30);
multiSet.add(30);
multiSet.add(40);
System.out.println(multiSet.count(30)); // 2
System.out.println(multiSet.size()); // 4
// add(E, int)------增加给定元素在Multiset中的计数
// remove(E, int)------减少给定元素在Multiset中的计数
// setCount(E, int)-----设置给定元素在Multiset中的计数,不可以为负数
3.3 Table
相当于有两个key的map
Table<Integer, Integer, String> personTable = HashBasedTable.create();
personTable.put(1, 20, new String("1--20"));
personTable.put(0, 30, new String("0--30"));
personTable.put(0, 25, new String("0--25"));
personTable.put(1, 50, new String("1--50"));
personTable.put(0, 27, new String("0--27"));
personTable.put(1, 29, new String("1--29"));
personTable.put(0, 33, new String("0--33"));
personTable.put(1, 66, new String("1--66"));

// 得到行集合
Map<Integer, String> rowMap = personTable.row(0);
System.out.println(rowMap);// {25=0--25, 33=0--33, 27=0--27,
// 30=0--30}
int maxAge = Collections.max(rowMap.keySet());
// System.out.println(maxAge);// 33
3.4 BiMap
是一个一一映射,可以通过key得到value,也可以通过value得到key;
BiMap<Integer, String> biMap = HashBiMap.create();
biMap.put(1, "hello");
biMap.put(2, "helloa");
biMap.put(3, "world");
biMap.put(4, "worldb");
biMap.put(5, "my");
biMap.put(6, "myc");

int value = biMap.inverse().get("my");
System.out.println("my--" + value + ", " + value + "--"
		+ biMap.get(value));


2. 处理null或空

Guava用Optional<T>表示可能为null的T类型引用。一个Optional实例可能包含非null的引用(称之为引用存在),也可能什么也不包括(称之为引用缺失)。它从不说包含的是null值,而是用存在或缺失来表示。 但Optional从不会包含null值引用。
Optional<Integer> possible = Optional.of(5);
// Optional.of(T)----
// 创建指定引用的Optional实例,若引用为null则快速失败,抛出java.lang.NullPointerException
// Optional.absent()-----创建引用缺失的Optional实例
// Optional.fromNullable(T)-----
// 创建指定引用的Optional实例,若引用为null则表示缺失(即Optional.absent())

// .isPresent()---
// 如果Optional包含非null的引用(引用存在),返回true
possible.isPresent();
System.out.println(possible.isPresent());// returns true

// .get()---
// 返回Optional所包含的引用,若引用缺失,则抛出java.lang.IllegalStateException
possible.get();
System.out.println(possible.get());// returns 5

// .or(T)---
// 返回Optional所包含的引用,若引用缺失,返回指定的值
possible.or(1);

// .orNull()---
// 返回Optional所包含的引用,若引用缺失,返回null
possible.orNull();

// 处理null或空字符
String aString = "";
String bString = null;
String cString = "aaa";
System.out.println(Strings.emptyToNull(aString));//null
System.out.println(Strings.emptyToNull(bString));//null
System.out.println(Strings.emptyToNull(cString));//aaa
System.out.println(Strings.nullToEmpty(aString));//空("")
System.out.println(Strings.nullToEmpty(bString));//空("")
System.out.println(Strings.nullToEmpty(cString));//aaa
System.out.println(Strings.isNullOrEmpty(aString));//true
System.out.println(Strings.isNullOrEmpty(bString));//true
System.out.println(Strings.isNullOrEmpty(cString));//false

3.排序器Ordering

List<String> list = Lists.newArrayList("22", "a", "bb", "11", "ccc");
// Ordering.natural()-------对可排序类型做自然排序,如数字按大小,日期按先后排序
list = Ordering.natural().sortedCopy(list);
System.out.println(list);// [11, 22, a, bb, ccc]

// Ordering.usingToString()------按对象的字符串形式做字典排序
list = Ordering.usingToString().sortedCopy(list);
System.out.println(list);// [11, 22, a, bb, ccc]

// Ordering.from(comparator)-------把给定的Comparator转化为排序器
Comparator<String> comparator = new Comparator<String>() {
	@Override
	public int compare(String o1, String o2) {
		// TODO Auto-generated method stub
		return o1.hashCode() - o2.hashCode();
	}
};
list = Ordering.from(comparator).sortedCopy(list);
System.out.println(list);// [a, 11, 22, bb, ccc]

// 实现自定义的排序器时,除了用上面的from方法,也可以跳过实现Comparator,而直接继承Ordering:
Ordering<String> byLenOrdering = new Ordering<String>() {
	public int compare(String left, String right) {
		return Ints.compare(left.length(), right.length());
	}
};

list = byLenOrdering.sortedCopy(list);
System.out.println(list);// [a, 11, 22, bb, ccc]

// 链式调用方法:通过链式调用,可以由给定的排序器衍生出其它排序器
// 1.reverse()-----获取语义相反的排序器
// 2.nullsFirst()-----使用当前排序器,但额外把null值排到最前面
// 3.nullsLast()-----使用当前排序器,但额外把null值排到最后面
// 4.compound(Comparator)-----合成另一个比较器,以处理当前排序器中的相等情况
// -------用compound方法包装排序器时,就不应遵循从后往前读的原则。
// -------为了避免理解上的混乱,请不要把compound写在一长串链式调用的中间,你可以另起一行,在链中最先或最后调用compound。
// 5.lexicographical()-----基于处理类型T的排序器,返回该类型的可迭代对象Iterable<T>的排序器
// 6.onResultOf(Function)-----对集合中元素调用Function,再按返回值用当前排序器排序
list = byLenOrdering.reverse().sortedCopy(list);
System.out.println(list);// [ccc, 11, 22, bb, a]

4.String处理工具

1.连接器[Joiner]
public static void testJoiner() {
	// .on("; ")以,分隔 ;.skipNulls()忽略null
	Joiner joiner = Joiner.on("; ").skipNulls();
	String aString = joiner.join("aaa", null, "bbb", "ccc");
	System.out.println(aString);// aaa; bbb; ccc

	// useForNull(String)方法可以给定某个字符串来替换null
	joiner = Joiner.on("; ").useForNull("ccc");
	aString = joiner.join("aaa", null, "bbb", "ccc");
	System.out.println(aString);// aaa; ccc; bbb; ccc

	Joiner.on(";").join(Arrays.asList(1, 5, 7)); // returns "1;5;7"
	// joiner实例总是不可变的。用来定义joiner目标语义的配置方法总会返回一个新的joiner实例。
	// 这使得joiner实例都是线程安全的,你可以将其定义为static final常量。
}
2.拆分器[Splitter]
public static void testSplitter() {
	// String.split悄悄丢弃了尾部的分隔符
	String[] strs = ",a,,b,".split(",");
	System.out.println(Arrays.toString(strs));// [, a, , b]

	
	//omitEmptyStrings()-----从结果中自动忽略空字符串
	//trimResults()-----移除结果字符串的前导空白和尾部空白
	//trimResults(CharMatcher)-----给定匹配器,移除结果字符串的前导匹配字符和尾部匹配字符
	//limit(int)-----限制拆分出的字符串数量
	Iterable<String> strsIt = Splitter.on(',').trimResults()
			.omitEmptyStrings().split(",a,,b,");//[a, b]
	Iterator<String> it = strsIt.iterator();
	while(it.hasNext())
		System.out.println(it.next());
}

5.并发[Concurrency]

Guava 定义了 ListenableFuture接口并继承了JDK concurrent包下的Future 接口。
大多数Futures 方法中需要它。转到ListenableFuture 编程比较容易。
Guava提供的通用公共类封装了公共的操作方方法,不需要提供Future和ListenableFuture的扩展方法。
public static void testListenableFuture() throws InterruptedException,
		ExecutionException {

	// ListeningExecutorService 接口, 该接口返回 ListenableFuture
	// 而相应的 ExecutorService 返回普通的 Future。
	// 将 ExecutorService 转为
	// ListeningExecutorService,可以使用MoreExecutors.listeningDecorator(ExecutorService)进行装饰。
	ListeningExecutorService service = MoreExecutors
			.listeningDecorator(Executors.newFixedThreadPool(10));

	ListenableFuture future = service.submit(new Callable() {
		@Override
		public String call() throws Exception {
			// TODO Auto-generated method stub
			return "aaaa";
		}
	});
	service.shutdown();
	System.out.println(future.get());// aaaa

	// ListenableFuture可以注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用,
	// 或者在运算(多线程执行)完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,
	// 在JDKconcurrent中的Future是不支持的。
	// *********************************************************
	// Callback采用轻量级的设计. FutureCallback<V> 中实现了两个方法:
	// onSuccess(V),在Future成功的时候执行,根据Future结果来判断。
	// onFailure(Throwable), 在Future失败的时候执行,根据Future结果来判断。
	Futures.addCallback(future, new FutureCallback() {

		@Override
		// future执行任务成功后,执行onSuccess,result值为future.get()
		public void onSuccess(Object result) {
			System.out.println("onSuccess---" + result);// onSuccess---aaaa
		}

		@Override
		public void onFailure(Throwable t) {
			System.out.println("onFailure---" + t.toString());
		}
	});
	// ListenableFuture 中addListener(Runnable, Executor),
	// 该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行。
}
public static void testService() throws Exception {
	MyService myService = new MyService();

	// myService.startUp();
	// myService.shutDown();
}
class MyService extends AbstractIdleService {

	@Override
	protected void startUp() throws Exception {
		System.out.println("startUp()");

	}

	@Override
	protected void shutDown() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("shutDown()");
	}
}

6.缓存

通常来说,Guava Cache适用于:
1.愿意消耗一些内存空间来提升速度。
2.预料到某些键会被查询一次以上。
3.缓存中存放的数据总量不会超出内存容量。
(GuavaCache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果这不符合需求,请尝试Memcached这类工具)
// LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
// .maximumSize(1000)
// .expireAfterWrite(10, TimeUnit.MINUTES)
// .removalListener(MY_LISTENER)
// .build(
// new CacheLoader<Key, Graph>() {
// public Graph load(Key key) throws AnyException {
// return createExpensiveGraph(key);
//
//
// }
// }});

// CacheLoader
// LoadingCache是附带CacheLoader构建而成的缓存实现。
// 创建自己的CacheLoader通常只需要简单地实现V load(K key) throws Exception方法。
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
		.expireAfterWrite(10, TimeUnit.SECONDS).maximumSize(1000)
		.build(new CacheLoader<String, String>() {
			@Override
			public String load(String key) throws Exception {
				// 实现了模式"如果有缓存则返回;否则运算、缓存、然后返回"。
				return "null";
			}
		});
cache.put("a", "aaaaaa");
try {
	System.out.println(cache.get("a"));// aaaaaa
	System.out.println(cache.get("bb"));// null----key不存在,使用CacheLoader向缓存原子地加载新值
} catch (ExecutionException e) {
	e.printStackTrace();
}

// 也可以在调用get时,指定Callable
Cache<String, String> cache1 = CacheBuilder.newBuilder()
		.maximumSize(1000)// 规定缓存项的数目不超过固定值,逼近限定值时将尝试回收最近没有使用或总体上很少使用的缓存项。
		.build(); // no CacheLoader
try {
	// If the key wasn't in the "easy to compute" group,
	// we need to do things the hard way.
	String aString = cache1.get("a", new Callable<String>() {
		@Override
		public String call() throws Exception {
			// TODO Auto-generated method stub
			return "nullnullnull";
		}
	});
	System.out.println(aString);
} catch (ExecutionException e) {
	e.printStackTrace();
}

不同的缓存项有不同的“权重”(weights)
可以使用CacheBuilder.weigher(Weigher)指定一个权重函数,
并且用CacheBuilder.maximumWeight(long)指定最大总重


定时回收(Timed Eviction)
expireAfterAccess(long, TimeUnit):
-----缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。
 expireAfterWrite(long, TimeUnit):
-----缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。


移除监听器
通过CacheBuilder.removalListener(RemovalListener),
可以声明一个监听器,以便缓存项被移除时做一些额外操作。
缓存项被移除时,RemovalListener会获取移除通知[RemovalNotification],其中包含移除原因[RemovalCause]、键和值。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值