LinkedList

想到一个优化


  • `if (prev == null) {
    first = next;
    } else {
    prev.next = next;
    x.prev = null;
    }

    if (next == null) {
    last = prev;
    } else {
    next.prev = prev;
    x.next = null;
    }`
    要是给链表分别插入一个虚拟的头结点和尾节点,就不用每次这样判断了所有操作都可以看成是链表内的操作,岂不是美滋滋。

Node<E> node(int index) {
    // assert isElementIndex(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;
    }

优化从前面开始找,还是从后面开始找。
从这个代码可以看出来,链表的编号是从0开始的。

java子类直接屏蔽父类的同名变量。

iteratorlistiterator的区别

http://stackoverflow.com/questions/10977992/difference-between-iterator-and-listiterator

List的iterator方法

public Iterator<E> iterator() {
        return listIterator();
    }

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

        return new ListIterator<E>() {
            private final ListIterator<E> i = l.listIterator(index+offset);

            public boolean hasNext() {
           .........
           ..........
        };
    }

其实是获取了是获取了ListIterator然后进行了向上转型。


 previous()的实现效果

public static void main(String[] args){
        LinkedList<Integer> list=new LinkedList<Integer>(); 
        for (int i=0;i<9;i++){
            list.add(i); 
        }
        ListIterator<Integer> li=list.listIterator(); 
//      while (li.hasNext()){
//          System.out.println(li.next()); 
//      } 
        for (int i=0;i<4;i++){
            System.out.println(li.next()); 
        }; 
        System.out.println(li.previous()); 
        System.out.println(li.previous()); 
        System.out.println(li.next());
        System.out.println(li.next()); 
    }
output:
0
1
2
3
3
2
2
3



感觉next()和previces()这两个函数的效果与含义不相符,既然已经输出了3那么previces()应该是2,previces()是2了那next()又是2??

找到一个解释:

E next()
Returns the next element in the list. This method may be called repeatedly
previous to go back and forth. (Note that alternating calls to next and previous will return the same element repeatedly.)
http://stackoverflow.com/questions/15598297/listiterator-next-and-previous-detail

public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (modCount == expectedModCount && nextIndex < size) {
                action.accept(next.item);
                lastReturned = next;
                next = next.next;
                nextIndex++;
            }
            checkForComodification();
        }
        这是迭代器中的一个方法,意思是讲当前位置以后的元素都处理一遍,其中Consumer<? super E> action的? super E指的是E的父类,而Consumer是一个函数借口FIFI主要是为了支持Lambda表达式。
 public Iterator<E> descendingIterator() {
        return new DescendingIterator();
    }
    由于Iterator只能是单向的,而List是双向的所以实现了两个Iterator,这个反向的Iterator是调用ListItr的方法实现的。这是代理吗?
### 什么是LinkedList数据结构 LinkedList 是一种基于链表的数据结构,它在 Java 中通过 `java.util.LinkedList` 类实现。它既可以作为列表使用,也可以作为队列或双端队列使用[^1]。LinkedList 内部通过双向链表实现,这意味着每个节点包含前驱和后继指针,从而允许高效的插入和删除操作。 --- ### LinkedList 的构造方法 以下是 `LinkedList` 提供的两种主要构造方法: 1. **无参构造方法**: ```java public LinkedList() ``` 创建一个空的 `LinkedList` 实例[^1]。 2. **基于集合的构造方法**: ```java public LinkedList(Collection<? extends E> c) ``` 使用指定集合中的元素创建一个新的 `LinkedList` 实例,元素顺序与集合的迭代器返回顺序一致。 --- ### LinkedList 的常用方法 以下是一些常用的 `LinkedList` 方法及其功能: #### 基本操作 - **add(E e)**:将指定元素追加到列表末尾。 - **add(int index, E element)**:在指定位置插入元素。 - **remove(Object o)**:移除首次出现的指定元素(如果存在)。 - **remove(int index)**:移除指定位置的元素并返回该元素。 #### 访问元素 - **get(int index)**:返回指定位置的元素。 - **indexOf(Object o)**:返回首次出现的指定元素的索引,如果不存在则返回 `-1`。 #### 队列操作 - **offer(E e)**:将元素添加到列表末尾(等同于 `add`)。 - **poll()**:获取并移除列表头部的元素。 - **peek()**:获取但不移除列表头部的元素。 #### 栈操作 - **push(E e)**:将元素压入栈顶(等同于在列表头部插入元素)。 - **pop()**:从栈顶弹出元素(等同于移除列表头部的元素)。 --- ### 示例代码 以下是一个简单的 `LinkedList` 使用示例: ```java import java.util.LinkedList; public class LinkedListExample { public static void main(String[] args) { // 创建一个空的 LinkedList LinkedList<String> list = new LinkedList<>(); // 添加元素 list.add("Apple"); list.add("Banana"); list.add("Cherry"); // 插入元素到指定位置 list.add(1, "Date"); // 打印列表 System.out.println("List: " + list); // 移除元素 String removedElement = list.remove(2); System.out.println("Removed Element: " + removedElement); // 获取元素 String firstElement = list.get(0); System.out.println("First Element: " + firstElement); // 遍历列表 for (String fruit : list) { System.out.println(fruit); } } } ``` --- ### LinkedList 的优缺点 #### 优点 - **高效插入和删除**:由于内部是双向链表结构,插入和删除操作的时间复杂度为 O(1)[^3]。 - **支持多种操作**:可以作为列表、队列或栈使用[^4]。 #### 缺点 - **随机访问慢**:通过索引访问元素时,需要从头或尾遍历链表,时间复杂度为 O(n)[^3]。 --- ### 自定义实现 LinkedList 以下是一个简单的自定义 `LinkedList` 实现示例: ```java class Node<T> { T data; Node<T> next; Node(T data) { this.data = data; this.next = null; } } class MyLinkedList<T> { private Node<T> head; public MyLinkedList() { head = null; } public void add(T data) { if (head == null) { head = new Node<>(data); } else { Node<T> current = head; while (current.next != null) { current = current.next; } current.next = new Node<>(data); } } public void printList() { Node<T> current = head; while (current != null) { System.out.print(current.data + " -> "); current = current.next; } System.out.println("null"); } } public class CustomLinkedListExample { public static void main(String[] args) { MyLinkedList<Integer> list = new MyLinkedList<>(); list.add(1); list.add(2); list.add(3); list.printList(); // 输出: 1 -> 2 -> 3 -> null } } ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值