在工作中如何写出高效优雅的Java代码:实战技巧与代码示例

1. 使用合适的数据结构

选择合适的数据结构对提高代码效率至关重要。

示例:使用HashMap优化查找

// 不推荐的做法:使用List进行查找  List 查找元素,是通过索引慢
List<String> list = new ArrayList<>(Arrays.asList("apple", "banana", "cherry"));
if (list.contains("banana")) {
    // 处理逻辑
}

// 推荐的做法:使用HashMap提高查找效率  HashSet 的底层是 HashMap ,直接相等与
Set<String> set = new HashSet<>(Arrays.asList("apple", "banana", "cherry"));
if (set.contains("banana")) {          
    // 处理逻辑 
}

set.contains("banana") == map.get("banana")

2. 避免重复代码

重复代码会使得程序难以维护,使用方法或类重构可以有效解决这一问题。

示例:提取重复代码到方法

// 重复代码示例
public void processUser(User user) {
    if (user != null && user.isActive()) {
        // 处理逻辑
    }
}

// 优化后
public void processUser(User user) {
    if (isValidUser(user)) {
        // 处理逻辑
    }
}

private boolean isValidUser(User user) {
    return user != null && user.isActive();
}

3. 利用Java 8特性

Java 8引入了许多新特性,如Lambda表达式和Stream API,它们可以使代码更加简洁高效。

示例:使用Stream API处理集合

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());

4. 理解并发编程

在多线程和并发编程中,正确管理资源和线程是提高性能的关键。

示例:可以使用Java 8 的  CompletableFuture

     // 异步把上个版本的数据 批量插入到 历史表
            CompletableFuture.runAsync(() -> {
                MyBatisBatchExecutorUtil.batchCommit(PzryMapper.class, INSERT_HISTORY, historyList);
                MyBatisBatchExecutorUtil.batchCommit(PzryMapper.class, BATCH_HISTORY_INSERT_LD, historyLdData);
            });


     // 异步调用一些方法(记录操作日志)
        CompletableFuture.runAsync(() -> logService.addLog(LogOperationYeMianEnum.getContent(2), logType, builder, isSucess, userId));


 5.使用全局异常类

可以使用全局异常处理类来替换写不完的 try catch

示例: @RestControllerAdvice

原本:
   @GetMapping("/add2")
    public String add2() {
        String result = "成功";
        try {
            int a = 10 / 0;
        } catch (Exception e) {
            result = "数据异常";
        }
        return result;
    }


使用后:
   @GetMapping("/add2")
    public String add2() {
        String result = "成功";
        int a = 10 / 0;
        return result;
    }



@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public String handleException(Exception e) {
        if (e instanceof ArithmeticException) {
            return "数据异常";
        }
        if (e != null) {
            return "服务器内部异常";
        }
        return null;
    }
}

 6. 多使用工具类方法

可以多使用一些工具类方法来判断集合,字符串,对象是否为空

示例: Objects,Strings,StringUtils, CollectionUtils,ObjectUtils

        Objects.nonNull(new Ld());
        Objects.isNull(new Ld());
        Objects.equals(new Ld(),new Ld());
        Strings.isNullOrEmpty("");
        StringUtils.isEmpty();
        CollectionUtils.isEmpty(new HashMap<>());
        CollectionUtils.isEmpty(new ArrayList<>());
        CollectionUtils.isEmpty(new HashSet<>());
        
        List<Object> list = new ArrayList<>();
        list.add("111");
        System.out.println(ObjectUtils.isEmpty(list));

 7. 字符串拼接

替换传统的 + “” +

示例:String.format

String.format("%s(%s)", name.getName(), name.getNetId())

 8. 优化一些码值的转换

替换传统的if else 判断存值

示例:使用 map 枚举

  //如果是 例行= 0 非例行= 1 OA申请=2
   Map<String, String> map= new HashMap<>(16);
   map.put("例行", "0");
   map.put("非例行", "1");
   map.put("OA申请", "2");

   yxThingsType.setIsRoutine(map.getOrDefault(yxThingsType.getIsRoutine(), ""));

9. 使用静态常量替换魔法值,字符串

 private static final String INSERT_HISTORY = "insertHistory";

 private static final Integer MAX_DRAFT_COUNT = 5;

10. 批量插入几百条,几千条数据库时使用工具类

穿透的批量插入,当数据量过多的时候批量插入的时间多长

示例:使用底层  sqlSessionFactory 的批量插入

