JAVA开发常用API及封装

一、按行读取文件返回List<String>.

1、java的nio包下使用

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
List<String> list = Files.readAllLines(Paths.get(PATH), StandardCharsets.UTF_8);

2、commons-io下使用

List<String> stringList = FileUtils.readLines(new File(PATH), StandardCharsets.UTF_8);

3、自定义实现

    /**
     * Buffer读取文件
     */
    public static List<String> readFile(){
        List<String> list=new ArrayList<>();
        try (BufferedReader reader = Files.newBufferedReader(Paths.get(PATH), StandardCharsets.UTF_8)) {
            String line;
            while ((line = reader.readLine()) != null) {
                list.add(line);
            }
        } catch (IOException e) {
            log.error("file read error", e);
        }
        return list;
    }

二、相同List数据叠加.

    /**
     * List数据叠加
     *
     * @param baseData 原始结合
     * @param addedData 叠加集合
     * @return 叠加集合
     */
    public static List<Long> add(List<Long> baseData,List<Long> addedData){
        if(CollectionUtils.isEmpty(baseData)){
            return Collections.emptyList();
        }
        if(CollectionUtils.isEmpty(addedData)){
            return baseData;
        }
        if(baseData.size()!=addedData.size()){
             new GlobalException("base data size not equal added data");
        }
        for(int i=0;i<baseData.size();i++){
            baseData.set(i,baseData.get(i)+addedData.get(i));
        }
        return baseData;
    }

 对象判空.

    /**
     * 对象空判断
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }

        if (obj.getClass().isArray()) {
            return Array.getLength(obj) == 0;
        }
        if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length() == 0;
        }
        if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        }
        if (obj instanceof Map) {
            return ((Map) obj).isEmpty();
        }
        // else
        return false;
    }

三、Long型数据转换int型,注意溢出时候会抛出异常便于排查.

System.out.println(Math.toIntExact(Long.MAX_VALUE));

 四、List数组之间转换以及常用的集合工具.

 // 1、空集合,底层自定义一个EmptyList实现,接口空list返回,不像new ArrayList分配不必要的内存空间
 Collections.emptyList();
 // 2、单值List,底层定义SingletonList,size为1
 Collections.singletonList(new Object());
 // 3、线程安全的List,底层定义SynchronizedList,方法定义通过synchronized代码实现线程安全,定义了一个SynchronizedCollection
 Collections.synchronizedList(new ArrayList<>());
 // 4、不可变List,不支持修改,定义一个UnmodifiableCollection,UnmodifiableList
 Collections.unmodifiableList(new ArrayList<>());
 // 5、CopiesList
 List<String> stringList = Collections.nCopies(10, "dfs");
// int[]转换List<Integer>
List<Integer> list = Arrays.stream(num).boxed().collect(Collectors.toList());
System.out.println(list);
// list<Integer>转换Integer[]
Integer[] integers = list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(integers));
// list<Integer>转换int[]
int[] result = list.stream().mapToInt(Integer::intValue).toArray();
System.out.println(Arrays.toString(result));
// List<Integer>转换Integer[]
Integer[] array = list.toArray(new Integer[0]);
System.out.println(Arrays.toString(array));
// Integer[]转换List<Integer>
List<Integer> asList = Arrays.asList(array);
System.out.println(asList);
// int[]->Integer[]
Integer[] integerNum = Arrays.stream(num).boxed().toArray(Integer[]::new);
// Integer[]->int[]
int[] intNum = Arrays.stream(integerNum).mapToInt(Integer::intValue).toArray();
    /**
     * Object转换Int
     *
     * @param value
     * @return int
     */
    private static int toInt(Object value){
        if(value instanceof BigDecimal){
            return ((BigDecimal)value).intValue();
        }
        if(value instanceof BigInteger){
            return ((BigInteger)value).intValue();
        }
        if(value instanceof Integer){
            return ((Integer) value).intValue();
        }
        if(value instanceof Long){
            return ((Long)value).intValue();
        }
        throw new GlobalException("to int error");
    }

 数组排序,一般使用util包下的以及转换为集合或者是Apache下的包

五、SpringBoot获取初始化ApplicationContext.

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SkywalkApplication.class, args);
        // 初始化ApplicationContext
        ApplicationContextUtil.setApplicationContext(context);
    }

 ApplicationContextUtil工具类.

package com.boot.skywalk.bean;

import com.boot.skywalk.exception.GlobalException;
import org.springframework.context.ApplicationContext;

import java.util.Objects;

/**
 * ApplicationContext工具类
 */
public final class ApplicationContextUtil {
    /**
     * 获取ApplicationContext
     */
    private static ApplicationContext applicationContext;

    private ApplicationContextUtil(){
        throw new GlobalException("unsupport create instance!");
    }
    
    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }

    /**
     * 获取ApplicationContext
     *
     * @return ApplicationContext
     */
    public static ApplicationContext getInstance(){
        if(Objects.isNull(applicationContext)){
             new GlobalException("Spring FrameWork Init Failure");
        }
        return applicationContext;
    }
}

六、BeanUtil工具类封装.

package com.boot.skywalk.bean;

import com.boot.skywalk.exception.GlobalException;
import org.apache.commons.collections.MapUtils;
import org.springframework.context.ApplicationContext;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * Bean工具获取类
 */
public final class CommonBeanUtils {
    private CommonBeanUtils(){
        throw new GlobalException("unsupport create instance");
    }
    
    /**
     * 获取ApplicationContext
     */
    private static final ApplicationContext context=ApplicationContextUtil.getInstance();
    /**
     * 获取指定类型的Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static  <T> T getBean(Class<T> clazz){
        return context.getBean(clazz);
    }
    /**
     * 获取指定名称的Bean
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return context.getBean(name);
    }
    /**
     * 获取指定类型Bean列表
     *
     * @param clazz clazz
     * @param <T>
     * @return List<T>
     */
    public static  <T> List<T> getBeanList(Class<T> clazz){
        Map<String, T> beans = context.getBeansOfType(clazz);
        if(MapUtils.isEmpty(beans)){
            return Collections.emptyList();
        }
        List<T> list = beans.values().stream().collect(Collectors.toList());
        return list;
    }
}

七、Bean的属性复制时候推荐使用Spring框架下的.

①、Spring框架下的BeanUtil

 ②、Apache下的,有加锁获取逻辑,相对耗时方便推荐Spring框架的.

 八、工具类尽可能封装为单例模式,如RestClient、BeanUtils等.

九、当Maven多模块循环依赖时候,经过过滤器需要调用某个类的业务方法时候,这个时候可以使用反射调用.Spring的ReflectUtils或者是Class.forName();

Student student = (Student)ReflectUtils.newInstance(Student.class);
student.test();

十、全局异常定义.

public class GlobalException extends RuntimeException {
    public GlobalException() {
        super();
    }

    public GlobalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    /**
     * @param message
     * @param cause
     */
    public GlobalException(String message, Throwable cause) {
        super(message, cause);
    }

    /**
     * @param message
     */
    public GlobalException(String message) {
        super(message);
    }

    /**
     * @param cause
     */
    public GlobalException(Throwable cause) {
        super(cause);
    }
}

可以根据一些项目自定义一些抽象异常子类,参考Spring框架的.

 

参数校验使用一些断言更佳.

Assert.isNull(str,"str message");

获取异常堆栈信息.

    public static List<Object> getStackInfoList(){
        List<Object> list = new ArrayList<>();
        try {
            int num=1/0;
        } catch (Exception e) {
            list.add(e.getStackTrace()[0].getClassName());
            list.add(e.getStackTrace()[0].getFileName());
            list.add(e.getStackTrace()[0].getClass());
            list.add(e.getStackTrace()[0].getLineNumber());
        }
        return list;
    }

 将异常信息拼接为字符串.

    /**
     * parse error to string
     *
     * @param e
     * @return
     */
    public static String toString(Throwable e) {
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        String errorMsg = stringWriter.toString();
        return errorMsg;
    }

普通执行器

    /**
     * 普通执行器
     *
     * @param supplier
     * @param <T>
     * @return
     */
    public static <T> T executor(Supplier<T> supplier){
        return supplier.get();
    }

 适用一些幂等的Client调用. 

   import com.boot.skywalk.exception.GlobalException;
   import lombok.extern.slf4j.Slf4j;
   import org.springframework.util.Assert;

   import java.util.function.Supplier;
  
   /**
     * 带重试次数执行器
     *
     * @param supplier
     * @param retry
     * @param <T>
     * @return
     */
    public static <T> T executorWithRetry(Supplier<T> supplier,int retry){
        Assert.isTrue(retry>=0, "retry times less than 0");
        int times=0;
        while(times++<retry){
            try {
                supplier.get();
            } catch (Exception e) {
                log.error("service method retry", e);
            }
        }
        log.error("service method already retry times={}",retry);
        throw new GlobalException("service method failed");
    }

