搜 索

面向guava编程(一)

  • 195阅读
  • 2022年05月02日
  • 0评论
首页 / Java/Scala/C / 正文

guava是google开发的一个基础java类库,包括主要的模块为utilities/Functional/Collections/concurrency/cache/eventbus/work files,guava提供了很多好用的api,使用guava编程可以有效提高开发效率和代码质量。

Joiner(list/map转化为string)


    private static final String COMMA = ",";
    private static final String EMPTY = "";
    private static final String EQUALS = "=";

    public static String oldJoiner(List<String> dataList) {
        // 老的方法实现
        if (dataList == null) {
            return null;
        }
        StringBuilder accum = new StringBuilder();
        for (String item : dataList) {
            accum.append(item == null ? EMPTY : item).append(COMMA);
        }
        String joinResult = accum.toString();
        return joinResult.substring(0, joinResult.length() - 1);
    }

    public static String oldJoiner(Map<String,String> dataMap){
        if (dataMap == null){
            return null;
        }
        // 老的方式,转换代码和判断比较多
        StringBuilder accum = new StringBuilder();
        for (Map.Entry<String,String> item : dataMap.entrySet()) {
            accum.append(item.getKey() == null ? EMPTY : item.getKey()).append(EQUALS).append(item.getValue()).append(COMMA);
        }
        String joinResult = accum.toString();
        return joinResult.substring(0, joinResult.length() - 1);
    }

    public static String joiner(List<String> dataList) {
        if (dataList == null) {
            return null;
        }
        // guava的实现,该方法使用类似于python中的",".join(list)
        return Joiner.on(COMMA).useForNull(EMPTY).join(dataList);
    }

    public static String appendTo(List<String> dataList){
        return Joiner.on(COMMA).useForNull(EMPTY).appendTo(new StringBuilder(), dataList).toString();
    }

    public static String joiner(Map<String,String> dataMap){
        if (dataMap == null){
            return null;
        }
        // guava joiner将map值转化为string
        return Joiner.on(COMMA).useForNull(EMPTY).withKeyValueSeparator(EQUALS).join(dataMap);
    }


    public static void main(String[] args) {
        // 要求:将list转化为使用逗号分隔的字符串
        List<String> dataList = Arrays.asList("1", "2", "3", null);
        System.out.println(appendTo(dataList));
        // 测试代码
        TestUtil.assertIsTrue(TestUtil.equals(joiner(dataList), oldJoiner(dataList)), "值不等");
        dataList = null;
        TestUtil.assertIsTrue(TestUtil.equals(joiner(dataList), oldJoiner(dataList)), "值不等");

        Map<String,String> dataMap = new HashMap<>(5);
        dataMap.put("a","1");
        dataMap.put("b","2");
        dataMap.put("c","3");
        dataMap.put(null,"4");
        dataMap.put("e","5");
        TestUtil.assertIsTrue(TestUtil.equals(joiner(dataMap), oldJoiner(dataMap)), "值不等");
        dataMap = null;
        TestUtil.assertIsTrue(TestUtil.equals(joiner(dataMap), oldJoiner(dataMap)), "值不等");
    }

Splitter(string转化为list/map)

private static final String COMMA = ",";
    private static final String EMPTY = "";
    private static final String EQUALS = "=";

    public static List<String> oldSplit(String data){
        if(data == null){
            return null;
        }
        String[] array = data.split(COMMA);
        List<String> resultList = new ArrayList<>(array.length);
        for(String item: array){
            if(item != null && !EMPTY.equals(item.trim())){
                resultList.add(item.trim());
            }
        }
        return resultList;
    }

    public static List<String> split(String data){
        if(data == null){
            return null;
        }
        // 可以split 到Iterator/List/Stream
        // 分隔符可以支持正则表达式
        return Splitter.on(COMMA).omitEmptyStrings().trimResults().splitToList(data);
    }


    public static Map<String,String> oldSplit2Map(String data){
        if(data == null){
            return null;
        }
        String[] array = data.split(COMMA);
        Map<String,String> resultMap = new HashMap<>(array.length);
        for(String item: array){
            if(item != null && !EMPTY.equals(item.trim())){
                String[] innerArr = item.split(EQUALS);
                if(innerArr.length==2) {
                    resultMap.put(innerArr[0], innerArr[1]);
                }
            }
        }
        return resultMap;
    }

    public static Map<String,String> split2Map(String data){
        if(data == null){
            return null;
        }
        // 和joiner相同,可以split 到Map(Beta版本)
        return Splitter.on(COMMA).omitEmptyStrings().trimResults().withKeyValueSeparator(EQUALS).split(data);
    }

    public static void main(String[] args) {
        String data = "1,2 , 3, ";
        TestUtil.assertIsTrue(TestUtil.equals(split(data), oldSplit(data)), "值不等");
        TestUtil.assertIsTrue(TestUtil.equals(split(null), oldSplit(null)), "值不等");
        String data2 = "=4,a=1,b=2,c=3,e=5";
        TestUtil.assertIsTrue(TestUtil.equals(split2Map(data2), split2Map(data2)), "值不等");
        TestUtil.assertIsTrue(TestUtil.equals(split2Map(null), split2Map(null)), "值不等");
    }