工具类1:

package com.ly.cloud.util;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import com.google.common.collect.Lists;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
 * @Author 
 * @Date Created in  2023/12/25 15:57
 * @DESCRIPTION: mybatis快速批量插入 数据 工具类
 * @Version V1.0
 */
@Component
public class MyBatisBatchExecutorUtil {
    private static final Logger logger = LoggerFactory.getLogger(MyBatisBatchExecutorUtil.class);

    @Resource
    private SqlSessionFactory sqlSessionFactory;
    private static MyBatisBatchExecutorUtil utils;

    @PostConstruct
    public void init() {
        utils = this;
        utils.sqlSessionFactory = this.sqlSessionFactory;
    }

    /**
     * 批量提交数据
     *
     * @param mapperClass     Mapper 类
     * @param dataList        要提交的数据列表
     */
    public static <T> void batchCommit(Class<?> mapperClass, String mybatisSqlId, List<T> dataList) {
        if (dataList == null || dataList.isEmpty()) {
            return;
        }

        SqlSession session = null;
        int commitCountEveryTime = 500;
        try {
            long startTime = System.currentTimeMillis();
            session = utils.sqlSessionFactory.openSession(ExecutorType.BATCH, false);
            List<List<T>> groupList = Lists.partition(dataList, commitCountEveryTime);
            for (List<T> tempList : groupList) {
                session.insert(mapperClass.getName() + "." + mybatisSqlId, tempList);
            }
            session.commit();
            session.clearCache();  // 移动到循环结束后执行
            long endTime = System.currentTimeMillis();
            logger.info("批量插入数据耗时:" + (endTime - startTime) + "毫秒");
        } catch (Exception e) {
            logger.error("batchCommit error!", e);
            if (session != null) {
                session.rollback();
            }
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

}




使用示例:
INSERT_HISTORY  === 》  对应的mapper 类的方法名 (mybatis 的id )
currentData     === 》  对应的数据集合
MyBatisBatchExecutorUtil.batchCommit(NewYxThingsTypeMapper.class, INSERT_HISTORY, currentData);

工具类2:

package com.example.juc.utils.dataUtils;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.function.BiFunction;

/**
 * @author 12926
 * @CreatTime: 2022/7/27 10:53
 */
@Component
public class MybatisBatchUtils {
    /**
     * 每次处理1000条
     */
    private static final int BATCH_SIZE = 1000;

    @Resource
    private SqlSessionFactory sqlSessionFactory;
    private static MybatisBatchUtils utils;
    @PostConstruct
    public void init() {
        utils = this;
        utils.sqlSessionFactory = this.sqlSessionFactory;
    }

    /**
     * 批量处理修改或者插入
     *
     * @param data     需要被处理的数据
     * @param mapperClass  Mybatis的Mapper类
     * @param function 自定义处理逻辑
     * @return int 影响的总行数
     */
    public static <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T, U, R> function) {
        int i = 1;
        SqlSession batchSqlSession = utils.sqlSessionFactory.openSession();
        batchSqlSession.getConfiguration().setDefaultExecutorType(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                function.apply(element,mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    System.out.println(batchSqlSession.flushStatements());
                }
                i++;
            }
            // 非事务环境下强制commit,事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            batchSqlSession.close();
        }
        return i - 1;
    }
}


//使用方法
       MybatisBatchUtils.batchUpdateOrInsert(list, UserMapper.class,
                (user, userMapper) -> userMapper.insert(user));


@Mapper
public interface UserMapper {
    List<User> getUsersList();

    int insert(@Param("user") User user);
}

11. 获取接口的请求头信息

使用工具类获取,每次在只需要一行代码

示例:

原来每个请求:@RequestHeader("loginUserId") String loginUserId

    @ApiOperation("查询流程[类型]列表(本地数据源)")
    @PostMapping("/listInstancesTypeByLocal")
    public WebResult<List<InstancesStatusVo>> listInstancesTypeByLocal(@RequestBody FlowGetInstanceByTypeDto flowGetInstanceByTypeDto,
                                                                      @RequestHeader("loginUserId") String loginUserId) {
            return WebResult.ok(yxMyThingsService.listInstancesTypeByLocal(flowGetInstanceByTypeDto, loginUserId));
       


工具类:
public class LoginUserUtil {
    public static String getLoginUserId() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = null;
        if (requestAttributes != null) {
            request = ((ServletRequestAttributes) requestAttributes).getRequest();
        }
        // 子线程共享
        RequestContextHolder.setRequestAttributes(requestAttributes, true);
        if (request != null) {
            return request.getHeader("loginUserId");
        }
        return null;
    }
}