十一、静态块+Map实现一些重构.

     1、如一些策略模式缓存策略实现类,StrategyFactory.

 private static final Map<String,IStrategy> STRATEGY=new HashMap<>();

十二、函数式接口的封装使用.

     1、回调接口.

/**
 * 通用回调函数式接口
 */
@FunctionalInterface
public interface ICallback<T>{
    /**
     * 回调方法
     * @param t
     */
    void callback(T t);
}

      2、参数校验接口.

@FunctionalInterface
public interface ICheck<T> {
    /**
     * 通用业务校验
     * @param t
     */
    void check(T t);
}

十三、List指定大小切割.

是直接在原来的List的改变的,partition,guava的也是一样的,一般使用批次更新查询和批次拉取数据,提升性能.

 封装一个不改变原来List的partitionList.

    /**
     * 切割List,类似Lists.partition的切割
     *
     * @param list
     * @param size
     * @param <T>
     * @return
     */
    private static <T> List<List<T>> partition(List<T> list, int size){
          if(CollectionUtils.isEmpty(list)){
              throw new GlobalException("partition list is null");
          }
          if(size<0){
              throw new GlobalException("partition size less than 0");
          }
          int length=list.size();
          // 计算分组大小
          int partitionSize=(length+size-1)/size;
          List<List<T>> newList = new ArrayList<>(partitionSize);
          for(int i=0;i<partitionSize;i++){
              int fromIndex=i*size;
              int toIndex=Math.min((i+1)*size,length);
              newList.add(list.subList(fromIndex, toIndex));
          }
          return newList;
    }

使用方式如下:

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, -6, 7, 8, 9, 10, -11, 12, 13, -14, 15, 16);
        // 分组
        List<List<Integer>> partitionList = partition(list, 5);
        System.out.println(partitionList);
        List<List<Integer>> result=new ArrayList<>();
        // 分组后再过滤
        partitionList.stream().forEach(partition->{
            List<Integer> collect = partition.stream().filter(num -> num > 0).collect(Collectors.toList());
            result.add(collect);
        });
        System.out.println(result);
        // 过滤再分组
        List<Integer> filterList = list.stream().filter(num -> num > 0).collect(Collectors.toList());
        List<List<Integer>> partitionResultList = partition(filterList, 5);
        System.out.println(partitionResultList);

 

不同的判定逻辑,注意业务代码中的使用. 

十三、时间工具类,参考Flink工具类封装.

org.apache.flink.api.common.time
public final class Time implements Serializable {

    private static final long serialVersionUID = -350254188460915999L;

    /** The time unit for this policy's time interval. */
    private final TimeUnit unit;

    /** The size of the windows generated by this policy. */
    private final long size;

    /** Instantiation only via factory method. */
    private Time(long size, TimeUnit unit) {
        this.unit = checkNotNull(unit, "time unit may not be null");
        this.size = size;
    }

    // ------------------------------------------------------------------------
    //  Properties
    // ------------------------------------------------------------------------

    /**
     * Gets the time unit for this policy's time interval.
     *
     * @return The time unit for this policy's time interval.
     */
    public TimeUnit getUnit() {
        return unit;
    }

    /**
     * Gets the length of this policy's time interval.
     *
     * @return The length of this policy's time interval.
     */
    public long getSize() {
        return size;
    }

    /**
     * Converts the time interval to milliseconds.
     *
     * @return The time interval in milliseconds.
     */
    public long toMilliseconds() {
        return unit.toMillis(size);
    }

    @Override
    public String toString() {
        return toMilliseconds() + " ms";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Time time = (Time) o;
        return toMilliseconds() == time.toMilliseconds();
    }

    @Override
    public int hashCode() {
        return Objects.hash(toMilliseconds());
    }

    // ------------------------------------------------------------------------
    //  Factory
    // ------------------------------------------------------------------------

    /**
     * Creates a new {@link Time} of the given duration and {@link TimeUnit}.
     *
     * @param size The duration of time.
     * @param unit The unit of time of the duration, for example {@code TimeUnit.SECONDS}.
     * @return The time policy.
     */
    public static Time of(long size, TimeUnit unit) {
        return new Time(size, unit);
    }

    /** Creates a new {@link Time} that represents the given number of milliseconds. */
    public static Time milliseconds(long milliseconds) {
        return of(milliseconds, TimeUnit.MILLISECONDS);
    }

    /** Creates a new {@link Time} that represents the given number of seconds. */
    public static Time seconds(long seconds) {
        return of(seconds, TimeUnit.SECONDS);
    }

    /** Creates a new {@link Time} that represents the given number of minutes. */
    public static Time minutes(long minutes) {
        return of(minutes, TimeUnit.MINUTES);
    }

    /** Creates a new {@link Time} that represents the given number of hours. */
    public static Time hours(long hours) {
        return of(hours, TimeUnit.HOURS);
    }

    /** Creates a new {@link Time} that represents the given number of days. */
    public static Time days(long days) {
        return of(days, TimeUnit.DAYS);
    }

    /**
     * Creates a new {@link Time} that represents the number of milliseconds in the given duration.
     */
    public static Time fromDuration(Duration duration) {
        return milliseconds(duration.toMillis());
    }
}

十四、线程休眠工具类,封装逻辑.

线程休眠方式.

// 原生线程休眠
try {
   Thread.sleep(1000);
} catch (InterruptedException e) {
   e.printStackTrace();
}

并发工具包休眠方式

try {
    TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
    e.printStackTrace();
}
import com.boot.skywalk.exception.GlobalException;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 线程工具类封装,ThreadUtil
 */
@Slf4j
public final class ThreadUtil {
    /**
     * Number of milliseconds in a standard second.
     */
    public static final long MILLIS_PER_SECOND = 1000;
    /**
     * Number of milliseconds in a standard minute.
     */
    public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
    /**
     * Number of milliseconds in a standard hour.
     */
    public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
    /**
     * Number of milliseconds in a standard day.
     */
    public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;
    /**
     * 校验时间单位
     *
     * @param duration duration
     * @param unit unit
     */
    public static void checkDurationLength(long duration, TimeUnit unit){
        long durationSeconds = TimeUnit.MILLISECONDS.convert(duration, unit);
        if(durationSeconds<0||durationSeconds>MILLIS_PER_DAY){
            log.error("illegal duration time,duration={},unit={}",duration,unit);
            throw new GlobalException("duration time is illegal");
        }
    }

    /**
     * 毫秒级中断线程
     *
     * @param millSeconds
     */
    public static void pauseThreadMillSeconds(long millSeconds){
        pauseThread(millSeconds, TimeUnit.MILLISECONDS);
    }

    /**
     * 秒级中断线程
     *
     * @param seconds
     */
    public static void pauseThreadSeconds(long seconds){
        pauseThread(seconds, TimeUnit.SECONDS);
    }

    /**
     * 中断线程
     *
     * @param duration duration
     * @param unit unit
     */
    public static void pauseThread(long duration,TimeUnit unit){
        if(Objects.isNull(unit)){
            log.error("TimeUnit is null");
            throw new GlobalException("TimeUnit is null");
        }
        checkDurationLength(duration, unit);
        try {
            unit.sleep(duration);
        } catch (InterruptedException e) {
            log.error("pause thread fail,duration={},unit={}",duration,unit,e);
        }
    }

    // 使用
    public static void main(String[] args) {
        System.out.println("start");
        pauseThreadSeconds(10);
        System.out.println("end");
    }
}

Spring框架反射工具类使用:

 一般在Maven多模块调用解决循环依赖的时候可以通过反射调用即可.

package com.boot.skywalk.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * ReflectTest.
 */
@Slf4j
public class ReflectTest {
    /**
     * Reflect CLASS
     */
    private static final String MAP_CLASS="com.boot.skywalk.util.MapUtil";

    public static void main(String[] args) {
        Class<?> forName=null;
        try {
            forName=Class.forName(MAP_CLASS);
        } catch (ClassNotFoundException e) {
            log.error("reflect class error!", e);
        }
        Map<String,String> map=new HashMap<>();
        map.put("Single","Single-Value");
        // 反射调用
        Method method = ReflectionUtils.findMethod(forName, "getMap", Map.class);
        Map<String,String> resp=null;
        try {
            resp=(Map<String,String>)method.invoke(null, map);
        } catch (IllegalAccessException e) {
            log.error("IllegalAccessException",e);
        } catch (InvocationTargetException e) {
            log.error("InvocationTargetException",e);
        }
        System.out.println(resp);
    }
}

 源码介绍:

	public static Method findMethod(Class<?> clazz, String name, @Nullable Class<?>... paramTypes) {
		Assert.notNull(clazz, "Class must not be null");
		Assert.notNull(name, "Method name must not be null");
		Class<?> searchType = clazz;
		while (searchType != null) {
			Method[] methods = (searchType.isInterface() ? searchType.getMethods() :
					getDeclaredMethods(searchType, false));
			for (Method method : methods) {
				if (name.equals(method.getName()) && (paramTypes == null || hasSameParams(method, paramTypes))) {
					return method;
				}
			}
			searchType = searchType.getSuperclass();
		}
		return null;
	}

