常用列表构建方法:
1.ImmutableList.of() : 静态方法、不可变的列表
可以接受任意数量的参数,并将它们作为元素添加到新创建的列表中,但是一旦创建,集合的内容就不能被改变。在多线程环境中非常有用,因为它可以避免并发修改异常,并且可以安全地在多个线程之间共享。
使用 ImmutableList.of() 创建的列表是线程安全的,并且具有高效的性能,因为它们是预先计算和缓存的,这使得访问元素非常快速。
此外,由于列表是不可变的,所以它们是不可变的集合的一个很好的选择,可以作为函数的返回值,或者作为对象的属性,以确保集合的内容不会被外部代码修改。
2.Lists.newArrayList() : 用于快速创建一个空的 ArrayList, 或者从已有的集合或数组中创建一个新的 ArrayList。可变的,可以添加、删除或修改其中的元素。
流中map和flatMap的使用场景
在Java的Stream API中,map 和 flatMap 是两个常用的方法,它们都用于转换流中的元素,但使用场景和转换的方式有所不同。
使用 map 的情况
map 方法用于将流中的每个元素转换成另一种形式或类型,但是它不会改变流中元素的数量。map 通常用于一对一的转换。
例子: 假设你有一个 List 包含员工对象,每个员工对象都有一个 getName() 方法返回员工的名字。如果你想要得到一个包含所有员工名字的 List,你可以使用 map 方法:
List<Employee> employees = ...; // 员工列表 List<String> names = employees.stream() .map(Employee::getName) // 将每个员工对象转换为名字 .collect(Collectors.toList());
使用 flatMap 的情况
flatMap 方法用于将流中的每个元素转换成另一个流,然后将这些流合并成一个流。flatMap 通常用于一对多的转换。
例子: 假设你有一个 List 包含订单对象,每个订单对象都有一个 getItems() 方法返回该订单包含的商品列表。如果你想要得到一个包含所有订单中所有商品的 List,你可以使用 flatMap 方法:
List<Order> orders = ...; // 订单列表 List<Item> items = orders.stream() .flatMap(order -> order.getItems().stream()) // 将每个订单转换为商品列表 .collect(Collectors.toList());
在这个例子中,每个订单可能包含多个商品,flatMap 将每个订单的 getItems() 方法返回的 List<Item> 流化,并合并这些流,最终得到一个包含所有商品的 List<Item>。
总结
- 使用 map 当你需要将流中的每个元素转换成另一个对象或值,且转换是一对一的。
- 使用 flatMap 当你需要将流中的每个元素转换成一个流(或集合),并且想要将这些流合并成一个更大的流,且转换是一对多的。
flatMap 可以看作是 map 和 flatten 的组合,即先映射(map),然后将结果展平(flatten)成一个单一的流。
预编译正则表达式
正则表达式的预编译是指将正则表达式的字符串模式编译成一个 Pattern 对象。编译过程是比较耗时的操作,如果在方法体内定义,每次方法调用时都会重新编译正则表达式,增加了不必要的开销。因此,推荐在类的静态成员中预先编译正则表达式,并在需要时直接使用预编译的 Pattern 对象。
public class XxxClass { // Use precompile private static final Pattern NUMBER_PATTERN = Pattern.compile("[0-9]+"); public Pattern getNumberPattern() { // Return the precompiled pattern return NUMBER_PATTERN; } }
这样修改后,每次调用 getNumberPattern() 方法时都会返回同一个预编译的 Pattern 对象,避免了重复编译的开销,提高了运行效率。
所有的包装类对象之间值的比较,全部使用equals方法比较。
- 对于Integer var=?在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。
Integer a = 235; Integer b = 235; if (a.equals(b)) { // code }
SimpleDateFormat(线程不安全)
在Java 1.8之后,SimpleDateFormat存在线程安全问题,因为它是非线程安全的。多线程环境中使用SimpleDateFormat可能会导致不可预测的结果。
JDK1.8后用:
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
JSON对象转string性能
- List<String>数组,转String对象输出
List<String> list = new ArrayList<>(); for(int i=0; i<2000000; i++){ list.add(RandomString.get().randomAlphaNumeric(5)); } long startone = System.currentTimeMillis(); cn.hutool.json.JSONUtil.toJsonStr(list); long endone = System.currentTimeMillis(); System.out.println("cn.hutool.json.JSONUtil time:"+(endone-startone)); com.alibaba.fastjson.JSON.toJSONString(list); long endtwo = System.currentTimeMillis(); System.out.println("com.alibaba.fastjson.JSON time:"+(endtwo-endone)); com.alibaba.fastjson2.JSON.toJSONString(list); long endthree = System.currentTimeMillis(); System.out.println("com.alibaba.fastjson2.JSON time:"+(endthree-endtwo));
- 100个
- cn.hutool.json.JSONUtil time:14
- com.alibaba.fastjson.JSON time:55
- com.alibaba.fastjson2.JSON time:80
- 1000个
- cn.hutool.json.JSONUtil time:16
- com.alibaba.fastjson.JSON time:55
- com.alibaba.fastjson2.JSON time:85
- 10000个
- cn.hutool.json.JSONUtil time:24
- com.alibaba.fastjson.JSON time:69
- com.alibaba.fastjson2.JSON time:101
- 100000个
- cn.hutool.json.JSONUtil time:75
- com.alibaba.fastjson.JSON time:96
- com.alibaba.fastjson2.JSON time:93
- 1000000个
- cn.hutool.json.JSONUtil time:319
- com.alibaba.fastjson.JSON time:159
- com.alibaba.fastjson2.JSON time:124
- 2000000个
- cn.hutool.json.JSONUtil time:576
- com.alibaba.fastjson.JSON time:255
- com.alibaba.fastjson2.JSON time:132
结论:
- 对于小规模数据的 JSON 序列化任务,Hutool 是一个很好的选择。
- 对于大规模数据的 JSON 序列化任务,建议使用 Fastjson2,以获得更高的性能。