Guava

Guave

使用

引入依赖

maven:

1
2
3
4
5
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>

gradle:

1
compile 'com.google.guava:guava:28.1-jre'

官方文档

集合操作

New Collection

创建不可变集合Immutable(不可变)对象

  • 在多线程操作下,是线程安全的
  • 所有不可变集合会比可变集合更有效的利用资源
  • 中途不可改变
1
ImmutableList<String> immutableList=ImmutableList.of("1","2","3","4");

当需要一个map中包含key为string,value为list类型时,使用guava是这样的:

1
2
3
4
Multimap<String,Integer> map = ArrayListMultimap.create();      
map.put("aa", 1);
map.put("aa", 2);
System.out.println(map.get("aa")); //[1, 2]

集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
MultiSet: 无序+可重复
//创建方式:
Multiset<String> set = HashMultiset.create();
/*
* 当把Multiset看成普通的Collection时,它表现得就像无序的ArrayList:
* add(E) 添加单个给定元素
* iterator() 返回一个迭代器,包含Multiset的所有元素(包括重复的元素)
* size() 返回所有元素的总个数(包括重复的元素)
* 当把Multiset看作Map<E, Integer>时,它也提供了符合性能期望的查询操作
* count(Object) 返回给定元素的计数。HashMultiset.count的复杂度为O(1),TreeMultiset.count的复杂度为O(log n)。
* entrySet() 返回Set<Multiset.Entry<E>>,和Map的entrySet类似。
* elementSet() 返回所有不重复元素的Set<E>,和Map的keySet()类似。
* Multiset.addAll(Collection)可以添加Collection中的所有元素并进行计数
*/

Multimap: key-value key可以重复
//创建方式:
Multimap<String, String> teachers = ArrayListMultimap.create();
/*
* put(K, V) 添加键到单个值的映射 等价于 multimap.get(key).add(value)
* putAll(K, Iterable<V>) 依次添加键到多个值的映射 等价于 Iterables.addAll(multimap.get(key), values)
* remove(K, V) 移除键到值的映射;如果有这样的键值并成功移除,返回true。 等价于 multimap.get(key).remove(value)
* removeAll(K) 清除键对应的所有值,返回的集合包含所有之前映射到K的值,但修改这个集合就不会影响Multimap了。 等价于 multimap.get(key).clear()
* replaceValues(K, Iterable<V>) 清除键对应的所有值,并重新把key关联到Iterable中的每个元素。返回的集合包含所有之前映射到K的值。 等价于 multimap.get(key).clear();Iterables.addAll(multimap.get(key), values);
*/

BiMap: 双向Map(Bidirectional Map) 键与值都不能重复
//创建方式:
BiMap<String, String> biMap = HashBiMap.create();
/*
* BiMap<K, V>是特殊的Map:
* 可以用 inverse()反转BiMap<K, V>的键值映射
* 保证值是唯一的,因此 values()返回Set而不是普通的Collection
* 实现方法:
* 键-值 | 值-键 | 对应BiMap实现
* HashMap | HashMap |HashBiMap
* ImmutableMap | ImmutableMap|ImmutableBiMap
* EnumMap | EnumMap |EnumBiMap
* EnumMap | HashMap |EnumHashBiMap
*/

Table: 双键的Map Map--> Table-->rowKey+columnKey+value
//和sql中的联合主键有点像
//创建方式:
Table<String, String, Integer> tables = HashBasedTable.create();
tables.put("v1", "v2", 4);
tables.put("v1", "v3", 20);
tables.put("v2", "v3", 5);
tables.row(v1); // returns a Map mapping v2 to 4, v3 to 20
tables.column(v3); // returns a Map mapping v1 to 20, v2 to 5
/*
* rowMap():用Map<R, Map<C, V>>表现Table<R, C, V>。同样的, rowKeySet()返回”行”的集合Set<R>。
* row(r) :用Map<C, V>返回给定”行”的所有列,对这个map进行的写操作也将写入Table中。
类似的列访问方法:columnMap()、columnKeySet()、column(c)。(基于列的访问会比基于的行访问稍微低效点)
* cellSet():用元素类型为Table.Cell<R, C, V>的Set表现Table<R, C, V>。Cell类似于Map.Entry,但它是用行和列两个键区分的。
* 实现方式:
* HashBasedTable,TreeBasedTable,ImmutableTable,ArrayTable
*/

集合过滤

