java技巧性技能点

  哈哈哈,我胡汉三...不对本博主Fn又回来了,从事开发也几年了,最近看了点东西,闲着一起聊一聊呗,如有误,望指正。

 

  自定义缓存

  在现在的项目开发过程中,缓存是必不可少的一部分,无论是redis还是memcached,这些都是一些缓存需要的中间件,通常使用的mybatis,其中也有缓存的参与,因此这一部分的东西掌握是必不可少的,而项目是分布式部署的,那么可以使用JDK本身来自定义一个缓存容器,无论是LRU,FIFO,还是自定义二级缓存,都需要借助容器类来进行实现的,下面是一个可作为本地二级缓存使用的一个类,可自行扩展设计

package com.fn.test.cache;

import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * @Class : CacheManager
 * @Description :单个服务器内保存在JDK中,可做为二级缓存使用
 * @Author | @Date : Fn-f | 2019-12-01 19:22:01
 */
@Service("cacheManager")
public class CacheManager {

    // 日志信息,真实项目中可使用LoggerFactory
    private static final Logger LOGGER = Logger.getLogger("CacheManager");

    // cacheMap,作为缓存的容器
    private Map<String, CacheItem> cache = new HashMap<String, CacheItem>();

    /**
     * 添加值至本地缓存中
     * @param key
     * @param val
     */
    public void set (String key, Object val) {
            set(key, val, null);
    }

    /**
     * 添加值至本地缓存中,含过期时间(默认秒)
     * @param key
     * @param val
     * @param expired
     */
    public void set (String key, Object val, Long expired) {
        LOGGER.info("cache set -> param: {" + key + ", " + val + ", " + expired + "}");
        cache.put(key, new CacheItem().setObj(val).setTime(System.currentTimeMillis()).setExpired(expired));
    }

    /**
     * 获取key对应的值
     * @param key
     * @return
     */
    public Object get (String key) {
        LOGGER.info("cache get -> param: {" + key + "}");
        CacheItem item = cache.get(key);
        if (item != null && (
                item.getExpired() == null
                ||
                System.currentTimeMillis() < (item.getExpired() + item.getTime() * 1000L))) {
            return item.getObj();
        }
        cache.remove(key);
        return null;
    }

    /**
     * 删除缓存中的key
     * @param key
     */
    public void del (String key) {
        LOGGER.info("cache del -> param: {" + key + "}");
        if (cache.get(key) != null) {
            cache.remove(key);
        }   
    }

    @Data
    @Accessors(chain = true)
    private class CacheItem {
        // 当前存储对象
        private Object obj;
        // 当前存储时间
        private Long time;
        // 过期时间段
        private Long expired;
    }
}

 

   函数式接口

   JDK 8 发布已经好几年了,当前JDK12已经出来了,而对于java开发者来说,已经进入吃力学习,不断追赶,但是对于公司来说,大部分公司还是使用的是JDK 8 为主的,当然也有使用JDK 11 及以上版本的,毕竟JDK版本越高,其中无论是开发,还是优化都有一些调整,而目前使用的JDK 8 中的函数式编程,前面有一章节介绍了 Stream 流,这章也可看看,试用一下呗,自我感觉还是可以的,毕竟代码越少,程序越简洁,执行效率可能会更高(这一点先不用着急否认呐,毕竟荣誉代码与简洁代码的执行之间,编译还是优化都有很大的差别的,可以仔细研究呐),可以看看<Java 8 实战>这本书呐

package com.fn.test.util;

import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Class : StreamUtil
 * @Description :JDK 8 lambda使用,可自行扩展
 * @Author | @Date : Fn-f | 2019-12-01 19:22:01
 */
public class StreamUtil {

    /**
     * 满足某种函数返回指定数据集合信息,去重
     * @param list
     * @param fn
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> ids (List<T> list, Function<T, R> fn) {
        return !CollectionUtils.isEmpty(list) ? new ArrayList(list.stream().map(fn).collect(Collectors.toSet())) : Collections.EMPTY_LIST;
    }

    /**
     * 满足某种函数返回K-V信息,groupingBy返回信息为Map<T, List>,可能并非目前所需
     * @param list
     * @param fn
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Map<T, R> map (List<R> list, Function<R, T> fn) {
        return !CollectionUtils.isEmpty(list) ? new ArrayList(list.stream().collect(Collectors.toMap(fn, i -> i)) : Collections.EMPTY_MAP;
    }

    /**
     * 可以指定其他类似
     */
    //public static test () { ...

}

 

  位运算(基础)

   对于本博主这个非科班出身的程序员来说,这个熟悉,但是开发中使用还是没有太多机会的,当然也做过一些研究,什么补位,反码,补码等等吧,而现在看到其一个具体的应用,自我感觉记录下来,有遇到同样问题的开发人员可以借鉴参考呐

   开发过程中,有可能会给某个东西贴标签,又或给某个人以某种身份,当有多中标签或身份时,难道要进行信息值累加吗?  这个时候用位运算是最好不过的。

package com.fn.test.demo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.experimental.Accessors;

/**
 * @Class : ItemInfo
 * @Description :商品信息:食物的味觉信息
 * @Author | @Date : Fn-f | 2019-12-01 19:22:01
 */
@Data
@Accessors(chain = true)
public class ItemInfo {

