转载

我的编码备忘录

本文将主要记录在日常开发中遇到的各种问题。以技术类别进行章节划分,作为个人的编码备忘录随时进行查阅,并长期进行置顶。

JavaCore相关

该模块主要记录JavaCore相关的技术点

bigdecimal四舍五入

BigDecimal.ROUND_HALF_UP: 遇到.5的情况时往上近似,例: 1.5 ->;2
BigDecimal.ROUND_HALF_DOWN : 遇到.5的情况时往下近似,例: 1.5 ->;1

bigDecimal转换为百分比,保留若干小数

DecimalFormat decimalFormat = new DecimalFormat("0.00%");
BigDecimal decimal = new BigDecimal(count.intValue()).divide(new BigDecimal(allCount), 5, ROUND_HALF_UP);
String formatted = decimalFormat.format(sdPercent);

bigDecimal精确度

BigDecimal.setScale(5,  BigDecimal.ROUND_HALF_UP)  -->保留五位小数,最后一位遇到.5的情况时往上近似

bigDecimal除法

  1. Java的BigDecimal在使用除法(divide方法)时,应该手动指定精度和舍入的方式。
  2. 如果不指定精度和舍入方式,在除不尽的时候会报异常。

bigdecimal详解

这里直接参考别人的文章:

(BigDecimal的用法详解)[ https://www.cnblogs.com/jpfss/p/8072379.html ]

java8的optionnal

理解、学习与使用 JAVA 中的 OPTIONAL

举个例子:

public static void main(String[] args) {
    Double d = 2.2;
    Optional.ofNullable(d).ifPresent(a -> {
        System.out.println(a);
    });
    Double a = null;
    System.out.println(Optional.ofNullable(a).orElse(2.2));
}

ofNullable:如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法:不会抛出NullPointerException

ifPresent:检查是否有值的。该方法除了执行检查,还接受一个Consumer(消费者) 参数,如果对象不是空的,就对执行传入的 Lambda 表达式:

orElse:如果有值则返回该值,否则返回传递给它的参数值

并发框架

这部分主要讲并发框架相关

  1. CompletableFuture用法

CompletableFuture需要单独总结,这里直接放一个参考链接。 CompletableFuture 使用详解

集合框架

本模块主要记录集合相关的问题

如何对一个list进行subList操作

List<Object> list = new Arraylist<>();
List<Object> subList = list.subList(0, 5);
其中subList(0, 5)取得的是下标为0到4的元素,不包含下标为5的元素.

注意:subList看起来好像是取出了原list的子list,实际上仅仅是取到原list的引用。

subList方法的返回值,只是ArrayList的一个映像而已。

也就是说,当我们使用子集合subList进行元素的修改操作时,会影响原有的list集合。

如果要生成原有list的子集合,还是采用硬复制的方式比较好,也就是新建一个新的list,对原list集合进行解析后装载到新的list中。

集合如何进行排序操作?(如:如何对一个list中的元素进行排序)

集合排序,一般有三种方法。

利用集合框架提供的Collections.sort实现排序,待进行排序的实体需要实现比较器Comparable接口的compareTo方法。

返回当前入参的实体和this对象的属性差(该属性为排序依据),

属性差如果为负数表示当前入参比本身小,

属性差如果为0表示当前入参与本身相等,

属性差如果为正数表示当前入参比本身大,

最后调用Collections.sort(temp);返回的集合排序方式为自然排序。

通过调用 Collections.sort(List list, Comparator<? super T> c) 方法,传入Comparator实现,这种方式下,实体不需要实现Comparable接口。

对于JDK1.8,可以通过stream流实现排序,对象本身不需要实现Comparable接口,示例代码如下

//3.利用Java8的stream流和Comparator实现集合排序
list = list.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());

数据库相关(包含Dao相关组件)

本章节主要记录数据库相关的技术点,包含Dao相关组件的使用,如JPA、Mybatis等

mybatis update自动追加逗号 “,”

一个推荐的SQL如下:

