guava学习

guava的基础使用

一、maven配置


    com.google.guava
    guava
    30.0-jre


二、guava的几种常见的方法

1、非空判断、

使用guava使用Preconditions.checkNotNull 进行非空判断的好处,一是语义清晰代码优雅;二是你也可以自定义报错信息,这样如果参数为空,报错的信息清晰,可以直接定位到具体参数。

String param2 = null;
String name2 = Preconditions.checkNotNull(param2,"param2 is null");

2、预期值判断

和非空判断类似,可以比较当前值和预期值,如果不相等可以自定义报错信息抛出

String param = "www.wdbyte.com2";
String wdbyte = "www.wdbyte.com";
Preconditions.checkArgument(wdbyte.equals(param), "[%s] 404 NOT FOUND", param);
// java.lang.IllegalArgumentException: [www.wdbyte.com2] 404 NOT FOUND

3、是否越界

Preconditions 类还可以用来检查数组和集合的元素获取是否越界。

// Guava 中快速创建ArrayList
List list = Lists.newArrayList("a", "b", "c", "d");
// 开始校验
int index = Preconditions.checkElementIndex(5, list.size());
// java.lang.IndexOutOfBoundsException: index (5) must be less than size (4)

4、不可变的集合

创建一个不能删除、不能修改、不能增加元素的集合

优点:

  1. 线程安全,因为不能修改任何元素,可以随意多线程使用且没有并发问题。
  2. 可以无忧的提供给第三方使用,反正修改不了。
  3. 减少内存占用,因为不能改变,所以内部实现可以最大程度节约内存占用。
  4. 可以用作常量集合。
// 创建方式1:of
ImmutableSet immutableSet = ImmutableSet.of("a", "b", "c");
immutableSet.forEach(System.out::println);
// a
// b
// c

// 创建方式2:builder
ImmutableSet immutableSet2 = ImmutableSet.builder()
    .add("hello")
    .add(new String("未读代码"))
    .build();
immutableSet2.forEach(System.out::println);
// hello
// 未读代码

// 创建方式3:从其他集合中拷贝创建
ArrayList arrayList = new ArrayList();
arrayList.add("www.wdbyte.com");
arrayList.add("https");
ImmutableSet immutableSet3 = ImmutableSet.copyOf(arrayList);
immutableSet3.forEach(System.out::println);
// www.wdbyte.com
// https

5、集合操作工厂

// 创建一个 ArrayList 集合
List list1 = Lists.newArrayList();
// 创建一个 ArrayList 集合,同时塞入3个数据
List list2 = Lists.newArrayList("a", "b", "c");
// 创建一个 ArrayList 集合,容量初始化为10
List list3 = Lists.newArrayListWithCapacity(10);

LinkedList linkedList1 = Lists.newLinkedList();
CopyOnWriteArrayList cowArrayList = Lists.newCopyOnWriteArrayList();

HashMap hashMap = Maps.newHashMap();
ConcurrentMap concurrentMap = Maps.newConcurrentMap();
TreeMap treeMap = Maps.newTreeMap();

HashSet hashSet = Sets.newHashSet();
HashSet newHashSet = Sets.newHashSet("a", "a", "b", "c");



6、集合交集并集差集

Set newHashSet1 = Sets.newHashSet("a", "a", "b", "c");
Set newHashSet2 = Sets.newHashSet("b", "b", "c", "d");

// 交集
SetView intersectionSet = Sets.intersection(newHashSet1, newHashSet2);
System.out.println(intersectionSet); // [b, c]

// 并集
SetView unionSet = Sets.union(newHashSet1, newHashSet2);
System.out.println(unionSet); // [a, b, c, d]

// newHashSet1 中存在,newHashSet2 中不存在
SetView setView = Sets.difference(newHashSet1, newHashSet2);
System.out.println(setView); // [a]

7、字符拼接

可以看到使用 skipNulls() 可以跳过空值,使用 useFornull(String) 可以为空值自定义显示文本。

ArrayList list = Lists.newArrayList("a", "b", "c", null);
String join = Joiner.on(",").skipNulls().join(list);
System.out.println(join); // a,b,c

String join1 = Joiner.on(",").useForNull("空值").join("旺财", "汤姆", "杰瑞", null);
System.out.println(join1); // 旺财,汤姆,杰瑞,空值

8、字符串分割

Guava 提供了 Splitter 类,并且有一系列的操作方式可以直观的控制分割逻辑。

String str = ",a ,,b ,";
Iterable split = Splitter.on(",")
    .omitEmptyStrings() // 忽略空值
    .trimResults() // 过滤结果中的空白
    .split(str);
split.forEach(System.out::println);

9、缓存

在开发中我们可能需要使用小规模的缓存,来提高访问速度。这时引入专业的缓存中间件可能又觉得浪费。现在可以了, Guava 中提供了简单的缓存类,且可以根据预计容量、过期时间等自动过期已经添加的元素。即使这样我们也要预估好可能占用的内存空间,以防内存占用过多。

@Test
public void testCache() throws ExecutionException, InterruptedException {

    CacheLoader cacheLoader = new CacheLoader() {
        // 如果找不到元素,会调用这里
        @Override
        public Animal load(String s) {
            return null;
        }
    };
    LoadingCache loadingCache = CacheBuilder.newBuilder()
        .maximumSize(1000) // 容量
        .expireAfterWrite(3, TimeUnit.SECONDS) // 过期时间
        .removalListener(new MyRemovalListener()) // 失效监听器
        .build(cacheLoader); //
    loadingCache.put("狗", new Animal("旺财", 1));
    loadingCache.put("猫", new Animal("汤姆", 3));
    loadingCache.put("狼", new Animal("灰太狼", 4));

    loadingCache.invalidate("猫"); // 手动失效

    Animal animal = loadingCache.get("狼");
    System.out.println(animal);
    Thread.sleep(4 * 1000);
    // 狼已经自动过去,获取为 null 值报错
    System.out.println(loadingCache.get("狼"));
    /**
     * key=猫,value=Animal{name='汤姆', age=3},reason=EXPLICIT
     * Animal{name='灰太狼', age=4}
     * key=狗,value=Animal{name='旺财', age=1},reason=EXPIRED
     * key=狼,value=Animal{name='灰太狼', age=4},reason=EXPIRED
     *
     * com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key 狼.
     */
}

/**
 * 缓存移除监听器
 */
class MyRemovalListener implements RemovalListener {

    @Override
    public void onRemoval(RemovalNotification notification) {
        String reason = String.format("key=%s,value=%s,reason=%s", notification.getKey(), notification.getValue(), notification.getCause());
        System.out.println(reason);
    }
}

class Animal {
    private String name;
    private Integer age;

    @Override
    public String toString() {
        return "Animal{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }

    public Animal(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

这个例子中主要分为 CacheLoader、MyRemovalListener、LoadingCache。

CacheLoader 中重写了 load 方法,这个方法会在查询缓存没有命中时被调用,我这里直接返回了 null,其实这样会在没有命中时抛出 CacheLoader returned null for key 异常信息。

MyRemovalListener 作为缓存元素失效时的监听类,在有元素缓存失效时会自动调用 onRemoval 方法,这里需要注意的是这个方法是同步方法,如果这里耗时较长,会阻塞直到处理完成。

LoadingCache 就是缓存的主要操作对象了,常用的就是其中的 put get 方法了。

你可能感兴趣的:(java,redis,android,python,scala)