    private String name;
    private String price;
    private int tasteval;
    private Taste teste;

    /**
     * 味道信息
     */
    @Data
    static class Taste {
        private boolean sweet;
        private boolean acid;
        private boolean bitter;
        private boolean spicy;
        private boolean fragrant;
        private boolean smelly;

// 与运算,复boolean制 public Taste (int tasteval) { this.sweet = (tasteval & TasteEnum.SWEET.getCode()) > 0; this.acid = (tasteval & TasteEnum.ACID.getCode()) > 0; this.bitter = (tasteval & TasteEnum.BITTER.getCode()) > 0; this.spicy = (tasteval & TasteEnum.SMELLY.getCode()) > 0; this.fragrant = (tasteval & TasteEnum.FRAGRANT.getCode()) > 0; this.smelly = (tasteval & TasteEnum.SMELLY.getCode()) > 0; } } /** * 味道枚举信息 */ @Getter @AllArgsConstructor enum TasteEnum { SWEET ( 1 << 0, "甜"), ACID ( 1 << 1, "酸"), BITTER ( 1 << 2, "苦"), SPICY ( 1 << 3, "辣"), SALTY ( 1 << 4, "咸"), FRAGRANT ( 1 << 5, "香"), SMELLY ( 1 << 6, "臭"), ; private int code; private String desc; } /** * 测试 */ public static void main(String[] args) { ItemInfo apple = new ItemInfo(); apple.setName("苹果"); apple.setPrice("19.9元"); // 苹果味道:甜酸香 apple.setTasteval( TasteEnum.SWEET.getCode() + TasteEnum.ACID.getCode() + TasteEnum.FRAGRANT.getCode()); // 解析味道信息,进行展示等 apple.setTeste(new Taste(apple.getTasteval())); System.out.println(apple); // ItemInfo( // name=苹果, price=19.9元, tasteval=35, // teste=ItemInfo.Taste( // sweet=true, acid=true, bitter=false, // spicy=false, fragrant=true, smelly=false) // ) } }

 

  随机数

   随机数处理,可以与时间戳一起,增大随机性

import java.util.Random;

/**
 * @Class : Random
 * @Description :随机数
 * @Author | @Date : Fn-f | 2019-12-01 19:10:01
 */
public class R {

  private static final String BASE_NUM = "0123456789";
  private static final String BASE_STR =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";

  /**
   * 获取指定大小的随机串(配合时间点来处理)
   *
   * @param base 指定字符源
   * @param size 随机串大小
   * @param zwst zero with start tag(从零开始标志)
   * @return String
   */
  public static String random(String base, int size, boolean zwst) {
    if (size <= 0) {
      return "";
    }
    StringBuilder s = new StringBuilder();
    Random r = new Random();
    for (int i = 0; i < size; i++) {
      char c;
      do {
        c = base.charAt(r.nextInt(base.length()));
        // 首位避免为零判断逻辑
      } while (zwst && i == 0 && ((int) '0' == (int) c));
      s.append(c);
    }
    return s.toString();
  }

  public static void main(String[] args) {
    System.out.println(random(BASE_NUM, 9, false));   // 189640865
    System.out.println(random(BASE_STR, 9, false));   // SvITxDRc3
  }

}
View Code

 

  多线程使用(异步处理)

   多线程的用法,有可能需要花费新的章节进行阐述,毕竟体系是十分胖庞大的,可以在项目中使用线程进行异步处理,可以使用线程池或相关的类来进行

        比如使用 ThreadPoolManager()、Runnable()、Callable()、CompletableFuture.runAsync()、CompletableFuture.whenComplete()、等等处理形式,这一小节后续放置独立的一篇进行阐述。

 

  枚举的别样用法

   枚举中除了日常使用方式之外,其实质上可以当做一个类来进行使用,内部也可以指定方法,相应的属性处理对应的业务逻辑即可,这个也是一个优秀的操作。

 

  视频剪辑工具FFMPEG

  当有视频、音频、图片需要处理时,该工具能够帮助你得到自己想要的数据。尝试之前,必须要先安装该工具哟

 

  工具类Hutool

  简介:https://gitee.com/loolly/hutool/

Hutool简介:

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

Hutool中的工具方法来自于每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;

Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
Hutool名称的由来

Hutool = Hu + tool,是原公司项目底层代码剥离后的开源库,“Hu”是公司名称的表示,tool表示工具。Hutool谐音“糊涂”,一方面简洁易懂,一方面寓意“难得糊涂”。
Hutool如何改变我们的coding方式

Hutool的目标是使用一个工具方法代替一段复杂代码,从而最大限度的避免“复制粘贴”代码的问题,彻底改变我们写代码的方式。

以计算MD5为例:
    【以前】打开搜索引擎 -> 搜“Java MD5加密” -> 打开某篇博客-> 复制粘贴 -> 改改好用
    【现在】引入Hutool -> SecureUtil.md5()

Hutool的存在就是为了减少代码搜索成本,避免网络上参差不齐的代码出现导致的bug。

 

       ......

  本文章后续不间断增新,望指正。

 

  (愿你的每一行代码,都有让世界进步的力量    ------   fn)

posted @ 2019-12-01 14:51  fn-f  阅读(316)  评论(0编辑  收藏  举报