Collection(封装)


    public static List<String> oldCreateList(String a, String b, String c){
        // m1: java入门的方法
//        List<String> resultList = new ArrayList<>();
//        resultList.add(a);
//        resultList.add(b);
//        resultList.add(c);
//        return resultList;
        // m2: 创建了一个list-Arrays$ArrayList,仅能读取,不支持add/remove操作(java.lang.UnsupportedOperationException)
//        return Arrays.asList(a,b,c);
        // m3: 包了一层ArrayList,可add/remove,但性能有降低,且很难看
        return new ArrayList<>(Arrays.asList(a,b,c));
    }

    public static List<String> createList(String a, String b, String c){
        // 创建一个array list
        return Lists.newArrayList(a,b,c);
    }

    public static List<List<String>> partition(List<String> sourceList, int size){
        // 将list按size分块,apache同样提供了ListUtils.partition方法
        return Lists.partition(sourceList, size);
    }

    public static List<Integer> oldTransform(List<String> sourceList){
        if(sourceList==null){
            return null;
        }
        // 原生转换
        return sourceList.stream().filter(Objects::nonNull).map(String::length).collect(Collectors.toList());
    }

    public static List<Integer> transform(List<String> sourceList){
        if(sourceList==null){
            return null;
        }
        // Lists转换,比起原生代码略短
        // 没有找到过滤方法
        return Lists.transform(sourceList, s->s==null?null:s.length());
    }


    public static Map createMap(){
        //指定的是实际容量,而非capacity,由于loadFactor默认为0.75,所以new HashMap(16)的实际容量只有12,超出会自动扩容影响效率
        return Maps.newHashMapWithExpectedSize(16);
    }



    public static void main(String[] args){
        String a="1",b="2",c="3";
        List<String> oldList = oldCreateList(a, b, c);
        TestUtil.assertIsTrue(TestUtil.equals(oldCreateList(a, b, c), createList(a,b,c)), "值不等");
        oldList.add("12");
        System.out.println(partition(oldList, 3));
        TestUtil.assertIsTrue(TestUtil.equals(oldTransform(oldList),transform(oldList)),"值不等");
        TestUtil.assertIsTrue(TestUtil.equals(oldTransform(null),transform(null)),"值不等");
        oldList.add(null);
        TestUtil.assertIsTrue(TestUtil.equals(oldTransform(oldList),transform(oldList)),"值不等");

    }

### 本地缓存()
我们一般会将频繁读取的数据保存在redis等缓存服务中,在每次请求的时候,优先从缓存中读取以减小数据开销,提升性能

 * 在访问远程缓存的情况下,一般耗时为3-5ms,虽然这个值不大,但是在一个流程中频繁读取的情况下,也会拖慢系统响应速度,
 * 此时我们需要使用本地缓存以提升性能,本地缓存顾名思义即数据存储在本地内存中,适用于频繁读取,并且数据量不太大的场景,在应用重启时本地缓存会全部丢失。
 * 而guava提供了一个易用的本地缓存

    // fixme:此处为方便测试,设置5秒钟后缓存过期
    private static final String CACHE_CONFIG = "initialCapacity=50,maximumSize=1000,expireAfterWrite=5s";

    /**
     * 以下为guava cache最简单的使用方法
     * cachebuilder.from 更便于参数化控制缓存效果
     */
    private LoadingCache<String, Optional<Integer>> cacheLoader = CacheBuilder.from(CACHE_CONFIG)
            .build(new CacheLoader<String, Optional<Integer>>() {
                @Override
                public Optional<Integer> load(String key) {
                    /**
                     * 在此处初始化缓存,从配置,redis或db从读取
                     * 备:使用optional的原因是load无法处理空值
                     */
                    return Optional.ofNullable(initCache(key));
                }
            });

    public Integer initCache(String key) {
        // fixme:假设加载缓存需要1秒钟
        Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
        return new Random().nextInt();
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Stopwatch stopwatch = Stopwatch.createStarted();
        String key1 = "paramA";
        Caches caches = new Caches();
        Optional<Integer> val = caches.cacheLoader.get(key1);
        System.out.println(String.format("key:%s,val:%s,time cost:%s", key1, val.get(), stopwatch.elapsed(TimeUnit.MILLISECONDS)));
        stopwatch.reset();
        stopwatch.start();
        val = caches.cacheLoader.get(key1);
        // 此处读取本地缓存,加载时间为0
        System.out.println(String.format("key:%s,val:%s,time cost:%s", key1, val.get(), stopwatch.elapsed(TimeUnit.MILLISECONDS)));
        stopwatch.reset();
        stopwatch.start();
        String key2 = "paramB";
        val = caches.cacheLoader.get(key2);
        System.out.println(String.format("key:%s,val:%s,time cost:%s", key2, val.get(), stopwatch.elapsed(TimeUnit.MILLISECONDS)));
        stopwatch.reset();
//        Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
        // 手动清除本地缓存
        caches.cacheLoader.invalidateAll();
        System.out.println("size:"+caches.cacheLoader.asMap().size());
        stopwatch.start();
        val = caches.cacheLoader.get(key1);
        // 此时耗时为1秒
        System.out.println(String.format("key:%s,val:%s,time cost:%s", key1, val.get(), stopwatch.elapsed(TimeUnit.MILLISECONDS)));

    }

基础类型

基础类型的封装:Booleans/Bytes/Chars/Doubles/Floats/Ints/Longs/Shorts八种基本类型的封装和衍生类型

 * 原生类型数组转化为list
 * 校验:checkedCast,ensureCapacity
 * 比较:compare,min,max
 * 查找:contains,indexOf,lastIndexOf
 * 类型转换:toByteArray,fromByteArray,fromBytes,stringConverter,toArray,asList,tryParse
 * 合并:concat,join,
 * 排序:sortDescending,reverse
评论区
暂无评论
avatar