MyBatisPlus的反射工具类:

ReflectionKit工具类介绍:

package com.baomidou.mybatisplus.core.toolkit;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;

import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toMap;

/**
 * <p>
 * 反射工具类
 * </p>
 *
 * @author Caratacus
 * @since 2016-09-22
 */
public class ReflectionKit {

    private static final Log logger = LogFactory.getLog(ReflectionKit.class);
    /**
     * class field cache
     */
    private static final Map<Class<?>, List<Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap<>();

    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap<>(8);

    static {
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Boolean.class, boolean.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Byte.class, byte.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Character.class, char.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Double.class, double.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Float.class, float.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Integer.class, int.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Long.class, long.class);
        PRIMITIVE_WRAPPER_TYPE_MAP.put(Short.class, short.class);
    }

    /**
     * <p>
     * 反射 method 方法名,例如 getId
     * </p>
     *
     * @param field
     * @param str   属性字符串内容
     */
    public static String getMethodCapitalize(Field field, final String str) {
        Class<?> fieldType = field.getType();
        // fix #176
        return StringUtils.concatCapitalize(boolean.class.equals(fieldType) ? "is" : "get", str);
    }

    /**
     * <p>
     * 反射 method 方法名,例如 setVersion
     * </p>
     *
     * @param field Field
     * @param str   String JavaBean类的version属性名
     * @return version属性的setter方法名称,e.g. setVersion
     * @deprecated 3.0.8
     */
    @Deprecated
    public static String setMethodCapitalize(Field field, final String str) {
        return StringUtils.concatCapitalize("set", str);
    }

    /**
     * <p>
     * 获取 public get方法的值
     * </p>
     *
     * @param cls    ignore
     * @param entity 实体
     * @param str    属性字符串内容
     * @return Object
     */
    public static Object getMethodValue(Class<?> cls, Object entity, String str) {
        Map<String, Field> fieldMaps = getFieldMap(cls);
        try {
            Assert.notEmpty(fieldMaps, "Error: NoSuchField in %s for %s.  Cause:", cls.getSimpleName(), str);
            Method method = cls.getMethod(getMethodCapitalize(fieldMaps.get(str), str));
            return method.invoke(entity);
        } catch (NoSuchMethodException e) {
            throw ExceptionUtils.mpe("Error: NoSuchMethod in %s.  Cause:", e, cls.getSimpleName());
        } catch (IllegalAccessException e) {
            throw ExceptionUtils.mpe("Error: Cannot execute a private method. in %s.  Cause:", e, cls.getSimpleName());
        } catch (InvocationTargetException e) {
            throw ExceptionUtils.mpe("Error: InvocationTargetException on getMethodValue.  Cause:" + e);
        }
    }

    /**
     * <p>
     * 获取 public get方法的值
     * </p>
     *
     * @param entity 实体
     * @param str    属性字符串内容
     * @return Object
     */
    public static Object getMethodValue(Object entity, String str) {
        if (null == entity) {
            return null;
        }
        return getMethodValue(entity.getClass(), entity, str);
    }

    /**
     * <p>
     * 反射对象获取泛型
     * </p>
     *
     * @param clazz 对象
     * @param index 泛型所在位置
     * @return Class
     */
    public static Class<?> getSuperClassGenericType(final Class<?> clazz, final int index) {
        Type genType = clazz.getGenericSuperclass();
        if (!(genType instanceof ParameterizedType)) {
            logger.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
            return Object.class;
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        if (index >= params.length || index < 0) {
            logger.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index,
                clazz.getSimpleName(), params.length));
            return Object.class;
        }
        if (!(params[index] instanceof Class)) {
            logger.warn(String.format("Warn: %s not set the actual class on superclass generic parameter",
                clazz.getSimpleName()));
            return Object.class;
        }
        return (Class<?>) params[index];
    }

    /**
     * <p>
     * 获取该类的所有属性列表
     * </p>
     *
     * @param clazz 反射类
     */
    public static Map<String, Field> getFieldMap(Class<?> clazz) {
        List<Field> fieldList = getFieldList(clazz);
        return CollectionUtils.isNotEmpty(fieldList) ? fieldList.stream().collect(Collectors.toMap(Field::getName, field -> field)) : Collections.emptyMap();
    }

    /**
     * <p>
     * 获取该类的所有属性列表
     * </p>
     *
     * @param clazz 反射类
     */
    public static List<Field> getFieldList(Class<?> clazz) {
        if (Objects.isNull(clazz)) {
            return Collections.emptyList();
        }
        List<Field> fields = CLASS_FIELD_CACHE.get(clazz);
        if (CollectionUtils.isEmpty(fields)) {
            synchronized (CLASS_FIELD_CACHE) {
                fields = doGetFieldList(clazz);
                CLASS_FIELD_CACHE.put(clazz, fields);
            }
        }
        return fields;
    }

    /**
     * <p>
     * 获取该类的所有属性列表
     * </p>
     *
     * @param clazz 反射类
     */
    public static List<Field> doGetFieldList(Class<?> clazz) {
        if (clazz.getSuperclass() != null) {
            /* 排除重载属性 */
            Map<String, Field> fieldMap = excludeOverrideSuperField(clazz.getDeclaredFields(),
                /* 处理父类字段 */
                getFieldList(clazz.getSuperclass()));
            List<Field> fieldList = new ArrayList<>();
            /*
             * 重写父类属性过滤后处理忽略部分,支持过滤父类属性功能
             * 场景:中间表不需要记录创建时间,忽略父类 createTime 公共属性
             * 中间表实体重写父类属性 ` private transient Date createTime; `
             */
            fieldMap.forEach((k, v) -> {
                /* 过滤静态属性 */
                if (!Modifier.isStatic(v.getModifiers())
                    /* 过滤 transient关键字修饰的属性 */
                    && !Modifier.isTransient(v.getModifiers())) {
                    fieldList.add(v);
                }
            });
            return fieldList;
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * <p>
     * 排序重置父类属性
     * </p>
     *
     * @param fields         子类属性
     * @param superFieldList 父类属性
     */
    public static Map<String, Field> excludeOverrideSuperField(Field[] fields, List<Field> superFieldList) {
        // 子类属性
        Map<String, Field> fieldMap = Stream.of(fields).collect(toMap(Field::getName, identity()));
        superFieldList.stream().filter(field -> !fieldMap.containsKey(field.getName()))
            .forEach(f -> fieldMap.put(f.getName(), f));
        return fieldMap;
    }

    /**
     * 获取字段get方法
     *
     * @param cls   class
     * @param field 字段
     * @return Get方法
     */
    public static Method getMethod(Class<?> cls, Field field) {
        try {
            return cls.getDeclaredMethod(ReflectionKit.getMethodCapitalize(field, field.getName()));
        } catch (NoSuchMethodException e) {
            throw ExceptionUtils.mpe("Error: NoSuchMethod in %s.  Cause:", e, cls.getName());
        }
    }

    /**
     * 判断是否为基本类型或基本包装类型
     *
     * @param clazz class
     * @return 是否基本类型或基本包装类型
     */
    public static boolean isPrimitiveOrWrapper(Class<?> clazz) {
        Assert.notNull(clazz, "Class must not be null");
        return (clazz.isPrimitive() || PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(clazz));
    }
}
List<Field> fieldList = ReflectionKit.getFieldList(ReflectTest.class);
System.out.println(fieldList);

异常堆栈信息打印:

package com.boot.skywalk.vo;

import java.util.LinkedHashMap;
import java.util.Map;

public class ExceptionUtil {
    public static void main(String[] args) {
        try{
            int num=1/0;
        }catch (ArithmeticException e){
            System.out.println(recordExceptionMap(e));
        }
    }

    /**
     * 记录Exception堆栈信息
     *
     * @param exception
     * @return Map<String,Object>
     */
    public static Map<String,Object> recordExceptionMap(Exception exception){
        Map<String,Object> map=new LinkedHashMap<>();
        StackTraceElement stackTraceElement = exception.getStackTrace()[0];
        map.put("class_name",stackTraceElement.getClassName());
        map.put("file_name",stackTraceElement.getFileName());
        map.put("method_name",stackTraceElement.getMethodName());
        map.put("line_number",stackTraceElement.getLineNumber());
        return map;
    }
}

Stream的静态方法,流的特点:无法重复消费、不存放数据、不改变数据源,具有延迟性,只有终端执行操作了,中间才会执行.

        // Stream的静态方法
        Stream<Integer> stream0 = Stream.of(7, 8, 9, 10, 11);
        Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6);
        // 合并流
        Stream<Integer> concatStream = Stream.concat(stream0, stream1);
        concatStream.forEach(System.out::println);
        // 迭代无限流
        Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
        stream2.forEach(System.out::println);
        // 生产无限流
        Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
        stream3.forEach(System.out::println);

Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合

分区和分组区别:主要是看函数式接口,Function和Predicate

    public static <T>
    Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
        return partitioningBy(predicate, toList());
    }
    public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                          Collector<? super T, A, D> downstream) {
        return groupingBy(classifier, HashMap::new, downstream);
    }

 常用总结:

toMap-->stream转为map
Function.identity()-->返回stream中的元素
集合-->Stream:stream()
数组-->Stream:Stream.of(T t)或者Arrays.stream(T[] t)
任意元素-->Stream:Stream.of(T... values)
归约:是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

获取字符串最大长度

    public static void getMaxStr(){
        List<String> list = Arrays.asList("abb", "abcd", "fegc", "efe", "adfes");
        // 最长字符串长度
        int maxLength = list.stream().filter(s -> s.startsWith("a")).mapToInt(r -> r.length()).max().orElse(0);
        System.out.println(maxLength);
        // 最长字符串
        Optional<String> optional = list.stream().filter(s -> s.startsWith("a")).max(Comparator.comparing(String::length));
        String string = Optional.ofNullable(optional.get()).orElse("");
        System.out.println(string);
    }

对象属性求和

    /**
     * Stream计算属性和
     * @return int
     */
    public static int getSum(){
        Student s1 = new Student("张一",5);
        Student s2 = new Student("张二",3);
        Student s3 = new Student("张三",4);
        Student s4 = new Student("张四",1);
        List<Student> list=new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        // 计算属性和:返回一个IntStream其中包含给定函数应用于此流得元素的结果
        int sum = list.stream().mapToInt(o -> Objects.isNull(o.getAge()) ? 0 : o.getAge()).sum();
        List<Integer> ageList = list.stream().map(o -> Objects.isNull(o.getAge()) ? 0 : o.getAge()).collect(Collectors.toList());
        // reduce规约计算
        Optional<Integer> result = ageList.stream().reduce(Integer::sum);
        System.out.println(result.get());
        return sum;
    }

BIO流读取:

①、字节流读取

    /**
     * 通过字节流实现文件复制:FileInputStream/FileOutputStream
     */
    public static void writeByInputStream(){
        //使用 jdk7 引入的自动关闭资源的 try 语句(该资源类要实现 AutoCloseable 或 Closeable 接口)
        try (FileInputStream fis = new FileInputStream("D:\\红色电视剧.txt");
             FileOutputStream fos = new FileOutputStream("D:\\红色电视剧_copy.txt")) {
            byte[] buf = new byte[126];
            int hasRead = 0;
            while ((hasRead = fis.read(buf)) > 0) {
                //每次读取多少就写多少
                fos.write(buf, 0, hasRead);
            }
        } catch (Exception e) {
            log.error("write error", e);
        }
    }

②、字符流读取

    /**
     * 通过字符流读取:FileReader/FileWriter
     */
    public static void writeByReader(){
        //使用 jdk7 引入的自动关闭资源的 try 语句
        try (FileReader fr = new FileReader("D:\\红色电视剧.txt");
             FileWriter fw = new FileWriter("D:\\红色电视剧_copy1.txt")) {
            char[] buf = new char[126];
            int hasRead = 0;
            while ((hasRead = fr.read(buf)) > 0) {
                //每次读取多少就写多少
                fw.write(buf, 0, hasRead);
            }
        } catch (Exception e){
            log.error("write error", e);
        }
    }

③、字符缓存流,按照行读取

    /**
     * 通过字符缓存流读取:BufferedReader/BufferedWriter
     */
    public static void writeByBufferReader(){
        //使用普通的 Reader 不方便整行读取,可以使用 BufferReader 包装,资源变量要定义在 try()中,否则不会自动关闭
        try (FileReader fr = new FileReader("D:\\红色电视剧.txt");
             FileWriter fw = new FileWriter("D:\\红色电视剧_copy2.txt");
             // 装饰缓存流
             BufferedReader bufferedReader = new BufferedReader(fr);
             BufferedWriter bufferedWriter = new BufferedWriter(fw)) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                //每次读取一行、写入一行
                bufferedWriter.write(line);
                bufferedWriter.newLine();
            }
        } catch (Exception e) {
            log.error("write error", e);
        }
    }

Bean和Map的工具类封装,基于cglib包实现.

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>3.3.0</version>
        </dependency>

 Mybatis-Plus框架封装BeanUtils工具类

package com.baomidou.mybatisplus.core.toolkit;

import static java.util.stream.Collectors.toList;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import net.sf.cglib.beans.BeanMap;

/**
 * Bean 转换工具类
 * <p>使用请依赖 cglib 包</p>
 *
 * @author hubin HCL
 * @since 2018-06-12
 */
public final class BeanUtils {

    private BeanUtils() {
    }

    /**
     * 将对象装换为 map,对象转成 map,key肯定是字符串
     *
     * @param bean 转换对象
     * @return 返回转换后的 map 对象
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> beanToMap(Object bean) {
        return null == bean ? null : BeanMap.create(bean);
    }

    /**
     * map 装换为 java bean 对象
     *
     * @param map   转换 MAP
     * @param clazz 对象 Class
     * @return 返回 bean 对象
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {
        T bean = ClassUtils.newInstance(clazz);
        BeanMap.create(bean).putAll(map);
        return bean;
    }

    /**
     * List&lt;T&gt; 转换为 List&lt;Map&lt;String, Object&gt;&gt;
     *
     * @param beans 转换对象集合
     * @return 返回转换后的 bean 列表
     */
    public static <T> List<Map<String, Object>> beansToMaps(List<T> beans) {
        if (CollectionUtils.isEmpty(beans)) {
            return Collections.emptyList();
        }
        return beans.stream().map(BeanUtils::beanToMap).collect(toList());
    }

    /**
     * List&lt;Map&lt;String, Object&gt;&gt; 转换为 List&lt;T&gt;
     *
     * @param maps  转换 MAP 集合
     * @param clazz 对象 Class
     * @return 返回转换后的 bean 集合
     */
    public static <T> List<T> mapsToBeans(List<Map<String, Object>> maps, Class<T> clazz) {
        if (CollectionUtils.isEmpty(maps)) {
            return Collections.emptyList();
        }
        return maps.stream().map(e -> mapToBean(e, clazz)).collect(toList());
    }
}

测试一下工具:

    /**
     * 测试Bean转换Map
     * @return Map<String, Object>
     */
    public static Map<String, Object> beanToMapTest(){
        Student s1 = new Student("张一",5);
        Map<String, Object> map = beanToMap(s1);
        return map;
    }

    /**
     * 测试List<Bean>转换List<Map>
     * @return Map<String, Object>
     */
    public static List<Map<String, Object>> beanListToMapTest(){
        Student s1 = new Student("张一",5);
        Student s2 = new Student("张二",4);
        Student s3 = new Student("张三",3);
        Student s4 = new Student("张四",2);
        Student s5 = new Student(null,1);
        List<Student> list=new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        list.add(s5);
        List<Map<String, Object>> maps = beansToMaps(list);
        return maps;
    }
    public static void main(String[] args) {
        Map<String, Object> map = beanToMapTest();
        System.out.println("Bean转换Map:"+map);
        Student student = mapToBean(map, Student.class);
        System.out.println("Map转换Bean"+student);
        List<Map<String, Object>> list = beanListToMapTest();
        System.out.println("ListBean转换ListMap"+list);
        List<Student> studentList = mapsToBeans(list, Student.class);
        System.out.println("ListMap转换ListBean"+studentList);
    }

十五、并发测试工具类

1、开源的HuTool测试工具类.

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.8.6</version>
        </dependency>
package com.boot.skywalk;

import cn.hutool.core.thread.ConcurrencyTester;
import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Hutool并发工具类测试
 */
@Slf4j
public class ConcurrentTest {

    private static final Map<String, List<Integer>> MAP = new HashMap<>();

