- Spring Boot 学习笔记 源码地址
- Spring Boot 学习笔记(一) hello world
- Spring Boot 学习笔记(二) 整合 log4j2
- Spring Boot 学习笔记(三) 整合 MyBatis + Druid
- Spring Boot 学习笔记(四) 整合 Druid 监控
- Spring Boot 学习笔记(五) 整合 静态资源
- Spring Boot 学习笔记(六) 整合 RESTful 参数传递
- Spring Boot 学习笔记(七) 整合 Swagger2
- Spring Boot 学习笔记(八) 整合 Filter
- Spring Boot 学习笔记(九) 整合 多环境配置
- Spring Boot 学习笔记(十) Redis集群搭建
- Spring Boot 学习笔记(十一) 整合 Redis
- Spring Boot 学习笔记(十二) 整合 定时任务
- Spring Boot 学习笔记(十三) 整合 AOP
- Spring Boot 学习笔记(十四) 整合 Guava
0. Guava
Guava 工程包含了若干被Google的 Java项目广泛依赖的核心库。或者说是 Google 工程师的瑞士军刀。Guava 里包含了集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 所有这些工具每天都在被Google的工程师应用在产品服务中。
想要使用 Guava 首先需要添加依赖。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency
1. Optional
Guava 用 Optional表示可能为 null 的 T 类型引用。一个 Optional 实例可能包含非 null 的引用(我们称之为引用存在),也可能什么也不包括(称之为引用缺失)。它从不说包含的是 null 值,而是用存在或缺失来表示。但 Optional 从不会包含 null 值引用。
1.1 简单使用
当某个方法有可能返回 null 值时候,我们可以返回一个 Optional 的泛型对象。代码如下:
/**
* 使用 empty 代替 null
*
* @param num
* @return
*/
private Optional<Integer> getNum(int num) {
if (num > 0) {
return Optional.of(num);
} else {
//使用 empty 代替 null
return Optional.empty();
}
}
public void testGetNum() {
Optional<Integer> num = this.getNum(5);
if (num.isPresent()) {
System.out.println(num.get());
}
//也可以使用 ifPresent 方法
num.ifPresent(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
}
使用 Optional.of()
来创建一个可用对象,使用 Optional.empty();
来创建一个不可引用的对象。用来替代之前直接返回 null 的情况。
使用 Optional 时,可以通过Optional.isPresent()
方法,或者是Optional.ifPresent()
方法来使用。
1.2 使用 filter 方法
可以使用 filter 方法 对返回结果做二次判断。
- 使用
Predicates.in()
方法,判断返回结果是否在集合内。
public static void testIn(){
List<AccountInfo> data = new ArrayList<>();
AccountInfo accountInfo = new AccountInfo();
accountInfo.setName("aaa");
accountInfo.setBalance(123);
data.add(accountInfo);
AccountInfo accountInfo2 = new AccountInfo();
accountInfo2.setName("aaa");
accountInfo2.setBalance(123);
System.out.println("equals:"+accountInfo.equals(accountInfo2));
Optional<AccountInfo> optional = Optional.of(accountInfo2);
//通过 调用对象的 equals 方法来判断是否存在
optional.filter(Predicates.in(data)).ifPresent(new Consumer<AccountInfo>() {
@Override
public void accept(AccountInfo accountInfo) {
System.out.println("1:"+accountInfo.21 [native code]
}">toString());
}
});
in 方法调用的是对象的 equals 方法,所以如果对象的 equals 方法返回 true,那么就会访问到该对象,否则就访问不到。
Predicates 类还有一些其他方法,用于过滤 Optional 对象。可以参考 Predicates 的API。
2. Preconditions
Guava 在 Preconditions 类中提供了若干前置条件判断的实用方法。这些方法让调用的前置条件判断更简单。
/**
* 检查参数是否为 true
* @param attr
*/
private static void testAttrs(boolean attr){
Preconditions.checkArgument(attr,"参数错误");
}
/**
* 检查参数是否为 null
* @param accountInfo
*/
private static void testAttr2(AccountInfo accountInfo) {
Preconditions.checkNotNull(accountInfo, "参数不能为 null");
}
/**
* 检查索引是否越界
* @param index
* @param size
*/
private static void testAttr3(int index, int size) {
Preconditions.checkElementIndex(index, size);
}
/**
* 检查区间是否越界
* @param start
* @param end
* @param size
*/
private static void testAttr4(int start,int end, int size) {
Preconditions.checkPositionIndexes(start,end, size);
}
public static void main(String[] args) {
//testAttrs(Boolean.FALSE);
//testAttr2(null);
//testAttr3(3, 2);
testAttr4(2, 4, 3);
Guava 建议直接静态导入,就不用 Preconditions.checkArgument(), 来调用了,直接使用 checkArgument(),比较简洁。
3. Ordering
排序器[Ordering]是 Guava 流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集
合排序的功能。
Guava 提供了 3 中常见的比较器。
- Ordering.natural()
默认比较器,针对可比较对象。
- Ordering.usingToString()
使用字符串的字典顺序排序。
- Ordering.arbitrary()
插入顺序的倒序。
还可以根据 Comparator 生成 Ordering.from(Comparator)
。
或者自定义比较器:
private static void lengthOrdering(List<String> list) {
Ordering<String> lengthOrdering = new Ordering<String>() {
@Override
public int compare(@Nullable String left, @Nullable String right) {
return left.length() - right.length();
}
};
list.sort(lengthOrdering);
//倒序
list.sort(lengthOrdering.reverse());
如果要根据对象的某个具体的属性排序,可以使用 onResultOf 方法。
private static void lengthOrdering2(List<AccountInfo> list) {
Ordering<AccountInfo> lengthOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<AccountInfo, Integer>() {
@Nullable
@Override
public Integer apply(@Nullable AccountInfo accountInfo) {
return accountInfo.getBalance();
}
});
list.sort(lengthOrdering);
//倒序
list.sort(lengthOrdering.reverse());
注意:这里跟平常的链式调用的不同是,执行顺序是从后往前执行!!!比如上面的例子。
Ordering.natural().nullsFirst().onResultOf()
首先执行 onResultOf 获取所有对象的 balance 值,然后将 null 值排在最前,然后再按照数字顺序排序。
Ordering 还提供了一些集合遍历、迭代的方法。比如:
- greatestOf(Iterableiterable, int k)
获取最大的 k 个元素
- min(Iterable)
获取最小的一个元素
- isOrdered(Iterable)
判断对象是否按照给定的排序器排序
4. Collections
4.1 不可变集合
创建对象的不可变拷贝是一项很好的防御性编程技巧。Guava 为所有 JDK 标准集合类型和 Guava 新集合类型都提供了简单易用的不可变版本。
使用方式:
public static void testImmutable(){
ImmutableSet<String> immutableSet = ImmutableSet.<String>builder().add("c")
.add("b").build();
for (String s : immutableSet) {
System.out.print(s + ",");
}
Guava 还提供了有序的不可变集合。
private static void testSort(){
ImmutableSortedSet<String> immutableSortedSet = ImmutableSortedSet.of("c", "a", "b");
for (String s:immutableSortedSet) {
System.out.print(s + ",");
}
4.2 新集合类型
- Multiset
Guava 提供了一个新集合类型 Multiset ,它可以多次添加相等的元素。你可以将 Multiset 类比成 Map<E, Integer>,键为元素,值为计数的一个 Map 集合。添加相同元素会增加计数,删除元素会减少计数。
private static void testMultiset(){
Multiset<String> multiset = HashMultiset.create();
multiset.add("a");
multiset.add("a");
multiset.add("b");
multiset.add("c");
multiset.setCount("b", 3);
System.out.println(multiset.contains("a"));
System.out.println(multiset.count("a"));
System.out.println(multiset.remove("b"));
System.out.println(multiset.count("b"));
System.out.println(multiset.size());
当然,Guava 还提供了 TreeMultiset、LinkedHashMultiset、ConcurrentHashMultiset、ImmutableMultiset
的实现,需要注意的是,这些类都提供了 create 方法,所以尽量不要使用 new 来创建对象。更贴心的是,Guava 还提供了一个 SortedMultiset ,默认排序。
private static void testSortMultiset(){
SortedMultiset<Integer> multiset = TreeMultiset.create();
multiset.addAll(Lists.newArrayList(3, 2, 5, 6, 9, 2, 5, 6, 8));
for (int num:multiset) {
System.out.print(num + ",");
}
- Multimap
Guava 的 Multimap 可以很容易地把一个键映射到多个值。换句话说,Multimap 是把键映射到任意多个值的一般方式。你可以将 Multimap 类比成 Map<K, List> 或 Map<K, Set>。
private static void testMultimap(){
Multimap<String, Integer> multimap = ArrayListMultimap.create();
multimap.put("a", 1);
multimap.put("a", 2);
multimap.put("a", 3);
multimap.put("a", 4);
System.out.println(multimap.containsKey("a"));
System.out.println(multimap.containsEntry("a", 1));
System.out.println(multimap.containsEntry("a", 0));
System.out.println(multimap.remove("a", 3));
System.out.println(Arrays.deepToString(multimap.get("a").toArray()));
Multimap 还提供了若干个视图
- multimap.asMap()
返回一个 Map<K,Collection>形式的视图。
- multimap.entries()
返回一个 Collection<Map.Entry<K, V>> 包含所有的键值对。
- multimap.keySet()
返回一个 Set 集合,包含所有不重复的键
- multimap.keys()
返回一个 Multiset 包含所有的 key。
- multimap.values()
返回一个 Collection 包含所有的 value
Multimap 的具体实现类包括 ArrayListMultimap、HashMultimap、TreeMultimap、ImmutableListMultimap 等。
- BiMap
BiMap 是一个特殊的 Map ,可以用 inverse()反转 BiMap<K, V>的键值映射。所以,在插入值时需要注意,保证值时唯一的。强制将某个值插入到 BiMap 中,会更新该值对应的 key。
private static void testBiMap(){
BiMap<String, Integer> biMap = HashBiMap.create();
biMap.put("a", 1);
biMap.put("b", 2);
System.out.println(biMap.inverse().get(2));
biMap.forcePut("c", 2);
System.out.println(biMap.inverse().get(2));
BiMap 的常见实现类 HashBiMap、ImmutableBiMap、EnumBiMap、EnumHashBiMap。
- other
还有一些不常用到的集合类,比如
- Table: 集合,可以根据行和列来存储和检索具体的值。
- ClassToInstanceMap: 是一个类型 Map,它的键是类型,而值是符合键所指类型的对象。
- RangeSet: 描述了一组不相连的区间。当把一个区间添加到可变的RangeSet时,所有相连的区间会被合并
- RangeMap: 将一个区间映射到一个对应的 value 上
5. collection utilities
Guava 提供了大量的集合工具。包括 Lists、Maps、Sets 等等。
5.1 静态工厂方法。
Guava 提供了能够推断范型的静态工厂方法。
private static void testUtil1(){
List<AccountInfo> accountInfoList = Lists.newArrayList();
List<AccountInfo> accountInfoList2 = Lists.newArrayListWithCapacity(3);
List<AccountInfo> accountInfoList3 = Lists.newArrayListWithExpectedSize(3);
List<AccountInfo> accountInfoList4 = Lists.newArrayList(new AccountInfo());
5.2 Iterables
Iterables 提供了一些集合操作的方法。
private static void testUtil1(){
List<AccountInfo> accountInfoList = Lists.newArrayList();
List<AccountInfo> accountInfoList2 = Lists.newArrayListWithCapacity(3);
List<AccountInfo> accountInfoList3 = Lists.newArrayListWithExpectedSize(3);
List<AccountInfo> accountInfoList4 = Lists.newArrayList(new AccountInfo());
Iterable<Integer> concatenated = Iterables.concat(Ints.asList(1, 2, 3),
Ints.asList(3, 4, 5));
System.out.println(Iterables.frequency(concatenated, 3));
System.out.println(Iterables.getFirst(concatenated, 0));
- concat(Iterable )
串联多个 iterables 的懒视图
- frequency(Iterable, Object)
返回对象在 iterable 中出现的次数
- partition(Iterable, int)
把 iterable 按指定大小分割,得到的子集都不能进行修改操作
- getFirst(Iterable, T default)
返回 iterable 的第一个元素,若 iterable 为空则返回默认值
- getLast(Iterable)
返回 iterable 的最后一个元素,若 iterable 为空则抛出NoSuchElementException
- elementsEqual(Iterable, Iterable)
如果两个 iterable 中的所有元素相等且顺序一致,返回 true
- unmodifiableIterable(Iterable)
返回 iterable 的不可变视图
- limit(Iterable, int)
限制 iterable 的元素个数限制给定值
- getOnlyElement(Iterable)
获取 iterable 中唯一的元素,如果 iterable 为空或有多个元素,则快速失败
5.2 Sets
Guava 提供了很多标准的集合运算的方法。比如集合间的交集、并集、补集等
- Sets.union()
返回两个集合的并集,并去除重复元素
- Sets.intersection()
返回两个集合的交集
- Sets.difference(set1,set2)
返回 set1 中,不存在在 set2 中的元素,或者说是 set2 在 set1 中的绝对补集
private static void testSets() {
Set<Integer> set = Sets.union(Sets.newHashSet(1, 2, 3), Sets.newHashSet(3, 4, 5));
System.out.println(Arrays.deepToString(set.toArray()));
Set<Integer> set2 = Sets.intersection(Sets.newHashSet(1, 2, 3), Sets.newHashSet(3, 4, 5));
System.out.println(Arrays.deepToString(set2.toArray()));
Set<Integer> set3 = Sets.difference(Sets.newHashSet(1, 2, 3), Sets.newHashSet(1,2));
System.out.println(Arrays.deepToString(set3.toArray()));
5.3 Maps
Maps 里有两个比较有意思的方法。
- Maps.filterKeys() / Maps.filterEntries
根据给定的规则过滤键值对
- Maps.difference
用来比较两个 Map 以获取所有不同点。
- Maps.uniqueIndex
这个方法可以将一个 Iterable 对象 转成 Map 集合。
PS: 有点没看懂这个方法,有了解的朋友可以留言
private static void testMaps() {
Map<String, Integer> hashMap = Maps.newHashMap();
hashMap.put("a", 1);
hashMap.put("bb", 2);
hashMap.put("ccc", 3);
Map<String, Integer> hashMap1 = Maps.filterKeys(hashMap, new Predicate<String>() {
@Override
public boolean apply(@Nullable String input) {
return input.length() > 2;
}
});
System.out.println(Arrays.deepToString(hashMap1.entrySet().toArray()));
Map<String, Integer> hashMap2 = Maps.filterEntries(hashMap, new Predicate<Map.Entry<String, Integer>>() {
@Override
public boolean apply(Map.@Nullable Entry<String, Integer> input) {
return input.getValue() > 2;
}
});
System.out.println(Arrays.deepToString(hashMap2.entrySet().toArray()));
Map<Integer, String> hashMap3 = Maps.uniqueIndex(Lists.newArrayList("sss", "ss", "ssss"),
new Function<String, Integer>() {
@Nullable
@Override
public Integer apply(@Nullable String input) {
return input.length();
}
});
System.out.println(Arrays.deepToString(hashMap3.entrySet().toArray()));
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Map<String, Integer> right = ImmutableMap.of("a", 1, "b", 2, "c", 3);
MapDifference<String, Integer> diff = Maps.difference(left, right);
diff.entriesInCommon(); // {"b" => 2}
diff.entriesInCommon(); // {"b" => 2}
diff.entriesOnlyOnLeft(); // {"a" => 1}
diff.entriesOnlyOnRight(); // {"d" => 5}MapDifference
5.3 Forwarding
针对所有类型的集合接口,Guava 都提供了 Forwarding 抽象类以简化装饰者模式的使用
private static void testForwarding(){
ForwardingList<String> forwardingList = new ForwardingList<String>() {
final List<String> delegate = new ArrayList<>(); // backing list
@Override
protected List<String> delegate() {
return delegate;
}
@Override
public void add(int index, String element) {
System.out.println("add:" + element);
super.add(index, element);
}
@Override
public String get(int index) {
System.out.println("get:" + index);
return super.get(index);
}
};
forwardingList.add(0,"aaa");
System.out.println(forwardingList.get(0));
类似于我们对 List 做了一层装饰(或者说说封装),在执行 List 的相关方法时,可以做一些其他的处理。
当然也可以通过一个类,来实现 Forwarding 的相关接口,比如:
class AddLoggingList<E> extends ForwardingList<E> {
final List<E> delegate; // backing list
@Override protected List<E> delegate() {
return delegate;
}
@Override public void add(int index, E elem) {
log(index, elem);
super.add(index, elem);
}
@Override public boolean add(E elem) {
return standardAdd(elem); // 用add(int, E)实现
}
@Override public boolean addAll(Collection<? extends E> c) {
return standardAddAll(c); // 用add实现
}
上面的 AddLoggingList 在使用时与普通的 ArrayList 并没有什么区别,唯一的区别是,使用 AddLoggingList 时,添加元素会打印出相应的 log。
6. Caches
通常来说,Guava Cache 适用于:
- 你愿意消耗一些内存空间来提升速度。
- 你预料到某些键会被查询一次以上。
- 缓存中存放的数据总量不会超出内存容量。
如果你的场景符合上述的每一条,Guava Cache 就适合你。
6.1 LoadingCache
private static LoadingCache<String, AccountInfo> loadingCache = CacheBuilder.newBuilder()
//最大缓存数量
.maximumSize(10).build(new CacheLoader<String, AccountInfo>() {
@Override
public AccountInfo load(String key) throws Exception {
System.out.println("load 方法执行:" + key);
AccountInfo accountInfo = new AccountInfo();
accountInfo.setName(key);
return accountInfo;
}
});
private static void testCaches() throws ExecutionException {
//如果缓存中没有该值,就会添加新值
loadingCache.get("aaa").setBalance(123);
System.out.println(loadingCache.get("aaa"));
可以通过 Builder 来创建一个缓存对象(或者叫本地缓存池)。可以设定缓存对象的一些基本参数,比如最大数量等。
load 方法用来加载需要缓存的对象。这些对象可以是手动创建的,也可以是从DB、Redis等其他外部存储加载进来的。
可以直接使用 get() 方法获取 LoadingCache 中的对象。注意:这里如果在缓存中没有找到对应的值,通过 load 方法创建一个新的值添加到缓存中,并返回该值。
如果我们不希望 使用默认的 load 方法创建对象。也可以在使用 get 方法时传入一个 Call 对象,用来创建需要缓存的值。
private static void testCaches() throws ExecutionException {
//如果缓存中没有该值,就会添加新值
loadingCache.get("aaa").setBalance(123);
System.out.println(loadingCache.get("aaa"));
//如果没有值,就会执行 call 方法,创建对应的值,并返回
AccountInfo accountInfo = loadingCache.get("bbb", new Callable<AccountInfo>() {
@Override
public AccountInfo call() throws Exception {
AccountInfo accountInfo = new AccountInfo();
accountInfo.setName("bbb");
accountInfo.setPwd("call-add");
return accountInfo;
}
});
System.out.println(accountInfo.16 [native code]
}">toString());
如果你执行了上面的代码,就会发现,获取 “aaa” 时,调用了 load 方法,而获取 “bbb” 时,则没有执行 load 方法。
也可以直接向缓存中插入值。
loadingCache.put("ccc",accountInfo);
System.out.println(loadingCache.get("ccc"))
不过,尽量优先使用 Cache.get(K, Callable) 方法
6.2 Eviction
Guava Cache 提供了三种基本的缓存回收方式:基于容量回收、定时回收和基于引用回收。
- 基于容量回收
我们可以指定缓存的容量,通过 maximumSize() 方法,当超过容量时,缓存将尝试回收最近没有使用或总体上很少使用的缓存项
private static LoadingCache<String, AccountInfo> loadingCache = CacheBuilder.newBuilder()
//最大缓存数量
.maximumSize(10).build(new CacheLoader<String, AccountInfo>() {
@Override
public AccountInfo load(String key) throws Exception {
System.out.println("load 方法执行:" + key);
AccountInfo accountInfo = new AccountInfo();
accountInfo.setName(key);
return accountInfo;
}
})
另外,Guava 缓存还提供了一种根据“权重(weights)” 来删除缓存的方式。你可以使用 CacheBuilder.weigher(Weigher)指定一个权重函数,并且用 CacheBuilder.maximumWeight(long)指定最大总重。
注意:maximumWeight() 方法与 maximumSize() 方法不能同时使用
private static void testEviction() throws ExecutionException {
LoadingCache<String, AccountInfo> cache = CacheBuilder.newBuilder()
//最大缓存数量
//.maximumSize(10)
//最大权重
.maximumWeight(10L)
.weigher(new Weigher<String, AccountInfo>() {
@Override
public int weigh(String key, AccountInfo value) {
return value.getBalance();
}
})
.build(new CacheLoader<String, AccountInfo>() {
@Override
public AccountInfo load(String key) throws Exception {
AccountInfo accountInfo = new AccountInfo();
accountInfo.setName(key);
return accountInfo;
}
});
for (int i = 0; i < 12; i++) {
AccountInfo accountInfo = new AccountInfo();
accountInfo.setName("aaa" + i);
accountInfo.setBalance(i);
cache.put(accountInfo.getName(), accountInfo);
}
System.out.println(cache.asMap().size());
System.out.println(Arrays.deepToString(cache.asMap().entrySet().toArray()));
- 定时回收
CacheBuilder 提供两种定时回收的方法:
- expireAfterAccess(long, TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。
- expireAfterWrite(long, TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。
- 基于引用的回收
通过使用弱引用的键、或弱引用的值、或软引用的值,Guava Cache 可以把缓存设置为允许垃圾回收:
- CacheBuilder.weakKeys():使用弱引用存储键。当键没有其它(强或软)引用时,缓存项可以被垃圾回收。因为垃圾回收仅依赖恒等式(==),使用弱引用键的缓存用==而不是 equals 比较键。
- CacheBuilder.weakValues():使用弱引用存储值。当值没有其它(强或软)引用时,缓存项可以被垃圾回收。因为垃圾回收仅依赖恒等式(==),使用弱引用值的缓存用==而不是 equals 比较值。
- CacheBuilder.softValues():使用软引用存储值。软引用只有在响应内存需要时,才按照全局最近最少使用的顺序回收。考虑到使用软引用的性能影响,我们通常建议使用更有性能预测性的缓存大小限定(见上文,基于容量回收)。使用软引用值的缓存同样用==而不是 equals 比较值。
显
- 显式清除
任何时候,你都可以显式地清除缓存项,而不是等到它被回收:
- 个别清除:Cache.invalidate(key)
- 批量清除:Cache.invalidateAll(keys)
- 清除所有缓存项:Cache.invalidateAll()
注意:这里的清除缓存并不一定会删除元素,准确的说法是将缓存置为无效。如果你调用 Cache.asMap 方法,你会发现,里面的元素并没有少。但是当调用 invalidate() 方法之后,再次调用 get() 方法,会重新执行 load 方法,说明原来的数据已经是无效的了
7. Strings
7.1 Joiner
用分隔符把字符串序列连接起来也可能会遇上不必要的麻烦。如果字符串序列中含有 null,那连接操作会更难。Fluent 风格的 Joiner 让连接字符串更简单。
private static void testJoiner(){
//使用 '-' 链接,遇到 null 值用 '#' 代替
Joiner joiner = Joiner.on("-").useForNull("#");
System.out.println(joiner.join("aaa","bbb",null,"","ccc"));
//忽略空值
joiner = Joiner.on("-").skipNulls();
//将拼接好的 String append 到 StringBuilder 之后
StringBuilder sb = Joiner.on("-").appendTo(new StringBuilder("sss"), "aaa","bbb");
System.out.println(sb.10 [native code]
}">toString());
7.2 Splitter
非常友好的 String 拆分器。
private static void testSplitter(){
//使用 ; 分隔,并且忽略结果集中的空字符串,移除结果中的开头和结尾的空白字符
Splitter splitter = Splitter.on(';').omitEmptyStrings().trimResults();
Iterable<String> arr = splitter.split("a;aa ; a ;;;");
for (String str : arr) {
System.out.print(str+",");
}
System.out.println();
//按照固定长度拆分
arr = Splitter.fixedLength(3).split("aaabbbcccdd");
for (String str : arr) {
System.out.print(str+",");
}
System.out.println();
7.3 CharMatcher
CharMatcher 实例代表着某一类字符,如数字或空白字符。使用 CharMatcher 的好处更在于它提供了一系列方法,让你对字符作特定类型的操作:修剪[trim]、折叠[collapse]、移除[remove]、保留[retain]等等。
private static void testCharMatcher(){
//去掉控制字符(回车、换行、tab等)
String noControl = CharMatcher.javaIsoControl().removeFrom("aa\tbb\ncc\\d\\.");
System.out.println(noControl);
String theDigits = CharMatcher.inRange('0', '9').retainFrom("1a2b3c4d");
System.out.println(theDigits);
//去除两端的空格,并把中间的连续空格替换成 '-'
String spaced = CharMatcher.whitespace().trimAndCollapseFrom("aaaa bbb cc ", '-');
System.out.println(spaced);
//用*号替换所有数字
String noDigits = CharMatcher.inRange('0', '9').replaceFrom("1a2b3c4d", "*");
System.out.println(noDigits);
String lowerAndDigit = CharMatcher.inRange('0', '9').or(CharMatcher.javaLowerCase()).retainFrom("1Aa2Bb3Cc");
System.out.println(lowerAndDigit);
8. 参考
转载请注明出处
本文链接:zdran.com/20190909.ht…