# 后端开发技巧常用规范

Posted MarlonBrando1998

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 后端开发技巧常用规范相关的知识,希望对你有一定的参考价值。


开发技巧

equals() 方法的使用
  • null.equals()会出报空指针,因该是非null的值.equals()
  • 可以使用Objectsequals()方法避免空值,完美
String strOne = null;
String strTwo = null;
boolean oneFlag = Objects.equals(strOne, strTwo);
  • 忽略大小写:equalsIgnoreCase()

创建 HashMap 指定初始化大小
public HashMap(int initialCapacity) 
    this(initialCapacity, DEFAULT_LOAD_FACTOR);

  • initialCapacity = (需要存储的元素个数/负载因子)+1。负载因子默认为0.75

  • 当不指定HashMap的大小会发生多次扩容会影响效率。比如map中有1000个元素,至少要将容量设置为1000/0.75=1333+1=1334,如果不设置大小那么就会多次扩容,比较影响效率。

  • 当无法估计大小的时候,请设置为HashMap的默认大小16


Optional.ofNullable().orElse() 避免空指针

通过Optional.ofNullable().orElse()避免空指针,例如遍历从map中拿到的某个list,原始代码如下:

Map<String,Object> map = new HashMap<>(16);
map.put("list",null);

List<Map<String ,Object>> list = (List<Map<String, Object>>) map.get("list");
// list 会报控指针
for (Map<String, Object> item : list) 
    logger.info(String.valueOf(item));

  • 使用Optional 完美解决
Map<String,Object> map = new HashMap<>(16);
map.put("list",null);

List<Map<String ,Object>> list = Optional.ofNullable((List < Map < String, Object >> ) map.get("list")).orElse(new ArrayList<>());
for (Map<String, Object> item : list) 
    logger.info(String.valueOf(item));

  • 使用Optional选择默认数据
User user1 = new User(1, "张三", "西安");
User user2 = new User(2, "李四", "新疆");

user1 = null;
User user = Optional.ofNullable(user1).orElseGet(() -> user2);
logger.info(user.toString());

Stream 求和
  • 使用 Stream流遍历集合中的元素进行求和操作
List<Double> doubleList = Arrays.asList(12.2, 13.45, 12.4);
double sumOne = doubleList.stream().mapToDouble(x -> x).sum();
logger.info("sumOne:", sumOne);

List<BigDecimal> decimalList = new ArrayList<>();
decimalList.add(new BigDecimal("12.3"));
decimalList.add(new BigDecimal("12.3"));
decimalList.add(new BigDecimal("12.3"));
BigDecimal bigDecimal = decimalList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
logger.info("bigDecimal:", bigDecimal.floatValue());
logger.info("bigDecimal:", bigDecimal.doubleValue());

List<Object> objectList = Arrays.asList(12, 13, 1);
int sum = objectList.stream().mapToInt(x -> (int) x).sum();
logger.info("sum:", sum);

List 切割工具
  • Lists.partition()
for (List<DataDto> dataDtos : Lists.partition(list, 1000)) 
    dataDtoMapper.insertBatch(dataDtos);

  • 依赖
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

单例类或者工具类 添加私有构造方法
  • 工具类或者单例类提供私有的构造函数,没有过多的功能,提供私有构造函数防止外部使用污染。

类变量(集合)应该在使用完成之后清空,避免内存泄漏
  • 应该及时销毁没用的对象,如果对象过大,虚拟机没办法垃圾回收的时候,有可能造成内存泄漏,所以使用完就清空.
private static final Map<String, Object> TABLE_COLUMN_MAP = new HashMap<>();

// 清空集合
TABLE_COLUMN_MAP.clear();

使用 ThreaadLocal 后需要释放资源防止内存泄漏
private ThreadLocal<Map<String, String>> threadLocalMap = new ThreadLocal<>();

@Test
public void test1() 
    Map<String, String> map = new HashMap<>();
    map.put("test1", "张三");
    map.put("test2", "李四");
    threadLocalMap.set(map);
    getThreadLocalMap();
    threadLocalMap.remove();


巧妙使用设计模式

Spring 工厂模式的结合使用
public interface CustomerService 

    /**
     * 获取用户姓名
     * @return
     */
    String getUserName();

    /**
     * 注册
     */
    void registered();

    /**
     * 登录
     */
    void login();


  • 接口的实现类:需要收集的对象实例可以有很多个实例
@Service
public class CustomerServiceOneImpl implements CustomerService 


    @Override
    public String getUserName() 
        return "CustomerOne";
    

    @Override
    public void registered() 

    

    @Override
    public void login() 

    


@Service
public class CustomerServiceTwoImpl implements CustomerService 


    @Override
    public String getUserName() 
        return "CustomerTwo";
    

    @Override
    public void registered() 

    

    @Override
    public void login() 

    

  • 工厂方法:可以使用set注入、或者构造函数方式、或者从当前上下文中拿到接口的实例对象
@Component
public class CustomerFactory 

    /**
     * 对象 Map
     */
    private static final Map<String, CustomerService> OBJECT_MAP = new HashMap<>();


    /**
     * set 方法注入
     *
     * @param customerService
     */
    @Autowired
    private void setObjectMap(List<CustomerService> customerService) 
        for (CustomerService service : customerService) 
            OBJECT_MAP.put(service.getUserName(), service);
        
    

    /**
     * 获取 CustomerService 的实例
     *
     * @param type
     * @return
     */
    public static CustomerService getInstance(String type) 
        return OBJECT_MAP.get(type);
    



  • 测试
/**
  * Spring 工厂模式测试
  */
@Override
public void testFive() 
    CustomerFactory.getInstance("CustomerOne").registered();
    CustomerFactory.getInstance("CustomerTwo").registered();


Spring、SpringBoot 经常使用技巧

Stream 流等操作时候使用方法的引用
  • Stream
List<String> collect = list.stream().filter("lisi"::equals).map(String::toUpperCase).collect(Collectors.toList());
collect.forEach(System.out::println);

list.removeIf("李四"::equals);
  • HashMap
Map<String, String> map = new HashMap<String, String>() 
    put("one", "one");
    put("two", "one");
    put("three", "one");
;
Map<String, String> mapOne = new HashMap<>();
map.forEach(mapOne::put);
logger.info(String.valueOf(mapOne));

Java 创建线程池
  • 使用 ThreadPoolExecutor创建线程池,使用线程,到处 new Thread() 没有回收造成资源浪费,因该交给线程池去管理线程。
public class ThreadPooTest 

    private static final Logger logger = LoggerFactory.getLogger(ThreadPooTest.class);

    private static final long THREAD_TIME_OUT = 60;

    @Test
    public void test() 
        // Cpu 核数
        int cpuNum = Runtime.getRuntime().availableProcessors();
        // 最大数
        int maxSize = 2 * cpuNum + 1;

        /**
         * 拒绝策略:当阻塞队列和最大线程都用完之后
         *
         * AbortPolicy:ThreadPoolExecutor中默认的拒绝策略就是AbortPolicy。直接抛出异常。
         * CallerRunsPolicy:在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务。
         * DiscardPolicy:会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。
         * DiscardOldestPolicy:当任务呗拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。
         */
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(cpuNum,
                maxSize,
                THREAD_TIME_OUT,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(20),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
        poolExecutor.execute(new Thread(() -> 
            logger.info(Thread.currentThread().toString());
        ));

    


Spring Boot 配置全局的线程池
@Configuration
@EnableAsync
public class ThreadPoolConfig 

    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolConfig.class);

    @Bean
    public Executor globalExecutor() 
        // 获取当前cpu核数
        int cpuNum = Runtime.getRuntime().availableProcessors();
        ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
        poolExecutor.setCorePoolSize(cpuNum);
        //配置最大线程数
        poolExecutor.setMaxPoolSize(cpuNum * 2);
        //配置队列大小
        poolExecutor.setQueueCapacity(300);
        //线程存活时间
        poolExecutor.setKeepAliveSeconds(60);
        //配置线程池中的线程的名称前缀
        poolExecutor.setThreadNamePrefix("globalExecutor");
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        poolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        poolExecutor.initialize();
        logger.info(LogConstant.FLAG);
        logger.info(LogConstant.LOG_SUCCESS_PREFIX + "Spring 全局线程池初始化完成......");
        logger.info(JSON.toJSONString(poolExecutor));
        logger.info(LogConstant.FLAG);
        return poolExecutor;
    


  • 使用
/**
  * 全局线程池配置测试
  */
@Async("globalExecutor")
@Override
public void globalExecutorTest() 
    logger.info("test thread!");


Idea 热部署插件:Jrebel
  • Idea社区版能满足常用的开发,支持mavengradle项目,真的没有必要破解Idea,哈哈哈哈哈哈哈哈。

  • 使用特别Nice基本上不用重启服务,网上都有注册码。


初始化 Map
  • 惯例
Map<String, String> mapTwo = new HashMap<>();
mapTwo.put("a", "b");
mapTwo.put("c", "d");
  • java8新特性:双括号初始化
Map<String, String> mapOne = new HashMap<String, String>() 
    
        put("one", "testOne");
        put("two", "testTwo");
        put("three", "testThree");
    
;
  • com.google.guava中的方法
ImmutableMap<String, Integer> map = ImmutableMap.of("a", 1, "b", 2, "c", 3);
logger.info(String.valueOf(map));

List 初始化
  • 构造Listadd()
List<String> listOne = new ArrayList提效小技巧——记录那些不常用的代码片段

python常用代码

你可能不知道的JavaScript代码片段和技巧(下)

你可能不知道的JavaScript代码片段和技巧(上)

Android课程---Android Studio使用小技巧:提取方法代码片段

Vue友们就靠这6个开发技巧了(建议收藏)