您的位置:首页 > 编程语言 > Java开发

java基础

2017-11-10 17:39 106 查看
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 值的情况,如下表格:

集合类keyvaluesuper说明
Hashtable不允许为 null不允许为 nullAbstractMap线程安全
ConcurrentHashMap不允许为 null不允许为 nullDictionary锁分段技术(JDK8:CAS)
TreeMap不允许为 null允许为 nullAbstractMap线程不安全
HashMap允许为 null允许为 nullAbstractMap线程不安全
由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上, 存储 null值时会抛出 NPE 异常。

泛型通配符
<? extends T>
来接收返回的数据,此写法的泛型集合不能使用 add 方法,而
<? super T>
不能使用 get 方法,做为接口调用赋值时易出错。

说明:扩展说一下 PECS(Producer Extends Consumer Super)原则:第一、频繁往外读取内容的,适合用
<? extends T>
。第二、经常往里插入的,适合用
<? super T>


使用集合转数组的方法,必须使用集合的 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 到。

4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java