<update id="updateOne"  parameterType="com.inspur.search.data.EntityRelation">
    UPDATE ENTITY_RELATION
        <trim prefix="set" suffixOverrides=",">
        <if test="srcId!=null">SRC_ID=#{srcId},</if>
        <if test="srcType!=null">SRC_TYPE=#{srcType},</if>
        <if test="destId!=null">DEST_ID=#{destId},</if>
        <if test="destType!=null">DEST_TYPE=#{destType},</if>
        <if test="relType!=null">REL_TYPE=#{relType},</if>
        <if test="status!=null">STATUS=#{status},</if>
        <if test="snId!=null">SN_ID=#{snId},</if>
        </trim>
    WHERE id=#{id}
</update>

这种方式是动态SQL拼接,使用trim是为了删掉最后字段的“,”

不用单独写SET了,因为set被包含在trim中了

mybatis使用truncate语句

在mybatis中使用truncate语句刷新表。

<update id="truncateTable">
    truncate table [表名]
</update>

mybatis使用@Param传参以及批量插入

@Param Parameter N/A 如果你的映射器的方法需要多个参数, 这个注解可以被应用于映射器的方法参数来给每个参数一个名字。否则,多参数将会以它们的顺序位置来被命名 (不包括任何 RowBounds 参数) 比如。 #{param1} , #{param2} 等 , 这是默认的。

如果使用 @Param(“person”), 则参数应该被命名为 #{person}。

这里重点总结一个场景,批量insert。对应sql如下:

<insert id="batchInsertIdList" parameterType="java.util.List">
    insert into idlist_tmp (id, record_date) values
    <foreach collection="tmpInfos" item="tmpInfo" separator=",">
        (#{tmpInfo.id}, #{tmpInfo.recordDate})
    </foreach>
</insert>

这里通过#{tmpInfo.id}指定insert参数为对象tmpInfo的某个属性

int batchInsert(@Param(value = "tmpInfos") List<TmpInfo> tmpInfos);

这里通过@Param指定insert的sql中的参数引用。

MySQL建表时设置timestamp精度到毫秒

CREATE TABLE `table1` (
`tab1_id` VARCHAR(11) DEFAULT NULL,
`create` TIMESTAMP(3) NULL DEFAULT NULL,
`create2` DATETIME(3) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8

设置精度的方式为:

TIMESTAMP(3)与 DATETIME(3)意思是保留3位毫秒数

TIMESTAMP(6)与 DATETIME(6)意思是保留6位毫秒数

修改字段精度的方式为:

ALTER TABLE tb_financial MODIFY CREATE_TIME DATETIME(3) DEFAULT NULL COMMENT '录入时间';

插入日期可以用NOW(3)来控制精确的毫秒数,如:SELECT CURRENT_TIMESTAMP(3);也是可以的

mybatis批量插入

mybatis 批量插入数据

mybatis批量保存的两种方式(高效插入)

MySQL的case when语法

语法如下:

select 字段1, 字段2,       
    case 字段3     
    when 值1 then 新值       
    when 值2 then 新值      
    end as 重新命名字段3的名字       
from table      
where ……      
order by ……

如:

SELECT
    m.id AS id0,
    v.id AS id1,
    v.user_id AS userId,
    v.app_id AS appId
    (
    CASE
            WHEN v.label = 0 THEN
            '清晰' 
            WHEN v.label = 1 THEN
            '模糊' 
            WHEN v.label = 2 THEN
            '超清晰' ELSE '其他' 
        END 
        ) AS '清晰度'
    FROM
        video_info v,
        media_info m 
    WHERE
        v.id = m.id 
        AND m.id IN (
            '123123',
            '123124',
            '123125'
        )

参考资料: MySQL 的CASE WHEN 语句使用说明

工具技巧

本章节主要记录各种工具使用的技巧,如IDEA GIT等

idea自动导包

IDEA自动导包配置方式如下:

在菜单中选择如下选项:
 Settings→
    Editor→
        General→
            Auto Import 
然后勾选Add unambiguous imports on the fly以及Optimize imports on the fly

解释一下含义:

Add unambiguous imports on the fly:        快速添加明确的导入。
Optimize imports on the fly:               快速优化导入,优化的意思即自动帮助删除无用的导入。

打包运行相关

本章节主要记录打包相关的问题

如何通过命令行传递带空格的参数?

通过参数引用即可解决该问题,在UNIX环境下,通过引号将带空格的参数括起来即可,如:

$ java PrintFileSizes "/home/steve/Test File.txt"

Linux下找出进程正在侦听的端口号

在Linux下快速查到正在侦听的端口号,命令如下:

# 安装工具包,默认已安装,centos下为yum install
sudo apt install net-tools
# 查看侦听中的端口
sudo netstat -ltnp

nohup的作用

举个例子,有启动命令如下

nohup java -jar XXX.jar > /dev/null 2>&1 &

nohup表示:不挂断运行命令,当账户退出或终端关闭时,程序仍然运行。

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;这里表示”禁止输出”。我们应当在程序内配置日志打印。

其他用法: linux环境下nohup的执行jar

Spring相关

这部分主要整理Spring框架相关的问题,包括SpringBoot

Spring中通过 @Value 设置默认值

1.1 字符串类型的属性设置默认值

    @Value("${some.key:my default value}")
    private String stringWithDefaultValue;

    如果默认值设为空,也将会被设置成默认值。

    @Value("${some.key:}")
    private String stringWithBlankDefaultValue;

1.2 基本类型设置默认值

    布尔类型
    @Value("${some.key:true}")
    private boolean booleanWithDefaultValue;

    数字类型
    @Value("${some.key:42}")
    private int intWithDefaultValue;

1.3 包装类型设置默认值

    布尔类型
    @Value("${some.key:true}")
    private Boolean booleanWithDefaultValue;

    数字类型
    @Value("${some.key:42}")
    private Integer intWithDefaultValue;

1.4 数组的默认值使用逗号分割

    @Value("${some.key:one,two,three}")
    private String[] stringArrayWithDefaults;

    @Value("${some.key:1,2,3}")
    private int[] intArrayWithDefaults;

1.5 使用 Spring Expression Language (SpEL) 设置默认值

    @Value("#{systemProperties['some.key'] ?: 'my default system property value'}")
    private String spelWithDefaultValue;

    这表示:在systemProperties属性文件中,如果没有设置 some.key 的值,my default system property value 会被设置成默认值。

Jersey相关

这里记录Jersey相关的内容

Jersey常用方法

jersey获取各个参数的总结

查看Jersey REST服务的WADL服务定义

查看WADL服务定义通过下方URL即可访问到。

http://ip:port/应用根路径/application.wadl

Json解析相关

这里主要解析Json解析相关的技术点。

Jackson整理

  1. 在Jackson中将JsonNode转换为Object

    mapper.convertValue(jsonNode, MyPojo.class)

  2. Jackson中的TypeReference

    一般情况下如果没有TypeReference的话,JsonNode转换过来的是LinkedHashMap而不是对象本身,因此

    需要使用TypeReference来进行Json的解析

    如:

    List<TableColumns> columns = mapper.convertValue(params.get("columns"), new TypeReference<List<TableColumns>>() {});
    
    对于复杂Json的转换,需要通过TypeReference解析,TypeReference可以正确反序列化嵌套多层的List或Map,例如List<Map<String,String>>

    举个实际的例子,

    Map<String, MarkDetail> markDetailMap = objectMapper.convertValue(haveMarkDetails, new TypeReference<Map<String,MarkDetail>>() {});
    
    Map<String, String> dataDetailMap = objectMapper.convertValue(dataDetailJsonNode, new TypeReference<Map<String, String>>() {});

    可以看到,convertValue的第二个参数是一个TypeReference实例。通过这种方式能够将复杂json类型进行正确解析。

版权声明:

原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。

原文  http://wuwenliang.net/2019/12/02/我的编码备忘录/
正文到此结束
Loading...