• 学习英语第十周至第十一周

    学习英语第十周至第十一周

    阅读英文原著

    Book Time Progress
    Harry Potter And The Goblet of Fire 2014.04.21 ~ 2014.05.04 312/734
    Read More ...
  • Learn English 1011

    学习英语第十周至第十一周

    标签:英语

    阅读英文原著

    Book Time Progress
    Harry Potter And The Goblet of Fire 2014.04.21 ~ 2014.05.04 312/734
    Read More ...
  • 学习英语第十二周

    学习英语第十二周

    标签:英语

    阅读英文原著

    Book Time Progress
    Harry Potter And The Goblet of Fire 2014.05.05 ~ 2014.05.11 732/734
    Read More ...
  • OpenJDK 源码阅读之 LinkedList

    OpenJDK 源码阅读之 LinkedList


    定义

    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {
    }
    

    盲点

    • serialVersionUID
        private static final long serialVersionUID = 876323262645176354L;
    

    序列化版本号,如果前一版本序列化后,后一版本发生了很大改变,就使用这个号告诉虚拟机,不能反序列化了。

    问题

    • writeObject

    比例一下 ArrayListLinkedList 中的 writeObject

        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 array length
            s.writeInt(elementData.length);
    
            // 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 writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
            // Write out any hidden serialization magic
            s.defaultWriteObject();
    
            // Write out size
            s.writeInt(size);
    
            // Write out all elements in the proper order.
            for (Node<E> x = first; x != null; x = x.next)
                s.writeObject(x.item);
        }
    

    注意后者没有检查 modCount,这是为什么呢?之前看 ArrayList的时候觉得是为线程安全考虑的,可是现在为什么又不检查了呢?虽然两个文件的注释中都说到,如果有多个线程操作此数据结构,应该从外部进行同步。但是一个检查,一个不检查是几个意思呀?

    思考

    • 维护数据结构一致性
        private void linkFirst(E e) {
            final Node<E> f = first;
            final Node<E> newNode = new Node<>(null, e, f);
            first = newNode;
            if (f == null)
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
        }
    

    注意代码第 5行对 f 的检查,6 行对 last 的调整。一定要细心,保证操作后, 所有可能 涉及的数据都得到相应更新。

    • 隐藏实现
        public E getFirst() {
            final Node<E> f = first;
            if (f == null)
                throw new NoSuchElementException();
            return f.item;
        }
    

    注意返回的是数据,而不是Node,外部根本不需要知道 Node 的存在。 另外,为什么 f == null 要抛出异常而不是返回 null

    Read More ...
  • OpenJDK 源码阅读之 HashSet

    OpenJDK 源代码阅读之 HashSet


    概要

    • 类继承关系
    java.lang.Object
        java.util.AbstractCollection<E>
            java.util.AbstractSet<E>
                java.util.HashSet<E>
    
    • 定义
    public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, Serializable
    
    • 要点
    1. 不保证元素次序,甚至不保证次序不随时间变化
    2. 基本操作(add, remove, contains, size)常量时间
    3. 迭代操作与当前元素个数加底层容量大小成正比
    4. 不保证同步

    思考

    • 总体实现

    底层是用 HashMap 实现的,Set 中的数据是 HashMapkey,所有的 key 指向同一个 value, 此 value 定义为:

    // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();
    

    再看一下 add,大概就能明白了

    /**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
    
    • load factor
        public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
    

    初始化中,注意使用的 HashMap 的 load factor 设置为 0.75,如果太小,就设置成 16. 为什么要 0.75 呢? 有什么依据吗?

    Read More ...
  • OpenJDK 源码阅读之 String

    OpenJDK 源代码阅读之 String


    概要

    • 类继承关系
    java.lang.Object
        java.lang.String
    
    • 定义
    public final class String
    extends Object
    implements Serializable, Comparable<String>, CharSequence
    
    • 要点

    一旦创建就不可改变

    实现

    • storage
    /** The value is used for character storage. */
    private final char value[];
    

    可以看出 String 中的数据是如何存储的。

    • 初始化
        public String(String original) {
            this.value = original.value;
            this.hash = original.hash;
        }
    

    可以看出使用 String 类型初始化,新 String 实际上与原来的 String 指向同一块内存。

    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
    

    如果用 char[] 初始化,可以看出,新分配了内存,并复制,保证了两者相互独立,只是内容相同。

        public String(StringBuffer buffer) {
            synchronized(buffer) {
                this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
            }
        }
    

    注意用 StringBuffer 初始化时,对同一 buffer 是线程安全的,即初始化 String 的过程中,其它线程不会改变 buffer 的内容。

    另外,能告诉我下面这段代码是怎么回事么?

       public String(StringBuilder builder) {
            this.value = Arrays.copyOf(builder.getValue(), builder.length());
        }
    

    为啥这次不同步了呢?

    Read More ...
  • OpenJDK 源码阅读之 ArrayList

    OpenJDK 源码阅读之 ArrayList


    概要

    • 类继承关系
    java.lang.Object
        java.util.AbstractCollection<E>
            java.util.AbstractList<E>
                java.util.ArrayList<E>
    
    • 定义
    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    {
    }
    
    Read More ...
  • 学习英语第十三十四周

    学习英语第十三十四周

    标签:英语

    阅读英文原著

    Book Time Progress
    Harry Potter And The Goblet of Fire 2014.05.12 ~ 2014.05.23 734/734
    Read More ...
  • OpenJDK 源码阅读之 HashMap

    OpenJDK 源代码阅读之 HashMap


    概要

    • 类继承关系
    java.lang.Object
        java.util.AbstractMap<K,V>
            java.util.TreeMap<K,V>
    
    • 定义
    public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, Serializable
    
    • 要点

    1) 与 Hashtable 区别在于:非同步,允许 null 2) 不保证次序,甚至不保证次序随时间不变 3) 基本操作 put, get 常量时间 4) 遍历操作 与 capacity+size 成正比 5) HashMap 性能与 capacityload factor 相关,load factor 是当前元素个数与 capacity 的比值,通常设定为 0.75,如果此值过大,空间利用率高,但是冲突的可能性增加,因而可能导致查找时间增加,如果过小,反之。当元素个数大于 capacity * load_factor 时,HashMap 会重新安排 Hash 表。因此高效地使用 HashMap 需要预估元素个数,设置最佳的 capacityload factor ,使得重新安排 Hash 表的次数下降。

    Read More ...
  • OpenJDK 源码阅读之 TreeMap

    OpenJDK 源代码阅读之 TreeMap


    概要

    • 类继承关系
    java.lang.Object
        java.util.AbstractMap<K,V>
            java.util.HashMap<K,V>
    
    • 定义
    public class TreeMap<K,V>
        extends AbstractMap<K,V>
        implements NavigableMap<K,V>, Cloneable, java.io.Serializable
    
    • 要点

    1) 基于 NavigableMap 实现的红黑树 2) 按 natrual ordering 或者 Comparator 定义的次序排序。 3) 基本操作 containsKey,get,putlog(n) 的时间复杂度。 4) 非线程安全

    Read More ...
  • 开始OpenJDK源代码阅读

    开始OpenJDK源代码阅读


    在阅读了一周的 OpenJDK 源代码后,我才写这篇文章。因为除非你已经开始阅读,否则是不知道自己是不是应该读下去的。所以,不要贸然说自己要干嘛,先做一段时间,觉得感觉还好,再决定做下去。

    这一周,主要是看 java.util 中和容器相关的几个文件,虽然还没看太多,但是已经有一些收获了。看到了以前学过的数据结构在Java的标准库中是如何被实现的。也明白了平时使用的一些类的原理是什么。另外,由于最近在看 《Java编程思想》,也能把书中讲的和标准库的源代码对应起来,感觉还不错。还有一个收获就是明白了,基础越扎实,阅读源代码收获也越大,否则根本就看不出一些设计的初衷是什么。之前看到源代码中一些编写程序的方式,我觉得没有必要那样写,后来看《Java编程思想》,才知道为什么会这样写。也有一些是我觉得可以从源代码中学习的东西,从《Java编程思想》中看到,标准库中的编写方式有些是历史遗留问题,不得不那么写,而不是说我们写的时候,也要那样做。这就是说不要迷信那些你不明白的东西,即使他们看起来很权威。

    Read More ...
  • OpenJDK 源码阅读之 LinkedList

    OpenJDK 源码阅读之 LinkedList


    概要

    • 类继承关系
    java.lang.Object
        java.util.AbstractCollection<E>
            java.util.AbstractList<E>
                java.util.AbstractSequentialList<E>
                    java.util.LinkedList<E>
    
    Read More ...