Predicate(断言)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//按照条件过滤
ImmutableList<String> names = ImmutableList.of("begin", "code", "Guava", "Java");
/*Predicates.equalTo()来表达需要过滤的元素
* 看一下equalTo方法源码:
* public static <T> Predicate<T> equalTo(@Nullable T target) {
* return (Predicate)(target == null ? isNull() : new Predicates.IsEqualToPredicate(target));}
* 然后用Predicates.or聚合所有条件然后过滤出来。
*/
Iterable<String> fitered = Iterables.filter(names, Predicates.or(Predicates.equalTo("Guava"), Predicates.equalTo("Java")));
System.out.println(fitered); // [Guava, Java]

//自定义过滤条件 使用自定义回调方法对Map的每个Value进行操作
ImmutableMap<String, Integer> m = ImmutableMap.of("begin", 12, "code", 15);
// Function<F, T> F表示apply()方法input的类型,T表示apply()方法返回类型
Map<String, Integer> m2 = Maps.transformValues(m, new Function<Integer, Integer>() {
public Integer apply(Integer input) {
if(input>12){
return input;
}else{
return input+1;
}
}
});
System.out.println(m2); //{begin=13, code=15}

集合 交、并、差集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*set*/
HashSet setA = newHashSet(1, 2, 3, 4, 5);
HashSet setB = newHashSet(4, 5, 6, 7, 8);
//并集
SetView union = Sets.union(setA, setB);
System.out.println("union:");
for (Integer integer : union)
System.out.println(integer); //union 并集:12345867
//差集
SetView difference = Sets.difference(setA, setB);//difference 差集:123
//交集
SetView intersection = Sets.intersection(setA, setB);//intersection 交集:45

/*map*/
HashMap<String, Integer> mapA = Maps.newHashMap();
mapA.put("a", 1);
mapA.put("b", 2);
mapA.put("c", 3);

HashMap<String, Integer> mapB = Maps.newHashMap();
mapB.put("b", 20);
mapB.put("c", 3);
mapB.put("d", 4);

MapDifference differenceMap = Maps.difference(mapA, mapB);
differenceMap.areEqual();
Map entriesDiffering = differenceMap.entriesDiffering();
Map entriesOnlyLeft = differenceMap.entriesOnlyOnLeft();
Map entriesOnlyRight = differenceMap.entriesOnlyOnRight();
Map entriesInCommon = differenceMap.entriesInCommon();

System.out.println(entriesDiffering); // {b=(2, 20)}
System.out.println(entriesOnlyLeft); // {a=1}
System.out.println(entriesOnlyRight); // {d=4}
System.out.println(entriesInCommon); // {c=3}

集合转化特定字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//list -> String
List<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
String result = Joiner.on("-").join(list);
//result为 aa-bb-cc

//map -> String
Map<String, Integer> map = Maps.newHashMap();
map.put("xiaoming", 12);
map.put("xiaohong",13);
String result = Joiner.on(",").withKeyValueSeparator("=").join(map);
// result为 xiaoming=12,xiaohong=13

字符串转化特定集合

字符串转化list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//java String -> list
List<String> list = new ArrayList<String>();
String a = "1-2-3-4-5-6";
String[] strs = a.split("-");
for(int i=0; i<strs.length; i++){
list.add(strs[i]);
}

//guava String -> list
String str = "1-2-3-4-5-6";
List<String> list = Splitter.on("-").splitToList(str);
//list为 [1, 2, 3, 4, 5, 6]

/*guava还可以使用 omitEmptyStrings().trimResults() 去除空串与空格*/
String str = "1-2-3-4- 5- 6 ";
List<String> list = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(str);
System.out.println(list);

字符串转为map

1
2
3
//string -> map
String str = "xiaoming=11,xiaohong=23";
Map<String,String> map = Splitter.on(",").withKeyValueSeparator("=").split(str);

字符串操作

在Splitter类中实现

1
2
3
4
5
6
7
8
9
10
// 判断匹配结果
boolean result = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).matches('K'); //true

// 保留数字文本 CharMatcher.digit() 已过时 retain 保留
//String s1 = CharMatcher.digit().retainFrom("abc 123 efg"); //123
String s1 = CharMatcher.inRange('0', '9').retainFrom("abc 123 efg"); // 123

// 删除数字文本 remove 删除
// String s2 = CharMatcher.digit().removeFrom("abc 123 efg"); //abc efg
String s2 = CharMatcher.inRange('0', '9').removeFrom("abc 123 efg"); // abc efg