    private static final Map<String, List<Integer>> CONCURRENTHASH_MAP = new ConcurrentHashMap<>();

    public static void main(String[] args) throws IOException {
        // 1、定义多少个线程,这里是100个并发,每个执行业务逻辑是循环计算
        ConcurrencyTester concurrencyTester = ThreadUtil.concurrencyTest(100, new Runnable() {
            @Override
            public void run() {
                List<Integer> list = IntStream.range(1, 1001).boxed().collect(Collectors.toList());
                for(int i=0;i<100;i++){
                    MAP.put(Thread.currentThread().getName()+"-"+i, list);
                    CONCURRENTHASH_MAP.put(Thread.currentThread().getName()+"-"+i, list);
                }
            }
        });
        //MAP.forEach((key, value) -> {
        //    log.info("key={},value={}", key, value);
        //});
        log.info("total HashMap size={},ConcurrentHashMap size={}",MAP.size(),CONCURRENTHASH_MAP.size());
        log.info("total cost time={}", concurrencyTester.getInterval()+"ms");
        // 2、关闭
        concurrencyTester.close();
    }
}

同时验证HashMap是线程不安全的.

源码也是比较简单的,ExecutorService+CountDownLatch

package cn.hutool.core.thread;

import cn.hutool.core.exceptions.UtilException;

import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

/**
 * 线程同步结束器<br>
 * 在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
 *
 * <pre>
 * ps:
 * //模拟1000个线程并发
 * SyncFinisher sf = new SyncFinisher(1000);
 * sf.addWorker(() -&gt; {
 *      // 需要并发测试的业务代码
 * });
 * sf.start()
 * </pre>
 *
 *
 * @author Looly
 * @since 4.1.15
 */
public class SyncFinisher implements Closeable {

	private final Set<Worker> workers;
	private final int threadSize;
	private ExecutorService executorService;

	private boolean isBeginAtSameTime;
	/** 启动同步器,用于保证所有worker线程同时开始 */
	private final CountDownLatch beginLatch;
	/** 结束同步器,用于等待所有worker线程同时结束 */
	private CountDownLatch endLatch;

	/**
	 * 构造
	 *
	 * @param threadSize 线程数
	 */
	public SyncFinisher(int threadSize) {
		this.beginLatch = new CountDownLatch(1);
		this.threadSize = threadSize;
		this.workers = new LinkedHashSet<>();
	}

	/**
	 * 设置是否所有worker线程同时开始
	 *
	 * @param isBeginAtSameTime 是否所有worker线程同时开始
	 * @return this
	 */
	public SyncFinisher setBeginAtSameTime(boolean isBeginAtSameTime) {
		this.isBeginAtSameTime = isBeginAtSameTime;
		return this;
	}

	/**
	 * 增加定义的线程数同等数量的worker
	 *
	 * @param runnable 工作线程
	 * @return this
	 */
	public SyncFinisher addRepeatWorker(final Runnable runnable) {
		for (int i = 0; i < this.threadSize; i++) {
			addWorker(new Worker() {
				@Override
				public void work() {
					runnable.run();
				}
			});
		}
		return this;
	}

	/**
	 * 增加工作线程
	 *
	 * @param runnable 工作线程
	 * @return this
	 */
	public SyncFinisher addWorker(final Runnable runnable) {
		return addWorker(new Worker() {
			@Override
			public void work() {
				runnable.run();
			}
		});
	}

	/**
	 * 增加工作线程
	 *
	 * @param worker 工作线程
	 * @return this
	 */
	synchronized public SyncFinisher addWorker(Worker worker) {
		workers.add(worker);
		return this;
	}

	/**
	 * 开始工作<br>
	 * 执行此方法后如果不再重复使用此对象,需调用{@link #stop()}关闭回收资源。
	 */
	public void start() {
		start(true);
	}

	/**
	 * 开始工作<br>
	 * 执行此方法后如果不再重复使用此对象,需调用{@link #stop()}关闭回收资源。
	 *
	 * @param sync 是否阻塞等待
	 * @since 4.5.8
	 */
	public void start(boolean sync) {
		endLatch = new CountDownLatch(workers.size());

		if(null == this.executorService || this.executorService.isShutdown()){
			this.executorService = ThreadUtil.newExecutor(threadSize);
		}
		for (Worker worker : workers) {
			executorService.submit(worker);
		}
		// 保证所有worker同时开始
		this.beginLatch.countDown();

		if (sync) {
			try {
				this.endLatch.await();
			} catch (InterruptedException e) {
				throw new UtilException(e);
			}
		}
	}

	/**
	 * 结束线程池。此方法执行两种情况:
	 * <ol>
	 *     <li>执行start(true)后,调用此方法结束线程池回收资源</li>
	 *     <li>执行start(false)后,用户自行判断结束点执行此方法</li>
	 * </ol>
	 *
	 * @since 5.6.6
	 */
	public void stop(){
		if(null != this.executorService){
			this.executorService.shutdown();
		}
		this.executorService = null;

		clearWorker();
	}

	/**
	 * 清空工作线程对象
	 */
	public void clearWorker() {
		workers.clear();
	}

	/**
	 * 剩余任务数
	 *
	 * @return 剩余任务数
	 */
	public long count() {
		return endLatch.getCount();
	}

	@Override
	public void close() throws IOException {
		stop();
	}

	/**
	 * 工作者,为一个线程
	 *
	 * @author xiaoleilu
	 *
	 */
	public abstract class Worker implements Runnable {

		@Override
		public void run() {
			if (isBeginAtSameTime) {
				try {
					beginLatch.await();
				} catch (InterruptedException e) {
					throw new UtilException(e);
				}
			}
			try {
				work();
			} finally {
				endLatch.countDown();
			}
		}

		/**
		 * 任务内容
		 */
		public abstract void work();
	}
}

2、自定义

    public static void concurrencyTest(){
        concurrencyExecute(100, ()->{
            List<Integer> list = IntStream.range(1, 1001).boxed().collect(Collectors.toList());
            for(int i=0;i<100;i++){
                MAP.put(Thread.currentThread().getName()+"-"+i, list);
                CONCURRENTHASH_MAP.put(Thread.currentThread().getName()+"-"+i, list);
            }
            return null;
        });
        log.info("total HashMap size={},ConcurrentHashMap size={}",MAP.size(),CONCURRENTHASH_MAP.size());
    }

    public static <T> T concurrencyExecute(int threadNumber, Supplier<T> supplier) {
        CountDownLatch start = new CountDownLatch(1);
        CountDownLatch end = new CountDownLatch(threadNumber);
        ExecutorService executorService = Executors.newFixedThreadPool(threadNumber);
        T object = null;
        for (int i = 0; i < threadNumber; i++) {
            executorService.submit(() -> {
                try {
                    // 1、先阻塞这别让这个线程跑起来
                    start.await();
                    // 具体的业务方法(本地方法 or 远程调用)
                    supplier.get();
                } catch (InterruptedException e) {
                    log.error("error message",e);
                    Thread.currentThread().interrupt();
                } finally {
                    // 一个线程跑完 end计数器-1
                    end.countDown();
                }
            });
        }
        // start-1 所有线程启动,同时进行业务计算
        start.countDown();
        // 阻塞直到所有线程执行完毕
        try {
            end.await();
        } catch (InterruptedException e) {
            log.error("error message",e);
            Thread.currentThread().interrupt();
        }
        executorService.shutdown();
        return object;
    }

十六、MyBatis的防止SQL注入写法.

   1、in查询写法

   错误写法:不是用$替换