//调用:
LoginUserUtil.getLoginUserId

12. 遍历Map 的时候,使用 EntrySet 方法

 使用 EntrySet 方法,可以直接返回 set 对象,直接拿来用即可;而使用 KeySet 方法,获得的是key 的集合,需要再进行一次 get 操作,多了一个操作步骤,所以更推荐使用 EntrySet 方式遍历 Map。

Set<Map.Entry<String, String>> entryseSet = nmap.entrySet();
for (Map.Entry<String, String> entry : entryseSet) {
    System.out.println(entry.getKey()+","+entry.getValue());
}

 13.为集合对象中的每个元素赋值(序号)

IntStream.rangeClosed(1, departmentList.size())
                    .forEach(i -> 
departmentList.get(i - 1).setMyNumber(String.valueOf(i)));

 14. 减少集合循环次数

在开发比较俩个集合的案例很多

示例:

反例
for(User user: userList) {
   for(Role role: roleList) {
      if(user.getRoleId().equals(role.getId())) {
         user.setRoleName(role.getName());
      }
   }
}

正例
Map<Long, List<Role>> roleMap = roleList.stream().collect(Collectors.groupingBy(Role::getId));

for (User user : userList) {
    List<Role> roles = roleMap.get(user.getRoleId());
    if(CollectionUtils.isNotEmpty(roles)) {
        user.setRoleName(roles.get(0).getName());
    }
}

15. 使用BigDecimal 进行小数点的加减

    private String covertString(String pzrySmallBbh) {
        if (!StringUtils.isEmpty(pzrySmallBbh)) {
            // 将字符串转换为 BigDecimal 类型
            BigDecimal number = new BigDecimal(pzrySmallBbh);
            // 每次加 0.01
            number = number.add(new BigDecimal("0.01"));
            // 将结果转换回字符串
            return number.toString();
        }
        return null;
    }

16. 多个线程往同一个集合中写数据时

使用:CopyOnWriteArrayList

List<Object> list = new CopyOnWriteArrayList<>();

Set<Object> list  = new CopyOnWriteArraySet<>();

Map<String,String> map2 = new ConcurrentHashMap<>()

17. 集合复制时修改复制后的集合

   
反例: 这样会把 yxAdminList 这个集合的 setYxThingNo 也值为空;
List<YxAdmin> yxAdminListTwo = new ArrayList<>(yxAdminList);

yxAdminListTwo.forEach(vo -> vo.setYxThingNo("")); 




正例:
        List<ListCopy> addALL = new ArrayList<>();
        addALL.addAll(list);
        addALL.forEach(vo -> vo
                .setName(""));

或者使用for循环 
    List<YxAdmin> yxAdminListTwo = new ArrayList<>();
            for (YxAdmin vo : yxAdminList) {
                YxAdmin copiedAdmin = new YxAdmin();
                copiedAdmin.setName(vo.getName());
                copiedAdmin.setDepartment(vo.getDepartment());
                copiedAdmin.setYxThingNo("");
                yxAdminListTwo.add(copiedAdmin);
            }

18. 将list<String> 转成字符串

List<String> objects = new ArrayList<>();

String name = String.join(",", objects);

19. 学会使用三目运算符

反例
String title;
if (isMember(phone)) {
    title = "会员";
} else {
    title = "游客";
} 

正例

String title = isMember(phone) ? "会员" : "游客";

20. 使用增强for 替换普通for 循环

    for (JsonElement element : dataArray) {
            JsonObject itemObject = element.getAsJsonObject();
            String title = itemObject.get("Title").getAsString();
            System.out.println("Title:----" + title);
        }

21. 利用 Map 的 computeIfAbsent 方法

利用 Map 的 computeIfAbsent 方法,可以保证获取到的对象非空,从而避免了不必要的空判断和重新设置值。

普通写法:
Map<Long, List<UserDO>> roleUserMap = new HashMap<>();
for (UserDO userDO : userDOList) {
    Long roleId = userDO.getRoleId();
    List<UserDO> userList = roleUserMap.get(roleId);
    if (Objects.isNull(userList)) {
        userList = new ArrayList<>();
        roleUserMap.put(roleId, userList);
    }
    userList.add(userDO);
}


使用利用 Map 的 computeIfAbsent 方法

