文章目录
- 1. JVM参数
- 2. Atomic
- 3. 日志
- 4. BUG分析
- 5. HTTP状态码
- 6. JDBC连接池
- 7. IDEA使用 @Autowired和@Resource时报错
- 8. 基于用户id查询用户权限
- 9. 参数取值兼容JDK5
- 10. 克隆项目注意事项
- 11. 序列化ID
- 12 设计模式
- 13 JDK和JVM版本
- 14 Hash一致性算法
- 15 单元测试导包问题
- 16 Json字符串 Java对象 object 互转
- 17 String 相关
- 18 mapper.xml中SQL关键字处理方案
- 19 求绝对值
- 20 ID发号器
- 21 数值操作
- 22 @Autowired,@Qualifier,@Resource
- 23 Mybatis---MySQL
- 24 根据某个属性进行分组
- 25 时间相关 Date and Calendar
- 26 Java定时任务
- 27 Arrays相关
- 27.1 List
- 27.2 Arrays
- 27.2.1 判断两个集合中元素是否完全相同
- 27.3 Collections
- 27.3.1 将List中的某一个元素移动到指定位置
- 28 Java transient 关键字
- 29 java RedisTemplate opsForValue().setIfAbsent()分布式锁的使用
- 30 IDEA
- 31 多线程
- 32 使用异步处理方法
- 33 产生随机数
- 34 连接阿里云redis
- 35 maven将本地jar包打入本地仓库
- 36 Linux查看防火墙状态及开启关闭命令
- 37 查看接口qps
- 38 idea启动报错: lang.OutOfMemoryError: GC overhead limit exceeded
- 39 读取本地文件字符串内容
- 40. java读取EXCEL数据变成科学计数法
1. JVM参数
1 . 类加载:
-XX:+TraceClassLoading
2 . gc :
-Xmx100m -Xms100m -XX:+PrintGC
3 . sentinle控制台标识网关服务
-Dcsp.sentinel.app.type=1
2. Atomic
Atomic:Atomic 包是 JUC 下得另一个专门为线程安全设计的 Java 包,包含多个原子操作类.
3. 日志
3.1 日志级别
trace<debug<info<warn<error
3.2 使用日志
- 依赖:
lombok
- 类上添加
@Slf4j
- 使用:
log.info("xxxxx")
4. BUG分析
- 401 : 访问资源时没有认证。
- 403 : 访问资源时没有权限。
- 404:访问的资源找不到(一定要检查你访问资源的url)
- 405: 请求方式不匹配(客户端请求方式是GET,服务端处理请求是Post就是这个问题)
- 500: 不看后台无法解决?(error,warn)
5. HTTP状态码
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
6. JDBC连接池
Spring Boot 使用 HikariCP
作为其默认数据源.
@ConditionalOnMissingBean(DataSource.class) 的含义是:当容器中没有 DataSource(数据源类)时,Spring Boot 才会使用 HikariCP 作为其默认数据源
JDBC连接池有一个标准的接口javax.sql.DataSource,注意这个类位于Java标准库中,但仅仅是接口。要使用JDBC连接池,我们必须选择一个JDBC连接池的实现。
常用的JDBC连接池有:
- HikariCP
- C3P0
- BoneCP
- Druid
7. IDEA使用 @Autowired和@Resource时报错
使用IDEA工具时使用@Resource和@Autowired自动注解bean时会显示红色,但是项目能运行.
解决方法:
File – Settings – Inspections。在Spring Core – Autowring for Bean Class 中将Severity的级别由之前的error改成warning。
8. 基于用户id查询用户权限
建议使用方式三多表联查,效率高.
#基于用户id查询权限
# 1. 单表查询
# 1.1 根据用户id查询角色id
SELECT role_id from tb_user_roles WHERE user_id=1
# 1.2 根据角色id查询菜单id
SELECT menu_id FROM tb_role_menus WHERE role_id = 1
# 1.3 根据菜单id查询权限
SELECT permission from tb_menus WHERE id in(1,2,3)
# 2. 嵌套查询
SELECT permission from tb_menus where id in(SELECT menu_id from tb_role_menus where role_id=(SELECT role_id from tb_user_roles where user_id=#{userId}))
# 3. 多表联查
select distinct m.permission from tb_role_menus rm join tb_user_roles ur on rm.role_id = ur.role_id join tb_menus m on m.id = rm.menu_id where ur.user_id= #{userId}
9. 参数取值兼容JDK5
当用 RESTful方式接收参数时,需要考虑兼容 JDK5 ,使用 @PathVariable 注解时,需要添加参数名用于兼容.
@PathVariable("username") String username
10. 克隆项目注意事项
1 . git命令直接克隆
2 . 通过idea打开该项目
2.1 配置maven
2.2 配置jdk编码环境
2.3 配置文件编码方式
3 . 初始化数据库中的数据
3.1 cmd登录mysql
3.2 执行命令 source sql文件路径+文件全名
4. 启动该服务
11. 序列化ID
在实体类里面 实现 java.io.Serializable 接口,然后选中实体类名称 使用快捷键 Alt + Enter自动生成标识符ID
注意事项:
为了确保错误,需要显示的提供序列化版本标识符。虽然类实现了接口会分配标识符,但是会出现一个问题:如果类对象序列化后,我们修改了类,那么系统会重新分配标识符,此时之前序列化的数据因为标识符和新分配的标识符不一致就会导致反序列化失败。
12 设计模式
12.1 享元模式
所有的池设计模式都是享元模式
12.2 策略模式
对行为进行策略实现
例:负载均衡(行为)–>算法(策略)
12.3 工厂模式
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
13 JDK和JVM版本
JDK :1.8
JVM: HotSpot 64-Bit Server VM
14 Hash一致性算法
Object顺时针寻找最近的一个Node(节点)进行存储,当添加节点时,只需挪动其中部分Object即可.
但是当删除节点时,会导致分布不均匀问题
在一致性Hash算法中,为了尽可能的满足平衡,其引入了虚拟节点
15 单元测试导包问题
15.1 非Spring Boot工程
引包:
import org.junit.Test
单元测试方法必须用public修饰,不写参数
15.2 Spring Boot工程
引包:
import org.junit.jupiter.api.Test
单元测试方法不用写方法修饰符,不写参数
16 Json字符串 Java对象 object 互转
例:map和jaon串互转
16.1 Gson(谷歌)
需要添加gson依赖
Gson gson = new Gson(); //构建对象
String json = gson.toJson(map); //map转json
map = gson.fromJson(json, Map.class); //json转map
16.2 Jackson(Spring)
spring-boot-starter-web依赖自带jackson(spring御用)
ObjectMapper objectMapper = new ObjectMapper(); //构建对象
String jsonStr = objectMapper.writeValueAsString(map); //map转json
map = objectMapper.readValue(jsonStr1,Map.class); //json转map
16.3 fastjson(阿里)
需要添加fastjson依赖
String jsonString = JSON.toJSONString(map); //map转json
map = JSON.parseObject(jsonString, Map.class); //json转map
16.4 object转Java对象
//1.
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.convertValue(object, User.class);
//2.
User user = JSON.parseObject(JSON.toJSONString(object) , User.class);
16.5 object对象 转 jsonarray数组
JSONArray list = JSON.parseArray(JSON.toJSONString(response.getData()));
17 String 相关
17.1 StringUtils String工具类
导包
import org.apache.commons.lang.StringUtils;
或
import org.apache.commons.lang3.StringUtils;
17.1.1 判断当前字符串是否为空
isBlank方法:
StringUtils.isBlank(null) = true
StringUtils.isBlank("") = true
StringUtils.isBlank(" ") = true
isEmpty方法
StringUtils.isEmpty(null) = true
StringUtils.isEmpty("") = true
StringUtils.isEmpty(" ") = false
17.2 String方法
17.2.1 从指定字符后截取
String.substring(String.lastIndexOf("/") + 1 );
17.2.2 replace和replaceAll的区别以及用法
-
replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);
-
replaceAll的参数是regex,即基于规则表达式的替换,比如:可以通过replaceAll(“\d”, “*”)把一个字符串所有的数字字符都换成星号;
相同点:都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串;
不同点:replaceAll支持正则表达式,因此会对参数进行解析(两个参数均是),而replace则不会解析为正则。
17.3 Object 转String
报错:java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
解决方案:
String[] y = x.toArray(new String[x.size()]);
17.4 StringJoiner类
实际上是运用了StringBuilder的一个拼接字符串
的封装处理。
//间隔符 前缀 后缀
StringJoiner sj = new StringJoiner(":", "[", "]");
sj.add("George").add("Sally").add("Fred");
String desiredString = sj.toString(); //[George:Sally:Fred]
// 间隔符
StringJoiner sj = new StringJoiner(",");
sj.add("123").add("456");
System.out.println(sj.toString()); //123,456
18 mapper.xml中SQL关键字处理方案
如果表名或者字段名使用了sql关键字,那么在mapper.xml中写sql语句的时候,要把表名或字段名添加反引号(`表名(字段名)`)
<insert id="create">
<!-- 因为在sql中 order by 是关键字,所以这里的order表名要添加反引号 -->
INSERT INTO `order` (`id`,`user_id`,`product_id`,`count`,`money`,`status`)
VALUES(#{id}, #{userId}, #{productId}, #{count}, #{money},1);
</insert>
19 求绝对值
如果生成的随机数存在负数,可以使用 Math.abs()
方法,取绝对值
20 ID发号器
在分布式事务中,防止相同服务的多张表id冲突,使用全局唯一ID发号器
使用 雪花算法或者数据库生成 两种方案
21 数值操作
21.1 BigDecimal 进行数值比较
BigDecimal a 和 BigDecimal b 进行比较
方法: a.compareTo(b)
返回值:
正数,表示a大
负数,表示a小
0,表示相同
21.2 Object 转 Double
Object number=10;
double douNumber1=Double.parseDouble(number.toString());
21.3 Double保留两位小数
Double sum = 0.0;
BigDecimal bigDecimal = new BigDecimal(sum).setScale(2, RoundingMode.HALF_UP);
double newSum = bigDecimal.doubleValue();
22 @Autowired,@Qualifier,@Resource
一般@Autowired和@Qualifier一起用,@Resource单独用。
当然没有冲突的话@Autowired也可以单独用
@Autowired:默认按类型
装配(这个注解是属业spring的),当同类型由多个时需要使用@Qualifier修饰
@Resource:默认按照名称
进行装配,可以通过name和type
属性进行选择性注入(这个注解属于J2EE的)
23 Mybatis—MySQL
mysql体系结构: 连接层、服务层、引擎层、存储层
23.1 if-else语法
<choose>
<when test="User != null and User != '' ">
and u.user = #{User}
</when>
<otherwise>
and u.user != '0'
</otherwise>
</choose>
23.2 id回显
例:
<!-- -->
<insert id="add" keyProperty="id" useGeneratedKeys="true" parameterType="compojo">pojo
insert into se (os,id,version,surlu,aurl,upload_time,modify_time) values (#{os},#{Id},#{version},#{sUrl},#{aUrl},now(),now());
</insert>
用法:
在
insert
标签中添加 keyProperty=“JAVA对象主键字段”,useGeneratedKeys=”true”
23.3 获取前一天日期
curdate() : 今天
# 获取昨天日期
date_sub(curdate(),interval 1 day)
23.4 获取当前时间,时间比较
//获取当前时间 2022-04-02 13:50:08
new()
//时间比较 发布时间小于等于当前时间
m.publish_time <= now()
23.5 数据比较
//比较的时候,如果使用参数作为比较符时,使用$拼接
m.publish_time $ {publishSts} now()
23.6 sql语句中大于号、小于号、大于等于、小于等于号的写法
<: <
<=: <=
>: >
>=: >=
23.7 模糊查询
<if test="name != null and name !=''">
and (u.username like concat( '%',#{name},'%') or u.login_id like concat( '%',#{name},'%'))
</if>
23.8 防止添加重复数据以及删除重复数据
23.8.1 删除重复数据
每日凌晨会插入一条比例,由于重复执行sql,导致大量数据重复插入,需要删除重复数据只保留一条
# 方法一 查出重复数据 直接删除
delete from ad_link where id in (
select id from (select id from ad_link where date = '2022-04-26' GROUP BY id HAVING count(*) >1) tmp )
# 方法二 把去重的数据查出来 放到一张临时表中 清空原有表 把临时表数据写入到原有表
CREATE TABLE tmp SELECT * FROM ad_link GROUP BY id , date ;
DROP TABLE ad_link;
ALTER TABLE tmp RENAME TO ad_link;
23.8.2 防止添加重复数据
由于多个项目同时连接一个数据库,会同时触发定时任务,导致数据库数据重复添加
解决办法1
: 使用@ConditionalOnProperty
注解 , 参考该文章https://blog.csdn.net/abcd741258358/article/details/125799197?spm=1001.2014.3001.5501
解决办法 2
:
- 根据业务在数据库表添加复合主键 , 如果你设置了复合主键,那么那个键的默认值不能为 NULL,可设置为 NOT NULL
- 把定时任务新增sql语句 INSERT INTO 修改为 INSERT IGNORE INTO
INSERT IGNORE INTO 与 INSERT INTO
的区别就是 INSERT IGNORE INTO 会忽略数据库中已经存在的数据,如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据。
这样就可以保留数据库中已经存在数据,达到在间隙中插入数据的目的。
INSERT IGNORE INTO
当插入数据时,在设置了记录的唯一性后,如果插入重复数据,将不返回错误,只以警告形式返回。 而 REPLACE INTO
如果存在 primary 或 unique 相同的记录,则先删除掉。再插入新记录
23.9 分页查询
23.9.1 不使用分页插件的分页操作
MySQL中有对分页的支持,是通过limit子句
# 每页5条记录,取第一页,返回的是前5条记录
select * from tableA limit 0,5;
# 每页5条记录,取第二页,返回的是第6条记录,到第10条记录
select * from tableA limit 5,5;
# 通用
select * from tableA limit (pageNum-1) * pageSize , pageSize ;
23.9.2 分页插件PageHelper
注意:只有紧跟着PageHelper.startPage(pageNum,pageSize)的sql语句才被pagehelper起作用
- 添加 依赖
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
- 定义page类
@Data
@Accessors(chain = true)
public class Pager<T> {
private long total;
private List<T> items;
}
- serverImpl 实现类
//开启分页
//注意:只有紧跟着PageHelper.startPage(pageNum,pageSize)的sql语句才被pagehelper起作用
PageHelper.startPage(pageNum, pageSize);
// ---- 执行查询的sql
List<User> list = userMapper.select()
//封装返回数据
PageInfo<User> pageInfo = new PageInfo<>(list);
return new Pager<User>().setItems(pageInfo.getList()).setTotal(pageInfo.getTotal());
23.10 mysql自增ID的起始值修改
- 修改主键id起始值
# 许多时候希望table中数据的id不要从1开始,像qq, id从10000开始,代码如下
# 一定要设置为primary key
alter table 表名 AUTO_INCREMENT=10000;
- 恢复主键id从默认值开始自增
# 注意:这个命令会清空数据包记录!
TRUNCATE TABLE 表名
24 根据某个属性进行分组
for (SVo sVo : list) {
Integer Id = sVo.getId();
if (map.containsKey(Id)){ //存在
List<SVo> sList = map.get(Id);
//将自己追加到其中
sList.add(sVo);
}else { //不存在: 准备List集合,将自己作为第一个元素封装
List<SVo> sList = new ArrayList<>();
sList.add(sVo);
map.put(Id, sList);
}
}
return map;
25 时间相关 Date and Calendar
25.1 Date
25.1.1 获取上个月
/**
* 获取当前月份的上个月
*/
public static String getLastMonth() {
LocalDate today = LocalDate.now();
today = today.minusMonths(1);
DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM");
return formatters.format(today);
}
25.1.2 获取当天日期
LocalDate now = LocalDate.now(); // 2022-02-21
String today = String.valueOf(now); // 2022-02-21
25.1.3 获取当前年月日时分秒,时间早晚比较
//获取当前年月日时分秒
SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now = time.format(new Date());
//时间早晚比较
beginTime.compareTo(endTime) < 0时,开始时间小于结束时间
25.1.4 获取指定日期的上一天或下一天 上个月或下个月 上一年和下一年
DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
try {
Date temp = dft.parse("传入的日期字符串");
Calendar cld = Calendar.getInstance();
cld.setTime(temp);
//获取指定日期的上一天或下一天 上一天就 -1 下一天就 1
cld.add(Calendar.DATE, 1);
//获取指定日期的上一月或下一月 那月今日 如果为月底会自动转换为当月最后一天
//cld.add(Calendar.MONTH, 1);
//获取指定日期的上一年或下一年 那年今日
//cld.add(Calendar.YEAR, 1);
temp = cld.getTime();
//获得目标日期字符串
String nextDay = dft.format(temp);
} catch (ParseException e) {
e.printStackTrace();
}
25.1.5 获取两个日期之间的所有天数
/**
* 获取两个日期之间的所有天数
* @param startDate
* @param endDate
* @return
*/
private List<String> getDaysDiff(String startDate, String endDate) {
LocalDate start = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate end = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
long numOfDaysBetween = ChronoUnit.DAYS.between(start, end);
List<LocalDate> collect = IntStream.iterate(0, i -> i + 1)
.limit(numOfDaysBetween)
.mapToObj(start::plusDays)
.collect(Collectors.toList());
List<String> dateList = collect.stream().map(localDate -> localDate.format(df)).collect(Collectors.toList());
//该list没有最后一天,所以此处加上最后一天
dateList.add(endDate);
return dateList;
}
25.2 Calendar日历类
Calendar:它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法。
Calendar(日历类) – 获取年,获取月,获取日,获取时,获取分,获取秒。
- public int get(int field):返回给定日历字段的值
import java.util.Calendar;
public class CalendarDemo {
public static void main(String[] args) {
/**
* 创建对象的方法:
* 1.new 类名();
* 2.有一些类是抽象类,他为我们提供了一个成员方法,
* 而这个成员方法的返回值就是这个抽象类的子类对象
*/
Calendar c = Calendar.getInstance();
//获取年份
System.out.println(c.get(Calendar.YEAR));
//获取月份,注意默认月份值是从0-11月,
//我们想要显示的更加符合我们的阅读规则,就必须手动给月份加上1
System.out.println(c.get(Calendar.MONTH)+1);
//获取日期
System.out.println(c.get(Calendar.DATE));
//获取时
System.out.println(c.get(Calendar.HOUR));
//获取分
System.out.println(c.get(Calendar.MINUTE));
//获取秒数
System.out.println(c.get(Calendar.SECOND));
}
}
- public void add(int field,int amount):根据amount修改field的值
public void set(int year,int month,int date):设置当前日历的年月日
package edu.calendar;
import java.util.Calendar;
//需求:获取当前时间的5年后的3个月前的7天后。
public class CalendarDemo2 {
public static void main(String[] args) {
//创建日历对象
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR, 5);
c.add(Calendar.MONTH, -3);
c.add(Calendar.DATE, 7);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH)+1);
System.out.println(c.get(Calendar.DATE));
// public void set(int year,int month,int date):设置当前日历的年月日
c.set(2016, 9, 9);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH)+1);
System.out.println(c.get(Calendar.DATE));
}
}
25.3 java 时间参数注解@DatetimeFormat和@JsonFormat
- 注解@JsonFormat(出参格式化)
@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
- 注解@DateTimeFormat(入参格式化)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
25.4 LocalDateTime和Date相互转换
25.4.1 Date to LocalDateTime
Date todayDate = new Date();
LocalDateTime ldt = todayDate.toInstant()
.atZone( ZoneId.systemDefault() )
.toLocalDateTime();
System.out.println(ldt);
//2019-05-16T19:22:12.773
25.4.2 LocalDateTime to Date
LocalDateTime localDateTime = LocalDateTime.now();
Date date = Date.from( localDateTime.atZone( ZoneId.systemDefault()).toInstant());
System.out.println(date);
//Thu May 16 19:22:37 CST 2019
26 Java定时任务
//在方法上添加@Scheduled(cron = "")注解
//corn代表定时时间表达式
//此例代表 每天上午九点1分执行
@Scheduled(cron = "0 1 9 * * ?")
//如果想在项目启动的时候就执行一次,就额外添加 @PostConstruct注解
@PostConstruct
27 Arrays相关
27.1 List
27.1.1 All elements are null
mysql查询结果为空,但是返回值为List,此时list内容为All elements are null
移除null值,判断list不为空的时候再添加到另一个list(最后返回的数据)
List<App> list = dashboardMapper.getById(user);
list.remove(null);
if (!CollectionUtils.isEmpty(list)){
appList.addAll(list);
}
27.1.2 list排序
27.1.2.1 List存储的是对象,需要根据对象的某个属性进行排序
方法一:Comparator.comparing
//正序
List<AVo> result = responseVos.stream().sorted(Comparator.comparing(AVo::getU)).collect(Collectors.toList());
// reversed() 倒序
List<AVo> result = responseVos.stream().sorted(Comparator.comparing(AVo::getU).reversed()).collect(Collectors.toList());
方法二:Collections.sort
Collections.sort(list, new Comparator<TestA>() {
@Override
public int compare(TestA o1, TestA o2) {
//升序
return o1.getAge().compareTo(o2.getAge());
}
});
Collections.sort(list, new Comparator<TestA>() {
@Override
public int compare(TestA o1, TestA o2) {
//降序
return o2.getAge().compareTo(o1.getAge());
}
});
27.1.2.2 list里边存的是字符串格式的日期 按照顺序排序
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("2022-11-02");
list.add("2022-12-01");
list.add("2022-12-31");
list.add("2022-10-28");
list.add("2022-05-15");
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = format.parse(o1);
Date d2 = format.parse(o2);
//正序
return d1.compareTo(d2);
// 倒序
return d2.compareTo(d1);
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
});
//[2022-05-15, 2022-10-28, 2022-11-02, 2022-12-01, 2022-12-31]
System.out.println(list);
}
27.1.2.3 list里边存的是字符串或者数字 正序或者倒序排序
List<String> list = new ArrayList<>();
list.add("1");
list.add("5");
list.add("2");
list.add("8");
//正序 如果为数字--> 则 Integer::compareTo
list.sort(String::compareTo);
//元素反转 如果需要倒序则先正序然后再反转元素
Collections.reverse(list);
27.1.3 List存储的是对象,需要根据对象的某个属性进行求和
list.stream().mapToDouble(user::getAge).sum();
27.1.4 List存储的是对象,需要把对象的某个属性单独拿出来存到list中
List<String> Ids = appList.stream().map(AVo::getId).collect(Collectors.toList());
27.1.5 把两个Lit中id相同的对象进行数据合并
List<PVo> uList = pMapper.getYe(tableName,pIds);
for (PVo responseVo : responseVos) {
Optional<PVo> first = uList.stream().filter(a -> Objects.equals(responseVo.getId(), a.getId())).findFirst();
if (first.isPresent()) {
PVo pVo = first.get();
responseVo.setUnitRevene(pVo.getUe());
}
}
27.1.6 数组转list
此list 不能调用 remove、add等方法 默认throw UnsupportedOperationException而且不作任何操作。
List<String> IdList = Arrays.asList(earlyVo.getIds().split(","));
如果需要调用相关方法, 需要调用ArrayList的构造方法
List<String> list = new ArrayList<>(IdList );
27.1.7 list截取指定长度,排序后获取分页数据
long start = (vo.getPage() - 1) * vo.getLimit();
long end = (start + vo.getLimit()) > list.size() ? list.size() : (start + vo.getLimit());
if (start > list.size()) {
return null;
}
if (org.apache.commons.lang.StringUtils.isEmpty(vo.getSortBy())) {
return list.stream().sorted(Comparator.comparing(AVo::getCreateTime).reversed()).collect(Collectors.toList()).subList((int) start, (int) (end));
}
List<AVo> result ;
if ("desc".equals(vo.getSortOrder())) {
result = list.stream().sorted(Comparator.comparing(o1 -> o1.getData().getIe())).collect(Collectors.toList());
Collections.reverse(result);
} else {
result = list.stream().sorted(Comparator.comparing(o1 -> o1.getData().getI())).collect(Collectors.toList());
}
return result.subList((int) start, (int) (end));
27.1.8 List集合异常:list All elements are null
//移除所有的null元素
list.removeAll(Collections.singleton(null));
27.1.9 list取交集
// list1 剩下交集部分
list1.retainAll(list2);
27.2 Arrays
27.2.1 判断两个集合中元素是否完全相同
boolean falg = Arrays.deepEquals(list1.toArray(), list2.toArray());
27.3 Collections
27.3.1 将List中的某一个元素移动到指定位置
// list是需要换位置的List
// a是你当前需要换位置的元素的索引
// b是你需要将这个元素换到哪个索引
Collections.swap(list,a,b)
28 Java transient 关键字
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问
。
2)transient关键字只能修饰变量
,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
29 java RedisTemplate opsForValue().setIfAbsent()分布式锁的使用
需要每日凌晨更新数据库,为了防止多个服务重复操作,引入分布式锁,需要使用同一个redis
//添加分布式锁,一天过期, 重复添加锁会返回false
String today = DateUtils.getDateStr();
Boolean b = redisTemplate.opsForValue().setIfAbsent(SS_ + today, today, 1, TimeUnit.DAYS);
30 IDEA
30.1 IDEA实现同一个启动类利用不同端口启动多服务
启动两个端口,一个端口自己debug调试,一个端口给前端联调
- 点击进入编辑
2.开启 Allow parallel run(允许多例运行),并修改jvm参数(指定端口)
-Dserver.port=8888
30.2 IDEA使用mybatis逆向工程
31 多线程
31.1 多线程 无法 注入Bean 原因
多线程 无法 注入Bean 原因: 在 spring 中,如果需要在异步 线程 中 注入bean ,会发现 bean 是空的 情况 。 原因据说是 spring bean 出于 线程 安全考虑,不得 注入bean 至 线程 类(Runnable接口的派生类)
可以在使用多线程的地方把bean传进去
32 使用异步处理方法
- 在方法上添加注解
@Async
, 并且方法没有返回值, - 该方法不能和调用者存在于同一个类中,新写一个类然后注入到调用的类中.
- 在主启动类上添加注解
@EnableAsync
注意: 如果第二步没完成,项目会启动失败并报错,报错如下
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.
33 产生随机数
Random:用于产生随机数的类
构造方法:
Random():没有指定种子,采用的是默认种子。
Random(long seed):可以指定种子。种子相同,产生的随机数就相同。
成员方法:
public int nextInt():返回int范围内的数据
public int nextInt(int n):返回[0,n)之间的整型数据
得到1-100之间的随机数:new Random().nextInt(100) + 1
import java.util.Random;
//利用有参、无参构造创建随机数生成器,产生5个大小在[0,10)随机数,并比较二者的不同
public class RandomDemo {
public static void main(String[] args) {
//利用有参、无参构造创建随机数生成器
Random rd0 = new Random();
Random rd1 = new Random(2);
//无参,产生10个随机数
for (int i = 0; i < 10; i++) {
System.out.print(rd0.nextInt(10)+" ");
}
System.out.println();
//有参,产生10个随机数
for (int i = 0; i < 10; i++) {
System.out.print(rd1.nextInt(10)+" ");
}
}
// 第一次运行
/**
* 6 0 0 2 0 3 5 9 0 3
8 2 0 7 9 0 6 9 7 8
*/
// 第二次运行
/**
* 2 5 3 2 9 6 2 7 1 9
8 2 0 7 9 0 6 9 7 8
*/
// Random():没有指定种子,采用的是默认种子。每次产生的都不一样
// Random(long seed):可以指定种子。种子相同,产生的随机数就相同。
}
34 连接阿里云redis
- 服务器需安装redis-cli客户端
- 进入redis-cli安装目录
- redis-cli -h redis服务Ip -p 6379
35 maven将本地jar包打入本地仓库
mvn install:install-file -DgroupId=org.xl.brave
-DartifactId=brave-axis2 -Dversion=0.0.1
-Dfile=C:\Users\sy\Desktop\brave-axis2-0.0.1-SNAPSHOT.jar
-Dpackaging=jar
36 Linux查看防火墙状态及开启关闭命令
37 查看接口qps
查看该文件 /log/adv_request接口 第三列不一样的数量(第三列是时间年月日时分秒)
tail -f saas-tracker.access.log.2023-04-04_16 | grep /log/adv_request | awk -F '\t' '{print3}' | uniq -c
38 idea启动报错: lang.OutOfMemoryError: GC overhead limit exceeded
修改build内存,默认是700M , 按照需要修改
39 读取本地文件字符串内容
BufferedReader reader = new BufferedReader(new FileReader("D:\\File\\File\\1.txt"));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
String ls = System.getProperty("line.separator");
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
// 删除最后一个新行分隔符
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
reader.close();
String content = stringBuilder.toString();
40. java读取EXCEL数据变成科学计数法
BigDecimal bd = new BigDecimal("读到的值");
String checkValue = bd.toPlainString();