JAVA一些编程技巧

1.Array转ArrayList

当Array转化为AarrayList

List list = Arrays.asList(arr);

Arrays.asList()会返回一个ArrayList,但是要特别注意,这个ArrayList中Arrays类的静态内部类,并不是java.util.ArrayList类。  

java.util.ArrayList类实现了set(),get(),contain()方法,但并没有实现增加元素的方法()(事实上是可以调整add方法,但是没有具体实现,仅仅抛出UnsupportedoperationException异常),因此他的大小也是固定不变的。

2.判断一个数组是否含某个值

在此需求下经常使用set集合,但效率不高,可以使用asList,

Arrays.asList(arr).contains(targetValue)

3.在循环内部删除list的一个元素

错误方法:

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c","d"));
for( int i = 0; i < list.size(); i++) {
    list.remove(i);
}
System.out.println(list);

 在上面这个方法中有一系列的问题,当一个元素被删除的时候,list大小减小,然后原先索引指向了其它元素。所以如果你想在循环里通过索引来删除多个元素,将不会正确工作。

错误方法:

ArrayList list = new ArrayList(Arrays.asList("a", "b", "c","d"));
for(String s : list) {
    if(s.equals("a"))
        list.remove(s);
}

将抛出ConcurrentModificationException异常。

查看构造器next()代码:

       public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

其中报错的关键在于checkForComodification():

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
 }

其中modCount表示集合的修改次数,这其中包括了调用集合本身的add方法等修改方法时进行的修改和调用集合迭代器的修改方法进行的修改。而expectedModCount则是表示迭代器对集合进行修改的次数。当调用迭代器时,而用list本身的remove()方法,则迭代器和集合的修改次数不一致,导致报错。

4.Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。

5.循环体内,字符串的连接方式,使用 StringBuilder append 方法进行扩展。

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

7.集合初始化时,指定集合初始值大小。HashMap 需要放置 1000 个元素,由于没有设置容量初始大小,随着元素不断增加,容 量数次被迫扩大,resize 需要重建 hash 表,严重影响性能。

8.使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key value 都放到了 entry 中,效率更高。

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

例:

1FixedThreadPool SingleThreadPool:

允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM

2CachedThreadPool ScheduledThreadPool:

允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM

10.对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造 成死锁。

11.HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在 开发过程中可以使用其它数据结构或加锁来规避此风险。

12.异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。

13.对大段代码进行 try-catch,这是不负责任的表现。catch 时请分清稳定代码和非稳 定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分 异常类型,再做对应的异常处理。

14.arrayList的subList函数,返回的list仅仅是一个试图,当对subList进行操作时会对原list也进行修改

你可能感兴趣的:(java基础)