Java 需要注意的地方

1.ArrayList源码分析

线程非安全性

对ArrayList的操作一般分为两个步骤,改变位置(size)和操作元素(e)。

transient关键字解析

Java中transient关键字的作用,简单地说,就是让某些被修饰的成员属性变量不被序列化。

 transient Object[] elementData;

 private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }

        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

//克隆数据低层调用
 System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));

ArrayList在序列化的时候会调用writeObject()方法,将sizeelement写入ObjectOutputStream;反序列化时调用readObject(),从ObjectInputStream获取sizeelement,再恢复到elementData。 

原因在于elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量,那么有些空间可能就没有实际存储元素,采用上诉的方式来实现序列化时,就可以保证只序列化实际存储的那些元素,而不是整个数组,从而节省空间和时间

ArrayList优缺点

优点:

  1. 因为其底层是数组,所以修改和查询效率高。

  2. 可自动扩容(1.5倍)。

缺点:

  1. 插入和删除效率不高。

  2. 线程不安全。

2.HashMap源码分析

数据结构

插入效率比平衡二叉树高,查询效率比普通二叉树高。所以选择性能相对折中的红黑树。

备注:为什么是8,6?个人认为7是临界点 3层深度,在临界点加减1.

//检查链表长度是否达到阈值,达到将该槽位节点组织形式转为红黑树
if (binCount >= TREEIFY_THRESHOLD - 1) 
    treeifyBin(tab, hash);


static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
    //构造函数
    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }
}

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;
    TreeNode(int hash, K key, V val, Node<K,V> next) {
        super(hash, key, val, next);
    }

    /**
     * Returns root of tree containing this node.
     */
    final TreeNode<K,V> root() {
        for (TreeNode<K,V> r = this, p;;) {
            if ((p = r.parent) == null)
                return r;
            r = p;
        }
    }
}
//通过移位和异或运算,可以让 hash 变得更复杂,进而影响 hash 的分布性。
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

备注:tab[index = (n - 1) & hash]----解释了为什么需要2的次幂作为数组的容量。由于n是2的次幂,因此,n-1类似于一个低位掩码。通过与操作,高位的hash值全部归零,保证低位才有效 从而保证获得的值都小于n。(还有就是扩容不是原索引就是原索引+原容量)

但是,使用了该功能之后,由于只取了低位,因此 hash 碰撞会也会相应的变得很严重。这时候就需要使用「扰动函数」^ (h >>> 16)该函数通过将哈希码的高16位的右移后与原哈希码进行异或而得到。此方法保证了高16位不变, 低16位根据异或后的结果改变。

   01010011 00100101 01010100 00100101
&  00000000 00000000 00000000 00001111
---------------------------------------
   00000000 00000000 00000000 00000101    //高位全部归零,只保留末四位  5
    // 保证了计算出的值小于数组的长度 n



   01010011 00100101 01010100 00100101
^  00000000 00000000 01010011 00100101
---------------------------------------
   01010011 00100101 00000111 00000000    //高位不变,低位改变  5->0

 

工作原理

 注意事项

虽然 HashMap 设计的非常优秀, 但是应该尽可能少的避免 resize(), 该过程会很耗费时间。

同时, 由于 hashmap 不能自动的缩小容量 因此,如果你的 hashmap 容量很大,但执行了很多 remove操作时,容量并不会减少。如果你觉得需要减少容量,请重新创建一个 hashmap

友情链接:https://union-click.jd.com/jdc?e=&p=AyIGZRprEwEXDlMca1FdSlkKKwJQR1NFXgVFSVJPWkpADgpQTFtLQwRAVlsbUxheHAQVGAxeB0gyUHcReDJvcXVnInlBcUtMBip6EkJwVAtZK1sVChIFVitbFAMRBlIYWhYGIjdVGGtUbBQEXRJZETISD1ATWBcEEg9XK1sRBBcBURpfFgUXB1IrXBULIkQFQwRGXFRVDE8EQzIiAVYeUhMFIgRlK2sWMhE3Cl8GSDIQBlQfUg%3D%3D

 

少儿编程:https://u.jd.com/W4JUoL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rainbowcheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值