进制转换

二进制转十进制

方法:把二进制数按权展开,相加即得十进制数。

image.png

十进制转二进制

方法:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。

image.png

二进制转八进制

方法:3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。

查看更多

java8总结

Java8总结

/**
* Java8常见操作总结
*/
public class ExampleEmployee {

private static List<Employee> employeeList = new ArrayList<>();

static {
employeeList.add(Employee.builder().name("zhangsan").salary(3000).office("beijing").build());
employeeList.add(Employee.builder().name("lisi").salary(6000).office("shanghai").build());
employeeList.add(Employee.builder().name("wangwu").salary(20000).office("guangzhou").build());
employeeList.add(Employee.builder().name("zhaoliu").salary(8000).office("shenzhen").build());
employeeList.add(Employee.builder().name("qiangqi").salary(8000).office("beijing").build());
employeeList.add(Employee.builder().name("renba").salary(21000).office("beijing").build());
}

public static void main(String[] args) {
// employeeList 是否包含 office="shanghai"
boolean isMatch = employeeList.stream()
.anyMatch(employee -> "shanghai".equals(employee.getOffice()));
System.out.println(isMatch);
System.out.println("-------------------------");

// employeeList 的所有 salary 都大于4000
boolean matched = employeeList.stream()
.allMatch(employee -> employee.getSalary() > 4000);
System.out.println(matched);
System.out.println("-------------------------");

// 工资最高
Optional<Employee> hightSalary = employeeList.stream()
.max((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()));
System.out.println(hightSalary);
System.out.println("-------------------------");

Optional<Employee> hightSalary2 = employeeList.stream()
.max(Comparator.comparingInt(Employee::getSalary));
System.out.println(hightSalary2);
System.out.println("-------------------------");

// 返回姓名集合
List<String> names = employeeList.stream()
.map(Employee::getName)
.collect(Collectors.toList());
System.out.println(names);
System.out.println("-------------------------");

// List 转 Map
Map<String, Employee> employeeMap = employeeList.stream()
.collect(Collectors.toMap(Employee::getName, value -> value));
employeeMap.forEach((key, value) -> {
System.out.println(key + " : " + value);
});
System.out.println("-------------------------");

// 统计 office 是 beijing 的个数
long count = employeeList.stream()
.filter(employee -> "beijing".equals(employee.getOffice()))
.count();
System.out.println(count);
System.out.println("-------------------------");

// List 转换为 Set
Set<String> officeSet = employeeList.stream()
.map(Employee::getOffice)
.collect(Collectors.toSet());
System.out.println(officeSet);
System.out.println("-------------------------");

// 查找 office 是 beijing 的员工
Optional<Employee> allMatchedEmployees = employeeList.stream()
.filter(employee -> "beijing".equals(employee.getOffice()))
.findAny();
System.out.println(allMatchedEmployees);
System.out.println("-------------------------");

// 按照工资的降序来列出员工信息
List<Employee> descEmployeeList = employeeList.stream()
.sorted((e1, e2) -> Integer.compare(e2.getSalary(), e1.getSalary()))
.collect(Collectors.toList());
System.out.println(descEmployeeList);
System.out.println("-------------------------");

// 按照名字的升序列出员工信息
List<Employee> sortEmployeeByName = employeeList.stream()
.sorted(Comparator.comparing(Employee::getName))
.collect(Collectors.toList());
System.out.println(sortEmployeeByName);
System.out.println("-------------------------");

// 获取工资最高的前两名员工信息
List<Employee> top2EmployeeList = employeeList.stream()
.sorted((e1, e2) -> Integer.compare(e2.getSalary(), e1.getSalary()))
.limit(2)
.collect(Collectors.toList());
System.out.println(top2EmployeeList);
System.out.println("-------------------------");

// 获取平均工资
OptionalDouble averageSalary = employeeList.stream()
.mapToInt(Employee::getSalary)
.average();
System.out.println(averageSalary);
System.out.println("-------------------------");

// beijing 办公室平均工资
OptionalDouble averageSalaryByOffice = employeeList.stream()
.filter(employee -> "beijing".equals(employee.getOffice()))
.mapToInt(Employee::getSalary)
.average();
System.out.println(averageSalaryByOffice);
System.out.println("-------------------------");

// Java8 分组操作
Map<String, List<Employee>> groupMap = employeeList.stream()
.collect(Collectors.groupingBy(Employee::getOffice));
System.out.println(groupMap);
}
}

