Guava工程包含了若干被Google的Java项目广泛依赖的核心库,例如:集合、缓存、原生类型支持、并发库、通用注解、字符串处理、I/O等等
/**
* 判断参数是否为空,并给出异常信息
*/
@Test
public void testCheckNotNull() {
Integer paramFlag = null;
try {
Preconditions.checkNotNull(null, "this param [%s] must be not null.", "paramFlag");
} catch (Exception e) {
assertThat(e, is(instanceOf(NullPointerException.class)));
assertThat(e.getMessage(), equalTo("this param [paramFlag] must be not null."));
}
}
/**
* 参数校验
*/
@Test
public void testCheckArguments() {
boolean flag = false;
try {
Preconditions.checkArgument(flag == true, "flag must be not true.");
} catch (Exception e) {
assertThat(e, is(instanceOf(IllegalArgumentException.class)));
assertThat(e.getMessage(), equalTo("flag must be not true."));
}
}
/**
* 状态校验
*/
@Test
public void testCheckState() {
String flag = "fail";
try {
Preconditions.checkState("success".equals(flag), "flag state is %s, not success.", flag);
} catch (Exception e) {
assertThat(e, is(instanceOf(IllegalStateException.class)));
assertThat(e.getMessage(), equalTo("flag state is fail, not success."));
}
}
/**
* 越界检测
*/
@Test
public void testCheckIndex() {
try {
List<String> list = ImmutableList.of();
Preconditions.checkElementIndex(3, list.size());
} catch (Exception e) {
assertThat(e, is(instanceOf(IndexOutOfBoundsException.class)));
}
}
/**
* JDK的Objects也可做null检测
*/
@Test(expected = NullPointerException.class)
public void testByObjects() {
Objects.requireNonNull(null);
}
/**
* 得到程序执行的耗时,自动根据耗时设置单位
*/
@Test
public void testStopWatch() throws InterruptedException {
Stopwatch stopwatch = Stopwatch.createStarted();
TimeUnit.NANOSECONDS.sleep(500L);
log.info("The process successful and elapsed [{}]", stopwatch.stop().elapsed());
}
/**
* 得到程序执行的耗时,根据指定的单位获得
*/
@Test
public void testStopWatchWithUtil() throws InterruptedException {
Stopwatch stopwatch = Stopwatch.createStarted();
TimeUnit.NANOSECONDS.sleep(500L);
log.info("The process successful and elapsed [{}]", stopwatch.stop().elapsed(TimeUnit.SECONDS));
}
@Test
public void testBase64Encode() {
String encodeResult = BaseEncoding.base64().encode("Hello".getBytes());
assertThat(encodeResult, equalTo("SGVsbG8="));
}
@Test
public void testBase64Decode() {
byte[] decodeResult = BaseEncoding.base64().decode("SGVsbG8=");
assertThat(new String(decodeResult), equalTo("Hello"));
}
@Test
public void testCloser() throws IOException {
String TARGET_FILE = "F:\\IDEAWorkerspace\\练习\\guava-lean\\target.txt";
String content = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n"
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n"
+ "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
Closer closer = Closer.create();
try {
File file = new File(TARGET_FILE);
FileOutputStream outputStream = new FileOutputStream(file);
// 注册入closer
closer.register(outputStream);
} catch (IOException e) {
// 重新包装异常进行抛出,目的是如果finally抛出异常,try里面的异常将被替换掉
throw closer.rethrow(e);
} finally {
// 执行关闭close
closer.close();
}
}
public class RateLimiterTest {
// 从速率限流,令牌产生速率是每秒两个许可
private final static RateLimiter limiter = RateLimiter.create(2);
// 同时只能工作线程数,来自JDK5,限制同时处理的线程个数来限流
private final static Semaphore semaphore = new Semaphore(3);
@Test
public void testLimiter() {
while (true) {
// 每次消耗4个令牌,即当前为2秒执行一次
System.out.println(currentThread() + " waiting " + limiter.acquire(4));
}
}
@Test
public void testSemaphore() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
service.submit(() -> {
while (true) {
try {
semaphore.acquire();
System.out.println(currentThread().getName() + " is doing work...");
TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
System.out.println(currentThread().getName() + " release the semaphore");
}
}
});
}
TimeUnit.SECONDS.sleep(100);
}
}
把其它集合的数据处理,拼接成为字符串
public class JoinerTest {
private final List<String> stringList = Arrays.asList("Google", "Guava", "Java", "Scala", "Kafka");
private final List<String> stringListWithNull = Arrays.asList("Google", "Guava", "Java", "Scala", null);
/**
* 使用指定符合连接数组或List形成字符串
*/
@Test
public void testJoinerOn() {
String result = Joiner.on("#").join(stringList);
assertThat(result, equalTo("Google#Guava#Java#Scala#Kafka"));
}
/**
* 连接数组或List(包含null)会抛出NullPointerException异常
*/
@Test(expected = NullPointerException.class)
public void testJoinerOnContainsNull() {
Joiner.on("#").join(stringListWithNull);
}
/**
* 连接数组或List(包含null),设置跳过null
*/
@Test
public void testJoinOnContainsNullButSkip() {
String result = Joiner.on("#").skipNulls().join(stringListWithNull);
assertThat(result, equalTo("Google#Guava#Java#Scala"));
}
/**
* 连接数组或List(包含null),使用默认值替换null
*/
@Test
public void testJoinOnContainsNullUseDefaultValue() {
String result = Joiner.on("#").useForNull("DV").join(stringListWithNull);
assertThat(result, equalTo("Google#Guava#Java#Scala#DV"));
}
/**
* 连接数组或List,将结果追加到StringBuilder中
*/
@Test
public void testJoinOnAppendToStringBuilder() {
StringBuilder sb = new StringBuilder("Mysql#");
StringBuilder result = Joiner.on("#").appendTo(sb, stringList);
assertThat(result, sameInstance(sb));
assertThat(result.toString(), equalTo("Mysql#Google#Guava#Java#Scala#Kafka"));
}
/**
* 连接数组或List,将结果追加到Writer中
*/
@Test
public void testJoinOnAppendToWriter() throws IOException {
Writer writer = new FileWriter("F:\\IDEAWorkerspace\\练习\\guava-lean\\writer.txt");
Joiner.on("#").appendTo(writer, stringList);
writer.close();
byte[] bytes = Files.readAllBytes(Paths.get("F:\\IDEAWorkerspace\\练习\\guava-lean\\writer.txt"));
String content = new String(bytes);
assertThat(content, equalTo("Google#Guava#Java#Scala#Kafka"));
File file = new File("F:\\IDEAWorkerspace\\练习\\guava-lean\\writer.txt");
file.deleteOnExit();
}
/**
* 使用java8实现join效果,还可使用filter进行过滤,map实现值处理等
*/
@Test
public void testJoiningStream() {
String result = stringList.stream().map(str -> "*" + str + "*").collect(Collectors.joining("#"));
assertThat(result, equalTo("*Google*#*Guava*#*Java*#*Scala*#*Kafka*"));
}
/**
* 拼接Map数据成为字符串
*/
@Test
public void testJoinOnWithMap() {
Map<String, String> params = ImmutableMap.of("name", "kun", "age", "18");
String result = Joiner.on(",").withKeyValueSeparator("=").join(params);
assertThat(result, equalTo("name=kun,age=18"));
}
}
使用各种方式将字符串拆分为不同的集合
/**
* 使用指字符串拆分字符串为List
*/
@Test
public void testSplitOn() {
List<String> result = Splitter.on("#").splitToList("Java#Mysql#Guava");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("Java"));
assertThat(result.get(1), equalTo("Mysql"));
assertThat(result.get(2), equalTo("Guava"));
}
/**
* 使用指字符串拆分字符串为List,忽略字符串切分出的空值
*/
@Test
public void testSplitOmitEmpty() {
List<String> result = Splitter.on("#").splitToList("Java##");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("Java"));
assertThat(result.get(1), equalTo(""));
assertThat(result.get(2), equalTo(""));
result = Splitter.on("#").omitEmptyStrings().splitToList("Java##");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(1));
assertThat(result.get(0), equalTo("Java"));
}
/**
* 使用指字符串拆分字符串为List,对切分出的List每个元素进行trim操作
*/
@Test
public void testSplitTrimResult() {
List<String> result = Splitter.on("#").trimResults().splitToList(" Java # Mysql # Guava");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("Java"));
assertThat(result.get(1), equalTo("Mysql"));
assertThat(result.get(2), equalTo("Guava"));
}
/**
* 已指定长度拆分字符串为List
*/
@Test
public void testSplitFixLength() {
List<String> result = Splitter.fixedLength(4).splitToList("AAAABBBBCCCC");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("AAAA"));
assertThat(result.get(1), equalTo("BBBB"));
assertThat(result.get(2), equalTo("CCCC"));
}
/**
* 使用指字符串拆分字符串为List,且只切分出指定个数的元素
*/
@Test
public void testSplitLimit() {
List<String> result = Splitter.on("#").limit(2).splitToList("Java#Mysql#Guava");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(2));
assertThat(result.get(0), equalTo("Java"));
assertThat(result.get(1), equalTo("Mysql#Guava"));
}
/**
* 使用正则表达切分字符串
*/
@Test
public void testSplitPattern() {
List<String> result = Splitter.onPattern("\\d+\\.")
.omitEmptyStrings()
.trimResults()
.splitToList("1.Java 2.Mysql 3.Guava");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("Java"));
assertThat(result.get(1), equalTo("Mysql"));
assertThat(result.get(2), equalTo("Guava"));
result = Splitter.on(Pattern.compile("\\d+\\."))
.omitEmptyStrings()
.trimResults()
.splitToList("1.Java 2.Mysql 3.Guava");
assertThat(result, notNullValue());
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("Java"));
assertThat(result.get(1), equalTo("Mysql"));
assertThat(result.get(2), equalTo("Guava"));
}
/**
* 使用指定字符串为字符串切分符,使用指定分隔符为key-value,生成Map
*/
@Test
public void testSplitToMap() {
Map<String, String> result = Splitter.on(",").withKeyValueSeparator("=").split("name=kun,age=18");
assertThat(result, notNullValue());
assertThat(result.get("name"), equalTo("kun"));
assertThat(result.get("age"), equalTo("18"));
}
/**
* 把每组连续的空白字符替换为特定字符
*/
@Test
public void testCharMatcherReplaceWhiteSpace() {
String result = CharMatcher.whitespace().collapseFrom("1 2 3 4", '-');
assertThat(result, equalTo("1-2-3-4"));
}
/**
* 把字符串的匹配字符移除
*/
@Test
public void testCharMatcherAnyOperator() {
String result = CharMatcher.anyOf("a").removeFrom("aHia");
assertThat(result, equalTo("Hi"));
}
/**
* 查看字符串是不是每个字符都在指定范围内
*/
@Test
public void testCharMatcherAny() {
boolean result = CharMatcher.inRange('a', 'z').matchesAllOf("abc");
assertThat(result, equalTo(true));
}
用于字符串的判空,填充,判断相同前后缀等操作
@Test
public void testStringsMethod() {
// 如果字符串是空串"",则转换为null
assertThat(Strings.emptyToNull(""), nullValue());
// 如果字符串是null,则转化为空串""
assertThat(Strings.nullToEmpty(null), equalTo(""));
// 判断字符串是否为""或者null
assertThat(Strings.isNullOrEmpty(""), equalTo(true));
assertThat(Strings.isNullOrEmpty(null), equalTo(true));
// 得到两个字符串的相同前缀
assertThat(Strings.commonPrefix("Hello", "Her"), equalTo("He"));
// 得到两个字符串的相同后缀
assertThat(Strings.commonSuffix("goods", "books"), equalTo("s"));
// 得到字符串重复三次的结果
assertThat(Strings.repeat("Book", 3), equalTo("BookBookBook"));
// 填充
assertThat(Strings.padStart("kun", 5, '*'), equalTo("**kun"));
assertThat(Strings.padEnd("kun", 5, '*'), equalTo("kun**"));
}
/**
* 格式 范例
* LOWER_CAMEL lowerCamel
* LOWER_HYPHEN lower-hyphen
* LOWER_UNDERSCORE lower_underscore
* UPPER_CAMEL UpperCamel
* UPPER_UNDERSCORE UPPER_UNDERSCORE
*/
@Test
public void testCaseFormat() {
String result = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, "lowerCamel");
assertThat(result,equalTo("LOWER_CAMEL"));
}
直接创建了字符集对象,比JDK的Charset.forName更加便捷
/**
* 比JDK的Charset.forName更加便捷
*/
@Test
public void testCharsets() {
Charset charset = Charset.forName("UTF-8");
assertThat(Charsets.UTF_8, equalTo(charset));
}
@Test
public void testFileWrite() throws IOException {
String content = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n"
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n"
+ "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
File file = new File(TARGET_FILE);
file.deleteOnExit();
Files.asCharSink(file, Charsets.UTF_8).write(content);
String actually = Files.asCharSource(file, Charsets.UTF_8).read();
assertThat(actually, equalTo(content));
}
@Test
public void testFileAppend() throws IOException {
String contentFirst = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n";
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n";
String contentSecond = "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
File file = new File(TARGET_FILE);
file.deleteOnExit();
Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND).write(contentFirst);
Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND).write(contentSecond);
String actually = Files.asCharSource(file, Charsets.UTF_8).read();
assertThat(actually, equalTo(contentFirst + contentSecond));
}
@Test
public void testTouchFile() throws IOException {
File file = new File(TARGET_FILE);
file.deleteOnExit();
Files.touch(file);
assertThat(file.exists(), equalTo(true));
}
@Test
public void testCopyFileWithGuava() throws IOException {
String content = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n"
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n"
+ "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
File sourceFile = new File(SOURCE_FILE);
sourceFile.deleteOnExit();
Files.asCharSink(sourceFile, Charsets.UTF_8).write(content);
File targetFile = new File(TARGET_FILE);
targetFile.deleteOnExit();
Files.copy(sourceFile, targetFile);
HashCode sourceHash = Files.asByteSource(sourceFile).hash(Hashing.sha256());
HashCode targetHash = Files.asByteSource(targetFile).hash(Hashing.sha256());
assertThat(targetHash.toString(), equalTo(sourceHash.toString()));
}
@Test
public void testCopyFileWithJDKNio() throws IOException {
String content = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n"
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n"
+ "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
File sourceFile = new File(SOURCE_FILE);
sourceFile.deleteOnExit();
Files.asCharSink(sourceFile, Charsets.UTF_8).write(content);
File targetFile = new File(TARGET_FILE);
targetFile.deleteOnExit();
java.nio.file.Files.copy(Paths.get(SOURCE_FILE), new FileOutputStream(targetFile));
HashCode sourceHash = Files.asByteSource(sourceFile).hash(Hashing.sha256());
HashCode targetHash = Files.asByteSource(targetFile).hash(Hashing.sha256());
assertThat(targetHash.toString(), equalTo(sourceHash.toString()));
}
@Test
public void testMoveFile() throws IOException {
String content = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n"
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n"
+ "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
File sourceFile = new File(SOURCE_FILE);
Files.asCharSink(sourceFile, Charsets.UTF_8).write(content);
File targetFile = new File(TARGET_FILE);
targetFile.deleteOnExit();
Files.move(sourceFile, targetFile);
String actually = Files.asCharSource(targetFile, Charsets.UTF_8).read();
assertThat(actually, equalTo(content));
}
@Test
public void testRead() throws IOException {
String content = "Give me the strength lightly to bear my joys and sorrows." + "\n"
+ "Give me the strength to make my love fruitful in service" + "\n"
+ "Give me the strength never to disown the poor or bend my knees before insolent might." + "\n"
+ "Give me the strength to raise my mind high above daily trifles." + "\n"
+ "And give me the strength to surrender my strength to thy will with love.";
File sourceFile = new File(SOURCE_FILE);
Files.asCharSink(sourceFile, Charsets.UTF_8).write(content);
sourceFile.deleteOnExit();
// 读取所有文件内容
String actuallyAllContent = Files.asCharSource(sourceFile, Charsets.UTF_8).read();
assertThat(actuallyAllContent, equalTo(content));
// 按行读取文件内容
ImmutableList<String> lines = Files.asCharSource(sourceFile, Charsets.UTF_8).readLines();
assertThat(lines, notNullValue());
assertThat(lines.size(), equalTo(5));
}
/**
* 递归获取文件列表(包含文件夹),可将结果使用Lists.newArrayList(breadthFirstFiles).stream()来进行处理
* breadthFirst 横向有限,先读取第一层目录,再读取第二层,广度优先
* depthFirstPreOrder 第一次访问到节点的顺序
* depthFirstPostOrder 先访问到最后一层,然后回退访问节点的顺序
*/
@Test
public void testRecursive() {
File file = new File("F:\\IDEAWorkerspace\\练习\\guava-lean");
Iterable<File> breadthFirstFiles = Files.fileTraverser().breadthFirst(file);
breadthFirstFiles.forEach(System.out::println);
Iterable<File> depthFirstPostOrderFiles = Files.fileTraverser().depthFirstPostOrder(file);
depthFirstPostOrderFiles.forEach(System.out::println);
Iterable<File> depthFirstPreOrderFiles = Files.fileTraverser().depthFirstPreOrder(file);
depthFirstPreOrderFiles.forEach(System.out::println);
}
/**
* 两个集合做笛卡尔积
* cartesian 笛卡尔积
*/
@Test
public void testCartesianProduct() {
// [[A, C], [A, D], [B, C], [B, D]]
List<List<String>> cartesianProduct = Lists.cartesianProduct(
Lists.newArrayList("A", "B"),
Lists.newArrayList("C", "D"));
assertThat(cartesianProduct.size(), equalTo(4));
}
/**
* 处理加工原有的List产生新的List
*/
@Test
public void testTransform() {
ArrayList<String> sourceList = Lists.newArrayList("Scala", "Guava", "Lists");
List<String> result = Lists.transform(sourceList, String::toUpperCase);
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("SCALA"));
assertThat(result.get(1), equalTo("GUAVA"));
assertThat(result.get(2), equalTo("LISTS"));
}
/**
* 将List内元素反转返回新的List
*/
@Test
public void testReverse() {
ArrayList<String> sourceList = Lists.newArrayList("Scala", "Guava", "Lists");
List<String> result = Lists.reverse(sourceList);
assertThat(result.size(), equalTo(3));
assertThat(result.get(0), equalTo("Lists"));
assertThat(result.get(1), equalTo("Guava"));
assertThat(result.get(2), equalTo("Scala"));
}
/**
* 将List内数据进行分区
*/
@Test
public void testPartition(){
// [[Scala, Guava], [Lists]]
ArrayList<String> sourceList = Lists.newArrayList("Scala", "Guava", "Lists");
List<List<String>> result = Lists.partition(sourceList, 2);
}
/**
* 创建Set
*/
@Test
public void testCreate() {
HashSet<String> sourceSet = Sets.newHashSet("A", "B", "C", "A");
assertThat(sourceSet.size(), equalTo(3));
}
/**
* 生成笛卡尔积
*/
@Test
public void testCartesianProduct() {
HashSet<String> sourceSetFirst = Sets.newHashSet("A", "B", "C");
HashSet<String> sourceSetSecond = Sets.newHashSet("A", "D", "E");
// [[A, A], [A, D], [A, E], [B, A], [B, D], [B, E], [C, A], [C, D], [C, E]]
Set<List<String>> result = Sets.cartesianProduct(sourceSetFirst, sourceSetSecond);
System.out.println(result);
}
/**
* 产生所有规定个数的子集
*/
@Test
public void testCombinations() {
HashSet<String> sourceSet = Sets.newHashSet("A", "B", "C");
Set<Set<String>> result = Sets.combinations(sourceSet, 2);
result.forEach(System.out::println);
}
/**
* 取差集
*/
@Test
public void testDiff() {
HashSet<String> sourceSetFirst = Sets.newHashSet("A", "B", "C", "F");
HashSet<String> sourceSetSecond = Sets.newHashSet("A", "D", "E");
Sets.SetView<String> diffView = Sets.difference(sourceSetFirst, sourceSetSecond);
//[B, C, F]
System.out.println(diffView);
}
/**
* 取交集
*/
@Test
public void testIntersection() {
HashSet<String> sourceSetFirst = Sets.newHashSet("A", "B", "C", "F");
HashSet<String> sourceSetSecond = Sets.newHashSet("A", "D", "E");
Sets.SetView<String> interView = Sets.intersection(sourceSetFirst, sourceSetSecond);
//[A]
System.out.println(interView);
}
/**
* 取并集
*/
@Test
public void testUnionSection() {
HashSet<String> sourceSetFirst = Sets.newHashSet("A", "B", "C");
HashSet<String> sourceSetSecond = Sets.newHashSet("A", "D", "E");
Sets.SetView<String> unionView = Sets.union(sourceSetFirst, sourceSetSecond);
// [A, B, C, D, E]
System.out.println(unionView);
}
/**
* 将一个Map进行处理生成另一个Map
*/
@Test
public void testMapTransform() {
HashMap<Integer, String> sourceMap = Maps.newHashMap();
sourceMap.put(1, "Java");
sourceMap.put(2, "Guava");
Map<Integer, String> newMap = Maps.transformEntries(sourceMap, (key, value) -> {
return "#" + value + "#";
});
assertThat(newMap.get(1), equalTo("#Java#"));
assertThat(newMap.get(2), equalTo("#Guava#"));
}
/**
* 过滤Map生成另一个Map
*/
@Test
public void testMapFilter() {
HashMap<Integer, String> sourceMap = Maps.newHashMap();
sourceMap.put(1, "Java");
sourceMap.put(2, "Guava");
Map<Integer, String> filterMap = Maps.filterEntries(sourceMap, entry -> entry.getKey() != 1);
assertThat(filterMap.get(1), nullValue());
assertThat(filterMap.get(2), equalTo("Guava"));
}
/**
* 可以用一个key对应多个value的Map
*/
@Test
public void testMultiMapBasic() {
LinkedListMultimap<Integer, String> multimap = LinkedListMultimap.create();
multimap.put(1, "Java");
multimap.put(1, "Guava");
assertThat(multimap.size(), equalTo(2));
assertThat(multimap.get(1).get(0), equalTo("Java"));
assertThat(multimap.get(1).get(1), equalTo("Guava"));
}
/**
* Value不能重复的Map
*/
@Test
public void testBiMapCreate() {
HashBiMap<Integer, String> biMap = HashBiMap.create();
biMap.put(1, "Java");
biMap.put(1, "Guava");
assertThat(biMap.containsKey(1), equalTo(true));
assertThat(biMap.size(), equalTo(1));
assertThat(biMap.get(1), equalTo("Guava"));
try {
biMap.put(2, "Guava");
fail();
} catch (Exception e) {
assertThat(e, is(instanceOf(IllegalArgumentException.class)));
}
}
/**
* BiMap的Key-Value进行反转
*/
@Test
public void testBiMapInverse() {
HashBiMap<Integer, String> biMap = HashBiMap.create();
biMap.put(1, "Java");
biMap.put(2, "Guava");
biMap.put(3, "Mysql");
BiMap<String, Integer> inverseResult = biMap.inverse();
assertThat(inverseResult.size(), equalTo(3));
assertThat(inverseResult.get("Java"), equalTo(1));
assertThat(inverseResult.get("Guava"), equalTo(2));
assertThat(inverseResult.get("Mysql"), equalTo(3));
}
/**
* BiMap强制放入数据,会删除原有value相同的key
*/
@Test
public void testBiForcePut() {
HashBiMap<Integer, String> biMap = HashBiMap.create();
biMap.put(1, "Java");
biMap.forcePut(2, "Java");
assertThat(biMap.size(), equalTo(1));
assertThat(biMap.get(1), nullValue());
assertThat(biMap.get(2), equalTo("Java"));
}
生成类似Excel的内存表格,实现有:ArrayTable
、TreeBaseTable
、HashBaseTable
、ImmutableTable
@Test
public void testTable() {
Table<String, String, String> table = HashBasedTable.create();
table.put("Language", "Java", "1.8");
table.put("Language", "Scala", "2.3");
table.put("Database", "Oracle", "12C");
table.put("Database", "Mysql", "8.0");
Map<String, String> language = table.row("Language");
assertThat(language.containsKey("Java"), is(true));
assertThat(language.get("Java"), equalTo("1.8"));
assertThat(language.get("Scala"), equalTo("2.3"));
// [(Language,Java)=1.8, (Language,Scala)=2.3, (Database,Oracle)=12C, (Database,Mysql)=8.0]
Set<Table.Cell<String, String, String>> cells = table.cellSet();
System.out.println(cells);
}
public class ImmutableCollectionsTest {
@Test(expected = UnsupportedOperationException.class)
public void testImmutableOf() {
ImmutableList<String> list = ImmutableList.of("A", "B", "C", "D");
assertThat(list, notNullValue());
list.add("E");
}
@Test(expected = UnsupportedOperationException.class)
public void testImmutableCopy() {
Integer[] array = {1, 2, 3, 4, 5};
ImmutableList<Integer> list = ImmutableList.copyOf(array);
list.add(6);
}
@Test(expected = UnsupportedOperationException.class)
public void testImmutableBuild() {
ImmutableList<Integer> list = ImmutableList.<Integer>builder().add(1).add(2).add(3).build();
list.add(4);
}
@Test(expected = UnsupportedOperationException.class)
public void testImmutableMap() {
ImmutableMap<Integer, String> map = ImmutableMap.<Integer, String>builder()
.put(1, "Java").put(2, "Guava").build();
map.put(3, "Mysql");
}
}
@Test
public void testBasic() {
Cache<Integer, String> cache = CacheBuilder.newBuilder().maximumSize(3).build();
cache.put(1, "Java");
cache.put(2, "MySql");
cache.put(3, "Guava");
String cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, equalTo("Java"));
cache.put(4, "Redis");
cacheValue = cache.getIfPresent(2);
assertThat(cacheValue, nullValue());
}
@Test
public void testCacheLoader() {
CacheLoader<Integer, String> cacheLoader = new CacheLoader<Integer, String>() {
@Override
public String load(Integer key) throws Exception {
return "#" + key + "#";
}
};
LoadingCache<Integer, String> cache = CacheBuilder.newBuilder().maximumSize(3).build(cacheLoader);
String cacheValue = cache.getUnchecked(1);
assertThat(cacheValue, equalTo("#1#"));
cacheValue = cache.getUnchecked(2);
assertThat(cacheValue, equalTo("#2#"));
cacheValue = cache.getUnchecked(3);
assertThat(cacheValue, equalTo("#3#"));
cacheValue = cache.getUnchecked(4);
assertThat(cacheValue, equalTo("#4#"));
assertThat(cache.getIfPresent(1), nullValue());
assertThat(cache.getIfPresent(4), notNullValue());
}
@Test
public void testCacheWeight() {
CacheLoader<Integer, String> cacheLoader = new CacheLoader<Integer, String>() {
@Override
public String load(Integer key) throws Exception {
return "#" + key + "#";
}
};
Weigher<Integer, String> weigher = (key, value) -> key;
LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()
.maximumWeight(10).weigher(weigher).build(cacheLoader);
cache.getUnchecked(1);
cache.getUnchecked(2);
cache.getUnchecked(3);
cache.getUnchecked(4);
cache.getUnchecked(5);
assertThat(cache.getIfPresent(1), nullValue());
assertThat(cache.getIfPresent(2), nullValue());
assertThat(cache.getIfPresent(3), nullValue());
assertThat(cache.getIfPresent(4), equalTo("#4#"));
assertThat(cache.getIfPresent(5), equalTo("#5#"));
}
/**
* 创建一个缓存对象,通过以访问的最后时间为锚点,设置存活时间
*/
@Test
public void testAccessTTL() throws InterruptedException {
Cache<Integer, String> cache = CacheBuilder.newBuilder()
.expireAfterAccess(1, TimeUnit.SECONDS).build();
cache.put(1, "Java");
String cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, equalTo("Java"));
TimeUnit.MILLISECONDS.sleep(700L);
cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, equalTo("Java"));
TimeUnit.MILLISECONDS.sleep(700L);
cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, equalTo("Java"));
TimeUnit.MILLISECONDS.sleep(1200L);
cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, nullValue());
}
/**
* 创建一个缓存对象,通过以写入时间为锚点,设置存活时间
*/
@Test
public void testWriteTTL() throws InterruptedException {
Cache<Integer, String> cache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.SECONDS).build();
cache.put(1, "Java");
String cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, equalTo("Java"));
TimeUnit.SECONDS.sleep(2L);
cacheValue = cache.getIfPresent(1);
assertThat(cacheValue, nullValue());
}
/**
* JVM argument: -Xms64m -Xmx64m -XX:+PrintGCDetails
* 设置强引用(默认)、软引用(Safe)、弱引用(weak)、虚引用(Phantom)
* 软引用:当JVM内存紧缺时GC开始回收
* 弱引用:当执行GC时开始回收
* 虚引用:主要用来跟踪对象被垃圾回收器回收的活动,虚引用必须和引用队列 (ReferenceQueue)联合使用。
* 当GC准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列
*/
@Test
public void testRefType() throws InterruptedException {
Cache<Integer, Byte[]> cache = CacheBuilder.newBuilder().softValues().build();
int i = 0;
while (true) {
cache.put(++i, new Byte[1024 * 1024]);
System.out.println("The [" + i + "] element is store into cache.");
TimeUnit.MILLISECONDS.sleep(500);
}
}
/**
* 虚引用使用示例
*/
@Test
public void testPhantomReference() throws Exception {
byte[] values = new byte[1024 * 1024 * 6];
ReferenceQueue<byte[]> referenceQueue = new ReferenceQueue<>();
PhantomReference<byte[]> phantomReference = new PhantomReference<>(values, referenceQueue);
// 第一次未执行时,ReferenceQueue为空
Reference<? extends byte[]> ref = referenceQueue.remove(100L);
assertThat(ref, nullValue());
values = null;
System.gc();
// 执行完GC时,values被释放,加入到ReferenceQueue
TimeUnit.SECONDS.sleep(1L);
ref = referenceQueue.remove(100L);
Field referentField = Reference.class.getDeclaredField("referent");
referentField.setAccessible(true);
values = (byte[]) referentField.get(ref);
assertThat(values, notNullValue());
}
/**
* 直接通过缓存的Key获取对象为null时会抛出InvalidCacheLoadException异常
*/
@Test
public void testLoadNullWithException() {
CacheLoader<Integer, String> cacheLoader = new CacheLoader<Integer, String>() {
@Override
public String load(Integer key) throws Exception {
return null;
}
};
LoadingCache<Integer, String> cache = CacheBuilder.newBuilder().build(cacheLoader);
try {
cache.getUnchecked(1);
fail();
} catch (Exception e) {
assertThat(e, is(instanceOf(CacheLoader.InvalidCacheLoadException.class)));
}
}
/**
* 直接通过缓存的Key获取对象为Optional时可根据情况获取null值
*/
@Test
public void testLoadNullWihOptional() {
CacheLoader<Integer, Optional<String>> cacheLoader = new CacheLoader<Integer, Optional<String>>() {
@Override
public Optional<String> load(Integer key) throws Exception {
return Optional.ofNullable(null);
}
};
LoadingCache<Integer, Optional<String>> cache = CacheBuilder.newBuilder().build(cacheLoader);
Optional<String> value = cache.getUnchecked(1);
assertThat(value.isPresent(), equalTo(false));
}
@Test
public void testCachePreLoad() {
CacheLoader<String, String> loader = CacheLoader.from(String::toUpperCase);
LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(loader);
Map<String, String> preData = ImmutableMap.of("kun", "kun", "tbb", "tbb");
cache.putAll(preData);
assertThat(cache.getUnchecked("kun"), equalTo("kun"));
assertThat(cache.getUnchecked("tbb"), equalTo("tbb"));
assertThat(cache.getUnchecked("jack"), equalTo("JACK"));
}
@Test
public void testCacheRefresh() throws InterruptedException {
AtomicInteger count = new AtomicInteger(0);
CacheLoader<String, Integer> loader = CacheLoader.from(key -> count.getAndIncrement());
LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
.refreshAfterWrite(1, TimeUnit.SECONDS).build(loader);
Integer key = cache.getUnchecked("key");
assertThat(key, equalTo(0));
key = cache.getUnchecked("key");
assertThat(key, equalTo(0));
TimeUnit.SECONDS.sleep(1L);
key = cache.getUnchecked("key");
assertThat(key, equalTo(1));
}
@Test
public void testCacheRemovedNotification() {
RemovalListener<String, String> listener = notification -> {
// 状态时被移除
if (notification.wasEvicted()) {
RemovalCause cause = notification.getCause();
/**
* 被移除的原因
* RemovalCause.EXPLICIT 显示的使缓存失效,invalidate,invalidateAll
* RemovalCause.REPLACED 值被另一个值替代
* RemovalCause.COLLECTED 软引用、弱引用被垃圾回收器回收
* RemovalCause.EXPIRED 超过TTL时间
* RemovalCause.SIZE 超过缓存大小
*/
assertThat(cause, is(RemovalCause.SIZE));
assertThat(notification.getKey(), equalTo("Tom"));
}
};
CacheLoader<String, String> loader = CacheLoader.from(String::toUpperCase);
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(3).removalListener(listener).build(loader);
cache.getUnchecked("Tom");
cache.getUnchecked("Jack");
cache.getUnchecked("Jane");
cache.getUnchecked("Rose");
}
@Test
public void testCacheStatInfo() {
CacheLoader<String, String> loader = CacheLoader.from(String::toUpperCase);
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(3).recordStats().build(loader);
assertThat(cache.getUnchecked("Kun"), equalTo("KUN"));
CacheStats stats = cache.stats();
assertThat(stats.hitCount(), equalTo(0L));
assertThat(stats.missCount(), equalTo(1L));
assertThat(cache.getUnchecked("Kun"), equalTo("KUN"));
stats = cache.stats();
assertThat(stats.hitCount(), equalTo(1L));
assertThat(stats.missCount(), equalTo(1L));
assertThat(BigDecimal.valueOf(stats.missRate()), equalTo(BigDecimal.valueOf(0.5)));
assertThat(BigDecimal.valueOf(stats.hitRate()), equalTo(BigDecimal.valueOf(0.5)));
}