其他分享
首页 > 其他分享> > LinkedList(链表)

LinkedList(链表)

作者:互联网

介绍

特点

链表结构

package java.util;

import java.util.function.Consumer;
public interface Iterator<E> {
    
    boolean hasNext();
    
    E next();
    
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
package java.util;

public interface ListIterator<E> extends Iterator<E> {

    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    void remove();

    void set(E e);

    void add(E e);
}
private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
Node<E> node(int index) {
    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}
package cn.dylanphang;

/**
 * @author dylan
 */
public class BitOperator2 {

    public static void main(String[] args) {
        // m进行有符号右移n位相当于(int) Math.floor(m / Math.pow(2, n))
        // 关于-7,采用8位解释,运算前需要求出反码和补码,对补码进行有符号右移,高位补1,之后得到原码,结算得到结果:
        // 十进制-7的原码为:1000 0111,计算其补码为:1111 1001,右移一位:1111 1100,计算原码:1000 0100
        // 因此十进制结果为:-4
        System.out.println(7 >> 1);
        System.out.println(-7 >> 1);
    }
}

关于add方法

public void add(int index, E element) {
    checkPositionIndex(index);

    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));
}
/**
 * Links e as last element.
 */
void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

/**
 * Inserts element e before non-null Node succ.
 */
void linkBefore(E e, Node<E> succ) {
    // assert succ != null;
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}
public ListIterator<E> listIterator(int index) {
    checkPositionIndex(index);
    return new ListItr(index);
}
public ListIterator<E> listIterator() {
    return listIterator(0);
}
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable { 
	public ListIterator<E> listIterator(int index) {
        checkPositionIndex(index);
        return new ListItr(index);
    }
    
    private class ListItr implements ListIterator<E> { ... }
}
public abstract class AbstractSequentialList<E> extends AbstractList<E> { 
    public Iterator<E> iterator() {
        return listIterator();
    }

    public abstract ListIterator<E> listIterator(int index);
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { 
    public Iterator<E> iterator() {
        return new Itr();
    }

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }
    
    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }
    
    private class Itr implements Iterator<E> { ... }

    private class ListItr extends Itr implements ListIterator<E> { ... }
}
public interface List<E> extends Collection<E> {
    Iterator<E> iterator();
    
    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int index);
}
public ListIterator<E> listIterator(int index) {
    checkPositionIndex(index);
    return new ListItr(index);
}

private class ListItr implements ListIterator<E> {
    private Node<E> lastReturned; // 这个成员变量将记录最后一次cursor跳过的那个链接Node,remove()方法依赖于它来删除链接Node
    private Node<E> next; // 从构造器方法可以看出,这个就是等于index为0的链接Node或者链表为空的时候它等于null
    private int nextIndex; // 记录当前cursor所指向位置后的那个索引
    private int expectedModCount = modCount; // 记录当前链表被操作的次数,调用此类中的大部分方法会使此操作数+1

    ListItr(int index) {
        // assert isPositionIndex(index);
        next = (index == size) ? null : node(index);
        nextIndex = index;
    }

    public void add(E e) {
        checkForComodification();
        lastReturned = null;
        if (next == null)
            linkLast(e);
        else
            linkBefore(e, next);
        nextIndex++;
        expectedModCount++;
    }
    
    final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
    }
}
public void add(int index, E element) {
    checkPositionIndex(index);

    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));
}

private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
}

线程不安全

public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}
package cn.dylanphang;

import cn.dylanphang.util.ThreadUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.LinkedList;
import java.util.ListIterator;
import java.util.concurrent.CountDownLatch;

/**
 * @author dylan
 * @date 2021/01/01
 */
@Slf4j
public class LinkedListTest {

    private static final int CONCURRENT_TIMES = 5000;

    private final CountDownLatch cdl = new CountDownLatch(CONCURRENT_TIMES);
    private final CountDownLatch testCdl = new CountDownLatch(CONCURRENT_TIMES);
    private final LinkedList<String> linkedList = new LinkedList<>();

    private int counter = 0;

    /**
     * 由于无法控制LinkedList中的程序流程,采用高并发插入数据的方式去为同一个LinkedList添加元素。
     */
    @Test
    public void test() throws InterruptedException {
        for (int i = 0; i < CONCURRENT_TIMES; i++) {
            final String content = i + "";
            ThreadUtils.create(() -> {
                try {
                    this.cdl.await();
                    Thread.sleep(1000);
                    this.linkedList.add(content);
                    count();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.testCdl.countDown();
            });
            this.cdl.countDown();
        }

        this.testCdl.await();
        log.info("Successful write into LinkedList times is: {}", this.counter);
        log.info("Current insert operation finish. LinkedList's size is: {}", this.linkedList.size());

        int currentIndex = -1;
        final ListIterator<String> listIterator = this.linkedList.listIterator();

        while (listIterator.hasNext()) {
            try {
                listIterator.next();
                currentIndex++;
            } catch (Exception e) {
                log.error("Exception is: {}", e.getClass().getSimpleName());
                break;
            }
        }
        log.info("Mistake element index is: {}", currentIndex);
    }

    synchronized private void count() {
        this.counter++;
    }
}

public E next() {
    checkForComodification();
    if (!hasNext())
        throw new NoSuchElementException();

    lastReturned = next;
    next = next.next;
    nextIndex++;
    return lastReturned.item;
}

操作数modCount

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

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.util.AbstractList;
import java.util.ConcurrentModificationException;
import java.util.LinkedList;
import java.util.ListIterator;

/**
 * @author dylan
 */
@Slf4j
@SuppressWarnings("all")
public class ListIteratorTest {

    @Test
    public void test() throws InterruptedException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        // 1.获取LinkedList对象
        AbstractList<String> linkedList = new LinkedList<>();

        // 2.线程一
        new Thread(() -> {
            try {
                // 2.1.获取listIterator对象,modCount/expectedModCount均为0
                ListIterator<String> listIterator = linkedList.listIterator();
                // 2.2.线程休眠2秒
                Thread.sleep(2000);
                // 2.3.线程结束休眠后,添加元素前需要经过checkForComodification()
                // *.此时线程二已经结束,modCount必然为1,checkForComodification()将抛出ConcurrentModificationException
                listIterator.add("dylan");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ConcurrentModificationException e) {
                log.error("{}", e.toString());
            }
        }).start();

        // 3.线程二
        new Thread(() -> {
            try {
                // 3.1.获取listIterator对象,modCount/expectedModCount均为0
                ListIterator<String> listIterator = linkedList.listIterator();
                // 3.2.线程休眠1秒
                Thread.sleep(1000);
                // 3.3.线程结束休眠后,添加元素完毕,modCount被更新为1
                listIterator.add("sunny");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        // 4.防止test线程结束
        Thread.sleep(3000);

        // 5.使用反射技术获取AbstractList中modCount的字段对象field
        Class<AbstractList> abstractListClass = AbstractList.class;
        Field field = abstractListClass.getDeclaredField("modCount");

        // 6.取消Java权限控制检查
        field.setAccessible(true);

        // 7.断言modCount的值为1
        log.info("modCount: {}", field.get(linkedList));
    }
}

ListIterator<String> listIterator = linkedList.listIterator();
listIterator.add("something.");

linkedList.add与listIterator.add

总结

标签:index,LinkedList,int,链表,add,listIterator,ListIterator
来源: https://www.cnblogs.com/phax2/p/14220394.html