一、使用Java模拟单向链表

/**
 * 节点
 */
public class Node<E> {
    // 数据域
    public E data;
    // 指针域
    public Node<E> next;

    public Node(E value) {
        this.data = value;
    }

    /**
     * 显示方法
     */
    public void display() {
        System.out.print(data + " ");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("回收Node对象。。。");
        super.finalize();
    }
}
/**
 * 模拟单向链表*/
public class MyLinkedList<E> {
    // 头节点
    public Node<E> first;

    // 尾节点
    public Node<E> last;

    // 链表的元素个数
    public int size;

    public MyLinkedList() {
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 在头节点前插入一个节点(头插)
     */
    public void addFirst(E value) {
        Node<E> node = new Node<>(value);
        // if (first == null || last == null) { // 此时链表还没有节点
        if (isEmpty()) { // 如果链表还没有节点
            first = node;
            last = node;
            size++;
            return;
        }

        // 头插
        node.next = first;
        first = node;
        size++;
    }

    /**
     * 在尾节点后插入一个节点(尾插)
     */
    public void add(E value) {
        Node<E> node = new Node<>(value);
        // if (first == null || last == null) { // 此时链表还没有节点
        if (isEmpty()) { // 如果链表还没有节点
            first = node;
            last = node;
            size++;
            return;
        }

        // 尾插
        last.next = node;
        last = node;
        size++;
    }

    /**
     * 删除头节点
     */
    public Node<E> deleteFirst() {
        Node<E> tmp = first;
        // if(size() == 1) {
        if (first.next == null) {
            last = null;
        }
        first = tmp.next;
        size--;
        return tmp;
    }

    /**
     * 查找方法
     */
    public Node<E> find(E value) {
        Node<E> current = first;
        while (!value.equals(current.data)) {
            if (current.next == null) {
                return null;
            }
            current = current.next;
        }
        return current;
    }

    /**
     * 显示方法
     */
    public void display() {
        Node<E> current = first;
        while (current != null) {
            current.display();
            current = current.next;
        }
        System.out.println();
    }
}

 

测试:

public class Demo1 {
    public static void main(String[] args) {
        MyLinkedList<Integer> list = new MyLinkedList<>();
        list.add(1);
        System.out.println("链表头节点:" + list.first.data); // 链表头节点:1
        System.out.println("链表尾节点:" + list.last.data); // 链表头节点:1
        System.out.print("list.dispaly(): ");
        list.display(); // list.dispaly(): 1
        System.out.println("size: " + list.size()); // size: 1

        list.deleteFirst(); // 删除头节点
        System.gc(); // 被删除的头节点的内存被系统回收
        try {
            Thread.sleep(1000 * 1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.print("list.dispaly(): ");
        list.display();
        
        System.out.println("======= 分割线 =======");
        list.add(10);
        list.add(20);
        System.out.println("链表头节点:" + list.first.data); // 链表头节点:10
        System.out.println("链表尾节点:" + list.last.data); // 链表头节点:20
        System.out.print("list.dispaly(): ");
        list.display(); // list.dispaly(): 10 20
        System.out.println("size: " + list.size()); // size: 2
        
        list.deleteFirst(); // 删除头节点
        System.out.println("链表头节点:" + list.first.data); // 链表头节点:20
        System.out.println("链表尾节点:" + list.last.data); // 链表头节点:20
        System.out.println("size: " + list.size()); // size: 1
        System.gc(); // 被删除的头节点的内存被系统回收
        try {
            Thread.sleep(1000 * 1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("======= 分割线 =======");
        list.add(30);
        list.addFirst(-10);
        list.addFirst(-30);
        list.display(); // list.dispaly(): -30 -10 20 30
        Node<Integer> node = list.find(-10);
        System.out.println(node.data); // -10
        Node<Integer> node2 = list.find(10); // node2 = null
        //System.out.println(node2.data); // NullPointerException
    }
}

 

二、jdk中使用单向链表的源码--HashMap

  我们知道jdk7的HashMap的底层实现是数组+单链表,jdk8的HashMap的底层实现是数组+单链表+红黑树。下面分析源码:

// jdk1.7.0_60
public
class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable { public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K, V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; } static class Entry<K, V> implements Map.Entry<K, V> { final K key; V value; Entry<K, V> next; int hash; Entry(int h, K k, V v, Entry<K, V> n) { value = v; next = n; key = k; hash = h; } } void addEntry(int hash, K key, V value, int bucketIndex) { if ((size >= threshold) && (null != table[bucketIndex])) { resize(2 * table.length); hash = (null != key) ? hash(key) : 0; bucketIndex = indexFor(hash, table.length); } createEntry(hash, key, value, bucketIndex); } void createEntry(int hash, K key, V value, int bucketIndex) { Entry<K, V> e = table[bucketIndex]; // 新建一个Entry,指针域指向e,即指向原来的table[bucketIndex] // 所以,jdk7中单链表添加数据时使用头插 table[bucketIndex] = new Entry<>(hash, key, value, e); size++; } }
// jdk1.8.0_111
public
class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable { public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K, V>[] tab; Node<K, V> p; int n, i; // 哈希表为空,第一次扩容 if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; // 当前哈希桶为空,直接添加到当前哈希桶 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { // 当前哈希桶不为空,则与哈希桶存储的节点进行比较 Node<K, V> e; K k; // 哈希值相同,并且key也相同,覆盖 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) // 否则,添加到红黑树 e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value); else { // 或者,添加节点到单链表(还需要与链表中节点比较,相同就不添加) for (int binCount = 0;; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); // 尾插 if (binCount >= TREEIFY_THRESHOLD - 1) // 节点超过8个单链表转换成红黑树 treeifyBin(tab, hash); break; } // 如果与链表中某个节点相同,则不添加 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } // 哈希值相同,并且key也相同,覆盖 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; } }

 

相关文章: