资讯专栏INFORMATION COLUMN

# 后端开发技巧、常用规范

Eirunye / 3004人阅读

摘要:在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务。会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。


开发技巧

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.guavagroupId>    <artifactId>guavaartifactId>    <version>31.0.1-jreversion>    <exclusions>        <exclusion>            <groupId>log4jgroupId>            <artifactId>log4jartifactId>        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<>();@Testpublic 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();}
  • 接口的实现类:需要收集的对象实例可以有很多个实例
@Servicepublic class CustomerServiceOneImpl implements CustomerService {    @Override    public String getUserName() {        return "CustomerOne";    }    @Override    public void registered() {    }    @Override    public void login() {    }}@Servicepublic class CustomerServiceTwoImpl implements CustomerService {    @Override    public String getUserName() {        return "CustomerTwo";    }    @Override    public void registered() {    }    @Override    public void login() {    }}
  • 工厂方法:可以使用set注入、或者构造函数方式、或者从当前上下文中拿到接口的实例对象
@Componentpublic 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 工厂模式测试  */@Overridepublic 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@EnableAsyncpublic 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")@Overridepublic 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
                 
               
              

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/124441.html

相关文章

  • 前端开发知识点整理

    摘要:前言本文主要是有关前端方面知识按照目前的认知进行的收集归类概括和整理,涵盖前端理论与前端实践两方面。 前言:本文主要是有关前端方面知识按照 XX 目前的认知进行的收集、归类、概括和整理,涵盖『前端理论』与『前端实践』两方面。本文会告诉你前端需要了解的知识大致有什么,看上去有很多,但具体你要学什么,还是要 follow your heart & follow your BOSS。 初衷...

    Blackjun 评论0 收藏0
  • 前端开发知识点整理

    摘要:前言本文主要是有关前端方面知识按照目前的认知进行的收集归类概括和整理,涵盖前端理论与前端实践两方面。 前言:本文主要是有关前端方面知识按照 XX 目前的认知进行的收集、归类、概括和整理,涵盖『前端理论』与『前端实践』两方面。本文会告诉你前端需要了解的知识大致有什么,看上去有很多,但具体你要学什么,还是要 follow your heart & follow your BOSS。 初衷...

    Sike 评论0 收藏0
  • 前端开发知识点整理

    摘要:前言本文主要是有关前端方面知识按照目前的认知进行的收集归类概括和整理,涵盖前端理论与前端实践两方面。 前言:本文主要是有关前端方面知识按照 XX 目前的认知进行的收集、归类、概括和整理,涵盖『前端理论』与『前端实践』两方面。本文会告诉你前端需要了解的知识大致有什么,看上去有很多,但具体你要学什么,还是要 follow your heart & follow your BOSS。 初衷...

    tracy 评论0 收藏0
  • 必看!java后端,亮剑诛仙(最全知识点)

    摘要:鉴于目前大多数服务器环境都是,提前接触能够相辅相成。正则也是必须要掌握的一个知识点。有多种创建多线程的方式,不过目前使用线程池的多一些。 原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。 你可能有所感悟。零散的资料读了很多,但是很难有提升。到处是干货,但是并没什么用,简单来说就是缺乏系统化。另外,噪音太多,雷同的框架一大把,我不至于全都要去学了吧。 这里,我...

    陈江龙 评论0 收藏0
  • Java - 收藏集 - 掘金

    摘要:强大的表单验证前端掘金支持非常强大的内置表单验证,以及。面向对象和面向过程的区别的种设计模式全解析后端掘金一设计模式的分类总体来说设计模式分为三大类创建型模式,共五种工厂方法模式抽象工厂模式单例模式建造者模式原型模式。 强大的 Angular 表单验证 - 前端 - 掘金Angular 支持非常强大的内置表单验证,maxlength、minlength、required 以及 patt...

    XiNGRZ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<