Select * from news where id in (#{ids})

  正确写法: 

    <!-- in查询写法-->
    <select id="queryListByIds" resultType="com.boot.skywalk.entity.UserInfo">
        SELECT * from user_info where create_time>#{createTime} and id in
        <foreach collection="list" item="idItem" open="(" close=")" separator="," >
            #{idItem}
        </foreach>
    </select>

  2、like模糊查询写法

 错误写法:

Select * from news where title like ‘%#{title}%’

正确写法: 

    <!--左匹配和右匹配 -->
<!--    select * from user_info where user_name like concat('%',#{userName},'%')-->
    <select id="queryListByUserName" resultType="com.boot.skywalk.entity.UserInfo">
        select * from user_info where user_name like concat(#{userName},'%')
    </select>

 借助ConcurrentHashMap封装一个ConcurrentHashSet.参考Dubbo的实现.

package org.apache.dubbo.common.utils;

import java.util.AbstractSet;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class ConcurrentHashSet<E> extends AbstractSet<E> implements Set<E>, java.io.Serializable {

    private static final long serialVersionUID = -8672117787651310382L;

    private static final Object PRESENT = new Object();

    private final ConcurrentMap<E, Object> map;

    public ConcurrentHashSet() {
        map = new ConcurrentHashMap<E, Object>();
    }

    public ConcurrentHashSet(int initialCapacity) {
        map = new ConcurrentHashMap<E, Object>(initialCapacity);
    }

    /**
     * Returns an iterator over the elements in this set. The elements are
     * returned in no particular order.
     *
     * @return an Iterator over the elements in this set
     * @see ConcurrentModificationException
     */
    @Override
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

    /**
     * Returns the number of elements in this set (its cardinality).
     *
     * @return the number of elements in this set (its cardinality)
     */
    @Override
    public int size() {
        return map.size();
    }

    /**
     * Returns <tt>true</tt> if this set contains no elements.
     *
     * @return <tt>true</tt> if this set contains no elements
     */
    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    /**
     * Returns <tt>true</tt> if this set contains the specified element. More
     * formally, returns <tt>true</tt> if and only if this set contains an
     * element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this set is to be tested
     * @return <tt>true</tt> if this set contains the specified element
     */
    @Override
    public boolean contains(Object o) {
        return map.containsKey(o);
    }

    /**
     * Adds the specified element to this set if it is not already present. More
     * formally, adds the specified element <tt>e</tt> to this set if this set
     * contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>. If this
     * set already contains the element, the call leaves the set unchanged and
     * returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    @Override
    public boolean add(E e) {
        return map.put(e, PRESENT) == null;
    }

    /**
     * Removes the specified element from this set if it is present. More
     * formally, removes an element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>, if this
     * set contains such an element. Returns <tt>true</tt> if this set contained
     * the element (or equivalently, if this set changed as a result of the
     * call). (This set will not contain the element once the call returns.)
     *
     * @param o object to be removed from this set, if present
     * @return <tt>true</tt> if the set contained the specified element
     */
    @Override
    public boolean remove(Object o) {
        return map.remove(o) == PRESENT;
    }

    /**
     * Removes all of the elements from this set. The set will be empty after
     * this call returns.
     */
    @Override
    public void clear() {
        map.clear();
    }

}

十七、时间格式转换

yyyy-MM-dd'T'HH:mm:ss.SSSXXX转换yyyy-MM-dd HH:mm:ss
yyyy-MM-dd'T'HH:mm:ss.SSSZ转换yyyy-MM-dd HH:mm:ss
    /**
     * 时间转换Z表示时区,RFC 822时区
     * @param date
     * @return
     */
    private static String formateUtcRfc(Date date){
        String format="yyyy-MM-dd'T'HH:mm:ss.SSSZ";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        String result = simpleDateFormat.format(date);
        System.out.println(result);
        return result;
    }

    /**
     * 时间转换Z表示时区,ISO 8601时区
     * @param date
     * @return
     */
    private static String formateUtcIso(Date date){
        String format="yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        String result = simpleDateFormat.format(date);
        System.out.println(result);
        return result;
    }

    /**
     * yyyy-MM-dd'T'HH:mm:ss.SSSZ转换yyyy-MM-dd HH:mm:ss
     * 2022-11-07T20:50:15.144+08:00转换2022-11-07 20:51:51
     * SSS表示毫秒
     * Z表示时区
     */
    private static void toUtcRfcString(){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date=null;
        try {
            date = simpleDateFormat.parse(formateUtcRfc(new Date()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(simpleDateFormat1.format(date));
    }

    /**
     * yyyy-MM-dd'T'HH:mm:ss.SSSXXX转换yyyy-MM-dd HH:mm:ss
     * 2022-11-07T20:51:51.704+0800转换2022-11-07 20:51:51
     * SSS表示毫秒
     * XXX表示时区时间格式
     */
    private static void toUtcIsoString(){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date=null;
        try {
            date = simpleDateFormat.parse(formateUtcIso(new Date()));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(simpleDateFormat1.format(date));
    }

	private static final Map<ISO, String> ISO_PATTERNS;

	static {
		Map<ISO, String> formats = new EnumMap<>(ISO.class);
		formats.put(ISO.DATE, "yyyy-MM-dd");
		formats.put(ISO.TIME, "HH:mm:ss.SSSXXX");
		formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
		ISO_PATTERNS = Collections.unmodifiableMap(formats);
	}
public enum DateField {

	/**
	 * 世纪
	 *
	 * @see Calendar#ERA
	 */
	ERA(Calendar.ERA),
	/**
	 * 年
	 *
	 * @see Calendar#YEAR
	 */
	YEAR(Calendar.YEAR),
	/**
	 * 月
	 *
	 * @see Calendar#MONTH
	 */
	MONTH(Calendar.MONTH),
	/**
	 * 一年中第几周
	 *
	 * @see Calendar#WEEK_OF_YEAR
	 */
	WEEK_OF_YEAR(Calendar.WEEK_OF_YEAR),
	/**
	 * 一月中第几周
	 *
	 * @see Calendar#WEEK_OF_MONTH
	 */
	WEEK_OF_MONTH(Calendar.WEEK_OF_MONTH),
	/**
	 * 一月中的第几天
	 *
	 * @see Calendar#DAY_OF_MONTH
	 */
	DAY_OF_MONTH(Calendar.DAY_OF_MONTH),
	/**
	 * 一年中的第几天
	 *
	 * @see Calendar#DAY_OF_YEAR
	 */
	DAY_OF_YEAR(Calendar.DAY_OF_YEAR),
	/**
	 * 周几,1表示周日,2表示周一
	 *
	 * @see Calendar#DAY_OF_WEEK
	 */
	DAY_OF_WEEK(Calendar.DAY_OF_WEEK),
	/**
	 * 天所在的周是这个月的第几周
	 *
	 * @see Calendar#DAY_OF_WEEK_IN_MONTH
	 */
	DAY_OF_WEEK_IN_MONTH(Calendar.DAY_OF_WEEK_IN_MONTH),
	/**
	 * 上午或者下午
	 *
	 * @see Calendar#AM_PM
	 */
	AM_PM(Calendar.AM_PM),
	/**
	 * 小时,用于12小时制
	 *
	 * @see Calendar#HOUR
	 */
	HOUR(Calendar.HOUR),
	/**
	 * 小时,用于24小时制
	 *
	 * @see Calendar#HOUR
	 */
	HOUR_OF_DAY(Calendar.HOUR_OF_DAY),
	/**
	 * 分钟
	 *
	 * @see Calendar#MINUTE
	 */
	MINUTE(Calendar.MINUTE),
	/**
	 * 秒
	 *
	 * @see Calendar#SECOND
	 */
	SECOND(Calendar.SECOND),
	/**
	 * 毫秒
	 *
	 * @see Calendar#MILLISECOND
	 */
	MILLISECOND(Calendar.MILLISECOND);

	// ---------------------------------------------------------------
	private final int value;

	DateField(int value) {
		this.value = value;
	}

	public int getValue() {
		return this.value;
	}

	/**
	 * 将 {@link Calendar}相关值转换为DatePart枚举对象<br>
	 *
	 * @param calendarPartIntValue Calendar中关于Week的int值
	 * @return DateField
	 */
	public static DateField of(int calendarPartIntValue) {
		switch (calendarPartIntValue) {
		case Calendar.ERA:
			return ERA;
		case Calendar.YEAR:
			return YEAR;
		case Calendar.MONTH:
			return MONTH;
		case Calendar.WEEK_OF_YEAR:
			return WEEK_OF_YEAR;
		case Calendar.WEEK_OF_MONTH:
			return WEEK_OF_MONTH;
		case Calendar.DAY_OF_MONTH:
			return DAY_OF_MONTH;
		case Calendar.DAY_OF_YEAR:
			return DAY_OF_YEAR;
		case Calendar.DAY_OF_WEEK:
			return DAY_OF_WEEK;
		case Calendar.DAY_OF_WEEK_IN_MONTH:
			return DAY_OF_WEEK_IN_MONTH;
		case Calendar.AM_PM:
			return AM_PM;
		case Calendar.HOUR:
			return HOUR;
		case Calendar.HOUR_OF_DAY:
			return HOUR_OF_DAY;
		case Calendar.MINUTE:
			return MINUTE;
		case Calendar.SECOND:
			return SECOND;
		case Calendar.MILLISECOND:
			return MILLISECOND;
		default:
			return null;
		}
	}
}

十八、FastJson中Json数组转换List<T>

class Function{
    private String functionId;
    private Boolean needBuy;
    private String functionName;

    public Function(){
    }

    public Function(String functionId, Boolean needBuy, String functionName) {
        this.functionId = functionId;
        this.needBuy = needBuy;
        this.functionName = functionName;
    }

    public String getFunctionId() {
        return functionId;
    }

    public void setFunctionId(String functionId) {
        this.functionId = functionId;
    }

    public Boolean getNeedBuy() {
        return needBuy;
    }

    public void setNeedBuy(Boolean needBuy) {
        this.needBuy = needBuy;
    }

    public String getFunctionName() {
        return functionName;
    }

    public void setFunctionName(String functionName) {
        this.functionName = functionName;
    }

    @Override
    public String toString() {
        return "Function{" +
                "functionId='" + functionId + '\'' +
                ", needBuy=" + needBuy +
                ", functionName='" + functionName + '\'' +
                '}';
    }
}
String jsonStr= "[{\"functionId\":\"14\",\"needBuy\":false,\"functionName\":\"功能1\"},{\"functionId\":\"17\",\"needBuy\":false,\"functionName\":\"功能2\"}]";        
// JSONArray转换List<T>
List<Function> functions = JSON.parseArray(jsonStr, Function.class);
// JSONObject实现
List<Function> list = jsonArray.stream().map(item -> {
            Function function = JSONObject.parseObject(JSONObject.toJSONString(item), Function.class);
            return function;
}).collect(Collectors.toList());
              

Idea将字符串转化为JSON字符串的方式 :鼠标放在括号内,然后Alt+Enter即可看到编辑.

十九、时间月份增加或者减少

 主要使用java8的LocalDate.now().plusMonths

    /**
     * 默认是增加月份
     *
     * @param num
     * @return
     */
    private static List<String> getRangDateMonthList(int num){
        return getRangDateMonthList(num,true);
    }

    /**
     * 返回指定月份的集合
     * @param num 月份
     * @param status 状态,true为增加,false为减少
     * @return
     */
    private static List<String> getRangDateMonthList(int num,boolean status){
        if(num<=0){
            return Collections.emptyList();
        }
        List<String> list=new ArrayList<>();
        for(int i=0;i<num;i++){
            long plus=i;
            if(!status){
                plus=Long.parseLong("-"+i);
            }
            list.add(LocalDate.now().plusMonths(plus).toString().substring(0,7));
        }
        return list;
    }

二十、函数式接口的封装使用

     1、定义函数式接口

package com.boot.skywalk.task;
/**
 * 通用数据清理任务接口
 */
@FunctionalInterface
public interface ICleanData {
    /**
     * 清理数据
     */
    void cleanData();
}
package com.boot.skywalk.task;
/**
 * 通用检验
 * @param <T>
 */
@FunctionalInterface
public interface ICheck<T> {
    /**
     * 通用检验
     * @param t
     */
    void check(T t);
}

   Dubbo中的检验,可以扩展为函数式接口

package org.apache.dubbo.common.status;

import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;

/**
 * StatusChecker
 */
@SPI(scope = ExtensionScope.APPLICATION)
public interface StatusChecker {

    /**
     * check status
     *
     * @return status
     */
    Status check();

}

   定时任务上传采集数据

import org.apache.dubbo.common.extension.SPI;

@SPI
public interface Merger<T> {

    T merge(T... items);

}

 

package org.apache.dubbo.rpc.cluster.merger;

import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.rpc.cluster.Merger;

import java.util.Arrays;
import java.util.Objects;

public class IntArrayMerger implements Merger<int[]> {

    @Override
    public int[] merge(int[]... items) {
        if (ArrayUtils.isEmpty(items)) {
            return new int[0];
        }
        return Arrays.stream(items).filter(Objects::nonNull)
                .flatMapToInt(Arrays::stream)
                .toArray();
    }

}

计算机存储空间

    /**
     * 计算Windows机器磁盘信息
     *
     * @param path
     * @return
     */
    public static String getFileSpace(String path){
        if(StringUtils.isBlank(path)){
            throw new IllegalArgumentException("path is null");
        }
        File file = new File(path+File.separator);
        // 单位是B
        long freeSpace = file.getFreeSpace();
        long totalSpace = file.getTotalSpace();
        long usableSpace = file.getUsableSpace();
        long usedSpace = totalSpace-usableSpace;
        StringJoiner stringJoiner = new StringJoiner(",","[","]");
        stringJoiner.add("空闲空间:"+freeSpace/1024/1024/1024+"GB")
                .add("总空间:"+totalSpace/1024/1024/1024+"GB")
                .add("可用空间:"+usableSpace/1024/1024/1024+"GB")
                .add("已用空间:"+usedSpace/1024/1024/1024+"GB");
        return stringJoiner.toString();
    }

二十一 自定义实现栈

package com.alibaba.dubbo.common.utils;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.List;

/**
 * Stack.
 */

public class Stack<E> {
    private int mSize = 0;

    private List<E> mElements = new ArrayList<E>();

    public Stack() {
    }

    /**
     * push.
     *
     * @param ele
     */
    public void push(E ele) {
        if (mElements.size() > mSize)
            mElements.set(mSize, ele);
        else
            mElements.add(ele);
        mSize++;
    }

    /**
     * pop.
     *
     * @return the last element.
     */
    public E pop() {
        if (mSize == 0)
            throw new EmptyStackException();
        return mElements.set(--mSize, null);
    }

    /**
     * peek.
     *
     * @return the last element.
     */
    public E peek() {
        if (mSize == 0)
            throw new EmptyStackException();
        return mElements.get(mSize - 1);
    }

    /**
     * get.
     *
     * @param index index.
     * @return element.
     */
    public E get(int index) {
        if (index >= mSize)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mSize);

        return index < 0 ? mElements.get(index + mSize) : mElements.get(index);
    }

    /**
     * set.
     *
     * @param index index.
     * @param value element.
     * @return old element.
     */
    public E set(int index, E value) {
        if (index >= mSize)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mSize);

        return mElements.set(index < 0 ? index + mSize : index, value);
    }

    /**
     * remove.
     *
     * @param index
     * @return element
     */
    public E remove(int index) {
        if (index >= mSize)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mSize);

        E ret = mElements.remove(index < 0 ? index + mSize : index);
        mSize--;
        return ret;
    }

    /**
     * get stack size.
     *
     * @return size.
     */
    public int size() {
        return mSize;
    }

    /**
     * is empty.
     *
     * @return empty or not.
     */
    public boolean isEmpty() {
        return mSize == 0;
    }

    /**
     * clear stack.
     */
    public void clear() {
        mSize = 0;
        mElements.clear();
    }
}

二十二、多种Json框架解析适配,看dubbo的框架代码

1、定义JSON接口,【常用业务方法】

public interface JSON {
    boolean isSupport();

    <T> T toJavaObject(String json, Type type);

    <T> List<T> toJavaList(String json, Class<T> clazz);

    String toJson(Object obj);

    List<?> getList(Map<String, ?> obj, String key);

    List<Map<String, ?>> getListOfObjects(Map<String, ?> obj, String key);

    List<String> getListOfStrings(Map<String, ?> obj, String key);

    Map<String, ?> getObject(Map<String, ?> obj, String key);

    Double getNumberAsDouble(Map<String, ?> obj, String key);

    Integer getNumberAsInteger(Map<String, ?> obj, String key);

    Long getNumberAsLong(Map<String, ?> obj, String key);

    String getString(Map<String, ?> obj, String key);

    List<Map<String, ?>> checkObjectList(List<?> rawList);

    List<String> checkStringList(List<?> rawList);

}

 2、AbstractJSONImpl【常用的类型转换校验】

package org.apache.dubbo.common.json.impl;

import org.apache.dubbo.common.json.JSON;

import java.util.List;
import java.util.Map;

public abstract class AbstractJSONImpl implements JSON {

    @Override
    public List<?> getList(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (!(value instanceof List)) {
            throw new ClassCastException(
                String.format("value '%s' for key '%s' in '%s' is not List", value, key, obj));
        }
        return (List<?>) value;
    }

    /**
     * Gets a list from an object for the given key, and verifies all entries are objects.  If the key
     * is not present, this returns null.  If the value is not a List or an entry is not an object,
     * throws an exception.
     */
    @Override
    public List<Map<String, ?>> getListOfObjects(Map<String, ?> obj, String key) {
        assert obj != null;
        List<?> list = getList(obj, key);
        if (list == null) {
            return null;
        }
        return checkObjectList(list);
    }

    /**
     * Gets a list from an object for the given key, and verifies all entries are strings.  If the key
     * is not present, this returns null.  If the value is not a List or an entry is not a string,
     * throws an exception.
     */
    @Override
    public List<String> getListOfStrings(Map<String, ?> obj, String key) {
        assert obj != null;
        List<?> list = getList(obj, key);
        if (list == null) {
            return null;
        }
        return checkStringList(list);
    }

    /**
     * Gets an object from an object for the given key.  If the key is not present, this returns null.
     * If the value is not a Map, throws an exception.
     */
    @SuppressWarnings("unchecked")
    @Override
    public Map<String, ?> getObject(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (!(value instanceof Map)) {
            throw new ClassCastException(
                String.format("value '%s' for key '%s' in '%s' is not object", value, key, obj));
        }
        return (Map<String, ?>) value;
    }

    /**
     * Gets a number from an object for the given key.  If the key is not present, this returns null.
     * If the value does not represent a double, throws an exception.
     */
    @Override
    public Double getNumberAsDouble(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (value instanceof Double) {
            return (Double) value;
        }
        if (value instanceof String) {
            try {
                return Double.parseDouble((String) value);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                    String.format("value '%s' for key '%s' is not a double", value, key));
            }
        }
        throw new IllegalArgumentException(
            String.format("value '%s' for key '%s' in '%s' is not a number", value, key, obj));
    }

    /**
     * Gets a number from an object for the given key, casted to an integer.  If the key is not
     * present, this returns null.  If the value does not represent an integer, throws an exception.
     */
    @Override
    public Integer getNumberAsInteger(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (value instanceof Double) {
            Double d = (Double) value;
            int i = d.intValue();
            if (i != d) {
                throw new ClassCastException("Number expected to be integer: " + d);
            }
            return i;
        }
        if (value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                    String.format("value '%s' for key '%s' is not an integer", value, key));
            }
        }
        throw new IllegalArgumentException(
            String.format("value '%s' for key '%s' is not an integer", value, key));
    }

    /**
     * Gets a number from an object for the given key, casted to an long.  If the key is not
     * present, this returns null.  If the value does not represent a long integer, throws an
     * exception.
     */
    @Override
    public Long getNumberAsLong(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (value instanceof Double) {
            Double d = (Double) value;
            long l = d.longValue();
            if (l != d) {
                throw new ClassCastException("Number expected to be long: " + d);
            }
            return l;
        }
        if (value instanceof String) {
            try {
                return Long.parseLong((String) value);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                    String.format("value '%s' for key '%s' is not a long integer", value, key));
            }
        }
        throw new IllegalArgumentException(
            String.format("value '%s' for key '%s' is not a long integer", value, key));
    }

    /**
     * Gets a string from an object for the given key.  If the key is not present, this returns null.
     * If the value is not a String, throws an exception.
     */
    @Override
    public String getString(Map<String, ?> obj, String key) {
        assert obj != null;
        assert key != null;
        if (!obj.containsKey(key)) {
            return null;
        }
        Object value = obj.get(key);
        if (!(value instanceof String)) {
            throw new ClassCastException(
                String.format("value '%s' for key '%s' in '%s' is not String", value, key, obj));
        }
        return (String) value;
    }

    /**
     * Casts a list of unchecked JSON values to a list of checked objects in Java type.
     * If the given list contains a value that is not a Map, throws an exception.
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Map<String, ?>> checkObjectList(List<?> rawList) {
        assert rawList != null;
        for (int i = 0; i < rawList.size(); i++) {
            if (!(rawList.get(i) instanceof Map)) {
                throw new ClassCastException(
                    String.format("value %s for idx %d in %s is not object", rawList.get(i), i, rawList));
            }
        }
        return (List<Map<String, ?>>) rawList;
    }


    /**
     * Casts a list of unchecked JSON values to a list of String. If the given list
     * contains a value that is not a String, throws an exception.
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<String> checkStringList(List<?> rawList) {
        assert rawList != null;
        for (int i = 0; i < rawList.size(); i++) {
            if (!(rawList.get(i) instanceof String)) {
                throw new ClassCastException(
                    String.format(
                        "value '%s' for idx %d in '%s' is not string", rawList.get(i), i, rawList));
            }
        }
        return (List<String>) rawList;
    }

}

3、GsonImpl【Gson框架实现】

package org.apache.dubbo.common.json.impl;

import org.apache.dubbo.common.utils.ClassUtils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.List;

public class GsonImpl extends AbstractJSONImpl {
    // weak reference of com.google.gson.Gson, prevent throw exception when init
    private volatile Object gsonCache = null;

    @Override
    public boolean isSupport() {
        try {
            Class<?> aClass = ClassUtils.forName("com.google.gson.Gson");
            return aClass != null;
        } catch (Throwable t) {
            return false;
        }
    }

    @Override
    public <T> T toJavaObject(String json, Type type) {
        return getGson().fromJson(json, type);
    }

    @Override
    public <T> List<T> toJavaList(String json, Class<T> clazz) {
        return getGson().fromJson(json, TypeToken.getParameterized(List.class, clazz).getType());
    }

    @Override
    public String toJson(Object obj) {
        return getGson().toJson(obj);
    }

    private Gson getGson() {
        if (gsonCache == null || !(gsonCache instanceof Gson)) {
            synchronized (this) {
                if (gsonCache == null || !(gsonCache instanceof Gson)) {
                    gsonCache = new Gson();
                }
            }
        }
        return (Gson) gsonCache;
    }
}

 4、FastJsonImpl【FastJson框架】

package org.apache.dubbo.common.json.impl;

import org.apache.dubbo.common.utils.ClassUtils;

import com.alibaba.fastjson.serializer.SerializerFeature;

import java.lang.reflect.Type;
import java.util.List;

public class FastJsonImpl extends AbstractJSONImpl {

    @Override
    public boolean isSupport() {
        try {
            Class<?> aClass = ClassUtils.forName("com.alibaba.fastjson.JSON");
            return aClass != null;
        } catch (Throwable t) {
            return false;
        }
    }

    @Override
    public <T> T toJavaObject(String json, Type type) {
        return com.alibaba.fastjson.JSON.parseObject(json, type);
    }

    @Override
    public <T> List<T> toJavaList(String json, Class<T> clazz) {
        return com.alibaba.fastjson.JSON.parseArray(json, clazz);
    }

    @Override
    public String toJson(Object obj) {
        return com.alibaba.fastjson.JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
    }
}

5、JsonUtil框架工具类【根据配置项选择使用】

String PREFER_JSON_FRAMEWORK_NAME = "dubbo.json-framework.prefer";
package org.apache.dubbo.common.utils;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.json.JSON;
import org.apache.dubbo.common.json.impl.FastJsonImpl;
import org.apache.dubbo.common.json.impl.GsonImpl;

import java.util.Arrays;
import java.util.List;

public class JsonUtils {
    private static volatile JSON json;

    public static JSON getJson() {
        if (json == null) {
            synchronized (JsonUtils.class) {
                if (json == null) {
                    String preferJsonFrameworkName = System.getProperty(CommonConstants.PREFER_JSON_FRAMEWORK_NAME);
                    if (StringUtils.isNotEmpty(preferJsonFrameworkName)) {
                        try {
                            JSON instance = null;
                            switch (preferJsonFrameworkName) {
                                case "fastjson":
                                    instance = new FastJsonImpl();
                                    break;
                                case "gson":
                                    instance = new GsonImpl();
                                    break;
                            }
                            if (instance != null && instance.isSupport()) {
                                json = instance;
                            }
                        } catch (Throwable ignore) {

                        }
                    }
                    if (json == null) {
                        List<Class<? extends JSON>> jsonClasses = Arrays.asList(
                            FastJsonImpl.class,
                            GsonImpl.class);
                        for (Class<? extends JSON> jsonClass : jsonClasses) {
                            try {
                                JSON instance = jsonClass.getConstructor().newInstance();
                                if (instance.isSupport()) {
                                    json = instance;
                                    break;
                                }
                            } catch (Throwable ignore) {

                            }
                        }
                    }
                    if (json == null) {
                        throw new IllegalStateException("Dubbo unable to find out any json framework (e.g. fastjson, gson) from jvm env. " +
                            "Please import at least one json framework.");
                    }
                }
            }
        }
        return json;
    }

    /**
     * @deprecated for uts only
     */
    @Deprecated
    protected static void setJson(JSON json) {
        JsonUtils.json = json;
    }
}

二十三、优化if/else/switch的方法,降低程序圈复杂度、提高扩展性.

     1、使用卫语句提前返回,包括各种配置项检查、断言检查、参数校验等.

     2、使用三目表达式.

     3、使用Optional来减少返回.

     4、使用静态块+Map的缓存.

     5、使用策略模式来减少不必要的分支.

     6、使用枚举结合方法来实现.

     7、开发完功能后,整理代码,包括格式化命名,圈复杂度和深度,以及IDAE重构快捷键抽取一下,提供复用,减少重复.

    8、多阅读开源框架代码,学习实践设计模式、编码技巧、软件设计思想对日常开发很有帮助.

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大道之简

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值