Map<Long, List<UserDO>> roleUserMap = new HashMap<>();
for (UserDO userDO : userDOList) {
    roleUserMap.computeIfAbsent(userDO.getRoleId(), key -> new ArrayList<>())
        .add(userDO);
}

22.stream 并行流适时使用

    // 使用stream 并行流处理查询结果,检查是否有重复数据 提高查询效率
if (admins.parallelStream().anyMatch(vo -
> !CollectionUtils.isEmpty(
pzPeopleMapper.isExitYxAdmin(vo.getName(), vo.getDepartment())))) {
// 只要匹配到有一条重复数据,直接返回 false
 return false;
}

后续。。。。持续更新

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: 《码出高效:java开发手册》这本书是由阿里巴巴Java开发团队所编的,它主要讲解了Java开发的一些最佳实践和优化技巧,旨在帮助开发者写出高质量、高效率的代码。 整本书包括了Java开发的方方面面,涵盖了从Java基础、集合框架、并发编程、IO操作、性能优化等方面的内容。最为重要的是这些知识点都是讲解得非常详细,大量体现出了作者们得实践经验和理论能力。在这个过程,书籍所提供的大量实战示例和最佳实践都可以在实际工作获得收益。 此外,书籍还讲解了很多阿里巴巴内部的开发流程代码规范,诸如代码注释、变量规范、枚举类设计等,这些规范奉行着“规模化、高效化、标准化”的开发理念,从而可以节省开发时间和代码质量的提高。 总的来说,《码出高效:java开发手册》这本书是一本很不错的Java开发指南,对于任何一位Java开发者都是一本必备参考书,尤其是在阿里体系工作的开发者更不能错过这本宝典。 ### 回答2: 《码出高效:java开发手册 pdf》是一本非常实用的Java开发书籍,旨在通过系统分析Java开发及其常见问题,提供一些高效的实用代码技巧。全书共分三部分,分别是Java基础知识、Java编码规范和高效Java编程,共计十二章。本书的主要内容包括编程规范、异常处理、集合使用、IO处理、线程和并发编程、数据库操作及JDK新特性等。其每一章都传授了一些实用的技巧,可以让Java开发者编更加高效代码。 《码出高效:java开发手册 pdf》的优点主要有三点。第一,本书内容涵盖Java开发的方方面面,从Java基础到高效编程技巧都有所涉及。这让读者可以系统全面地掌握Java开发技能,是一本非常适合初学者和级开发者的Java开发书籍。第二,本书提供了大量实用的代码示例,这些代码可以快速解决开发常见的问题,节省了开发者解决问题的时间。第三,本书的编风格通俗易懂,语言简洁明了,结构清晰,非常适合读者阅读和学习,即使是非专业人士也能轻松理解其的内容。 总之,《码出高效:java开发手册 pdf》是一本值得Java开发者阅读的优秀书籍,通过学习这本书,读者可以获得许多实际的Java开发技巧和经验,提高编码水平,编更加高效代码。同时,读者也可以将书所学的知识运用到实际开发,实现自己的技术突破和知识更新。 ### 回答3: 《码出高效: Java开发手册PDF》是一本关于Java软件开发的实践指南。本书作者通过自己多年的实践经验以及技术积累,总结归纳出了一套行之有效的Java开发规范和最佳实践。本书涵盖了Java开发的方方面面,涉及Java语言的基础知识、常见开发框架、设计模式、性能优化、调试技巧代码安全以及项目管理等内容,适用于Java程序员、软件架构师、开发经理等读者。 本书主要包括三个部分:编码规范,工程实践和架构实践。其,编码规范部分详细介绍了Java编码规范、命名规范、注释规范、代码格式规范等,这些规范都是编高质量Java代码的基础。在工程实践部分,作者主要介绍了Java开发的常见问题以及解决方案,包括环境配置、开发工具、单元测试、集成测试等。架构实践部分则从架构设计、服务发现、数据缓存、性能优化等方面给出了一些实用的建议。 通过阅读本书,读者可以学习到一些高效Java开发技巧和实践经验,并且将这些技巧应用到实际项目,提高开发效率和代码质量,从而在竞争激烈的软件开发市场占据更好的位置。此外,本书还提供了很多案例分析和代码示例,为读者解决实际问题提供了可参考的经验。总之,《码出高效: Java开发手册PDF》是一本值得Java开发人员阅读的经典参考书籍。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

入夏忆梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值