java基础

1.hashCode和equals详解:参见

2.集合初始化时,指定集合初始值大小。

说明:HashMap 使用 HashMap(int initialCapacity) 初始化, 正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。
注意: 负载因子(即 loader factor)默认为 0.75,这个一般不要改
如果暂时无法确定初始值大小,请设置为 16(即默认值)。通常创建一个足够大的map(查找效率会低)比频繁的进行rehsah的性能要好。
反例:HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素不断增加,容量 7 次被迫扩大,resize 需要重建 hash 表,严重影响性能。

高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:

集合类 key value super 说明
Hashtable 不允许为 null 不允许为 null AbstractMap 线程安全
ConcurrentHashMap 不允许为 null 不允许为 null Dictionary 锁分段技术(JDK8:CAS)
TreeMap 不允许为 null 允许为 null AbstractMap 线程不安全
HashMap 允许为 null 允许为 null AbstractMap 线程不安全

由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上, 存储 null值时会抛出 NPE 异常。

泛型通配符来接收返回的数据,此写法的泛型集合不能使用 add 方法,而不能使用 get 方法,做为接口调用赋值时易出错。
说明:扩展说一下 PECS(Producer Extends Consumer Super)原则:第一、频繁往外读取内容的,适合用。第二、经常往里插入的,适合用

使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()。
说明:使用 toArray 带参方法,入参分配的数组空间不够大时,toArray 方法内部将重新分配内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[ list.size() ]的数组元素将被置为 null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出现 ClassCastException 错误。

ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是
ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。
在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生ConcurrentModificationException 异常。

关于 hashCode 和 equals 的处理,遵循如下规则:
1) 只要重写 equals,就必须重写 hashCode。
2) 因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的
对象必须重写这两个方法。
3) 如果自定义对象做为 Map 的键,那么必须重写 hashCode 和 equals。
4 ) String 重写了 hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象作为 key 来使用。

循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
说明:反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。
说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。

在创建新的 Integer 对象之前会先在 IntegerCache.cache 中查找。有一个专门的 Java 类来负责 Integer 的缓存。这个类是用来实现缓存支持,并支持-128到127之间的自动装箱过程。最大值127可以通过JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改。在程序中第一次使用 Integer 的时候也需要一定的额外时间来初始化这个缓存。

定义DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。

说明:POJO 类的 gmtCreate 默认值为 new Date();但是这个属性在数据提取时并没有置入具体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。

POJO 类必须写 toString 方法。如果继承了另一个 POJO 类,注意在前面加一下 super.toString。

说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排 查问题。

线程池不允许使用 Executors 去创建,而是通ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

1)FixedThreadPool SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

  • 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
  • 循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
  • 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
  • 子线程抛出异常堆栈,不能在主线程 try-catch 到。

你可能感兴趣的:(java)