Spring事务

Spring 事务管理 API 分析

Spring 框架中,涉及到事务管理的 API 大约有100个左右,其中最重要的有三个:PlatformTransactionManagerTransactionDefinitionTransactionStatus

所谓事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。

“按照……来执行提交或者回滚操作”便是用 PlatformTransactionManager 来表示,

“给定的事务规则“就是用 TransactionDefinition 表示的,

TransactionStatus 用于表示一个运行着的事务的状态。

查看更多

Redis过期策略

Redis 过期策略

Redis 过期策略是:定期删除 + 惰性删除。

所谓定期删除,指的是 Redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

假设 Redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 Redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难。实际上 Redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。

但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个 key 的时候,Redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。

但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 Redis 内存快耗尽了,怎么办?

查看更多

Redis安全防范

指令安全

Redis 有一些非常危险的指令,这些指令会对 Redis 的稳定以及数据安全造成非常严重的影响。比如 keys 指令会导致 Redis 卡顿,flushdbflushall 会让 Redis 的所有数据全部清空。如何避免人为操作失误导致这些灾难性的后果也是运维人员特别需要注意的风险点之一。

Redis 在配置文件中提供了 rename-command 指令用于将某些危险的指令修改成特别的名称,用来避免人为误操作。比如在配置文件的 security 块增加下面的内容:

rename-command keys abckeysabc

如果还想执行 keys 方法,那就不能直接敲 keys 命令了,而需要键入abckeysabc。 如果想完全封杀某条指令,可以将指令 rename 成空串,就无法通过任何字符串指令来执行这条指令了。

查看更多

java小技巧

java判断对象中属性值是否全为空

/**
* 判断对象中属性值是否全为空
*
* @param object
* @return
*/
public static boolean checkObjAllFieldsIsNull(Object object) throws IllegalAccessException {
if (null == object) {
return true;
}

for (Field f : object.getClass().getDeclaredFields()) {
f.setAccessible(true);
if (f.get(object) != null && StringUtils.isNotBlank(f.get(object).toString())) {
return false;
}
}
return true;
}

Java判断字符串是否为数字(包括浮点类型)

public static boolean isNumber(String str){
String reg = "^[0-9]+(.[0-9]+)?$";
return str.matches(reg);
}

SpringBoot中间件

Spring Boot 和 Redis 常用操作

spring-boot-starter-data-redis

Spring Boot 提供了对 Redis 集成的组件包:spring-boot-starter-data-redis,它依赖于 spring-data-redis 和 lettuce。Spring Boot 1.0 默认使⽤的是 Jedis 客户端,2.0 替换成了 Lettuce,但如果你从 Spring Boot 1.5.X 切换过来,⼏乎感受不⼤差异,这是因为 spring-boot-starter-data-redis 为我们隔离了其中的差异性。

  • Lettuce:是⼀个可伸缩线程安全的 Redis 客户端,多个线程可以共享同⼀个 RedisConnection,它利⽤优秀 Netty NIO 框架来⾼效地管理多个连接。
  • Spring Data:是 Spring 框架中的⼀个主要项⽬,⽬的是为了简化构建基于 Spring 框架应⽤的数据访问,包括⾮关系数据库、Map-Reduce 框架、云数据服务等,另外也包含对关系数据库的访问⽀持。
  • Spring Data Redis:是 Spring Data 项⽬中的⼀个主要模块,实现了对 Redis 客户端 API 的⾼度封装,使对 Redis 的操作更加便捷。
查看更多