检查参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/use java
if(list!=null && list.size()>0)
'''
if(str!=null && str.length()>0)
'''
if(str !=null && !str.isEmpty())

//use guava
if(!Strings.isNullOrEmpty(str))

//use java
if (count <= 0) {
throw new IllegalArgumentException("must be positive: " + count);
}

//use guava
Preconditions.checkArgument(count > 0, "must be positive: %s", count);
方法声明(不包括额外参数) 描述 检查失败时抛出的异常
checkArgument(boolean) 检查boolean是否为true,用来检查传递给方法的参数。 IllegalArgumentException
checkNotNull(T) 检查value是否为null,该方法直接返回value,因此可以内嵌使用checkNotNull。 NullPointerException
checkState(boolean) 用来检查对象的某些状态。 IllegalStateException
checkElementIndex(int index, int size) 检查index作为索引值对某个列表、字符串或数组是否有效。 index > 0 && index < size IndexOutOfBoundsException
checkPositionIndexes(int start, int end, int size) 检查[start,end]表示的位置范围对某个列表、字符串或数组是否有效 IndexOutOfBoundsException

然后看一下checkNotNull(T) 方法的源码:

1
2
3
4
5
6
7
@CanIgnoreReturnValue
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
}

就是封装了一下判空和抛出异常。

Ordering排序器

排序器[Ordering]是Guava流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。

1
2
3
4
5
6
7
8
9
natural()   对可排序类型做自然排序,如数字按大小,日期按先后排序
usingToString() 按对象的字符串形式做字典排序[lexicographical ordering]
from(Comparator) 把给定的Comparator转化为排序器
reverse() 获取语义相反的排序器
nullsFirst() 使用当前排序器,但额外把null值排到最前面。
nullsLast() 使用当前排序器,但额外把null值排到最后面。
compound(Comparator) 合成另一个比较器,以处理当前排序器中的相等情况。
lexicographical() 基于处理类型T的排序器,返回该类型的可迭代对象Iterable<T>的排序器。
onResultOf(Function) 对集合中元素调用Function,再按返回值用当前排序器排序。123456789

示例

1
2
3
4
5
6
7
8
9
Person person = new Person("aa",14);  //String name  ,Integer age
Person ps = new Person("bb",13);
Ordering<Person> byOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Person,String>(){
public String apply(Person person){
return person.age.toString();
}
});
byOrdering.compare(person, ps);
System.out.println(byOrdering.compare(person, ps)); //1 person的年龄比ps大 所以输出1

计算中间代码的运行时间

1
2
3
4
5
6
Stopwatch stopwatch = Stopwatch.createStarted();
for(int i=0; i<100000; i++){
// do some thing
}
long nanos = stopwatch.elapsed(TimeUnit.MILLISECONDS);
System.out.println(nanos);

TimeUnit 可以指定时间输出精确到多少时间

文件操作

1
2
3
4
5
6
7
8
9
10
11
12
File file = new File("test.txt");
List<String> list = null;
try {
list = Files.readLines(file, Charsets.UTF_8);
} catch (Exception e) {
}

Files.copy(from,to); //复制文件
Files.deleteDirectoryContents(File directory); //删除文件夹下的内容(包括文件与子文件夹)
Files.deleteRecursively(File file); //删除文件或者文件夹
Files.move(File from, File to); //移动文件
URL url = Resources.getResource("abc.xml"); //获取classpath根下的abc.xml文件url

guava缓存

guava的缓存设计的比较巧妙,可以很精巧的使用。guava缓存创建分为两种,一种是CacheLoader,另一种则是callback方式

CacheLoader:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LoadingCache<String,String> cahceBuilder=CacheBuilder
.newBuilder()
.build(new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
String strProValue="hello "+key+"!";
return strProValue;
}
});
System.out.println(cahceBuilder.get("begincode")); //hello begincode!
System.out.println(cahceBuilder.get("wen")); //hello wen!
System.out.println(cahceBuilder.get("da"));//hello da!
cahceBuilder.put("begin", "code");
System.out.println(cahceBuilder.get("begin")); //code

callback方式:

1
2
3
4
5
6
7
8
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();  
String resultVal = cache.get("code", new Callable<String>() {
public String call() {
String strProValue="begin "+"code"+"!";
return strProValue;
}
});
System.out.println("value : " + resultVal); //value : begin code!
0%