【源码分析】LinkedList

签名

这里写图片描述
可以看到,LinkedList 继承了AbstractSequentialList
实现了Cloneable,和序列化接口。

类和接口

AbstractSequentialList——骨架实现(skeletal implementation)类

很多都参照了effective java ,向大佬致敬!!!

优点:把接口和抽象类的优点结合起来。就关了所有与接口实现相关的工作,方便了其他接口的实现

public abstract class AbstractList extends AbstractCollection implements List {
这里的Collection 实现的是包装模式,包装了collection接口

Cloneable

简介:这是一个标记接口,表明这个类重写(Override)了Object.clone()方法,复制这个类是合法的。

Serializable

简介:这个也是一个标记接口,在以前的分析里分析过。

Deque

简介:一个支持两端插入删除的线性集合。deque是double end queue 的简称——即双向队列。。。

成员变量

transient int size = 0;
transient Node first;
transient Node last;

这三个变量很显然,就是分别指向了前,后,size表示这个LinkedList的容量。
Q:size 什么时候不会扩展LinkedList的容量,反而会抛出异常?

transient:
ransient是java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。——引自bing网典

源码剖析

1.构造器

这里写图片描述

public LinkedList() {
 }


public More ...LinkedList(Collection<? extends E> c) {
    this();
     addAll(c);
 }

2.方法

add系列

这里写图片描述

 public void More ...addLast(E e) {
    linkLast(e);
 }



public void More ...addFirst(E e) {
     linkFirst(e);
 }

public boolean More ...addAll(Collection<? extends E> c) {
     return addAll(size, c);
 }


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

这几个类封装了算法,应该是策略模式。
实际上不是,人家策略算法是指:出行=坐飞机/坐火车/坐自行。。。都封装到一起。这个应该是装饰模式。

  public boolean addAll(int index, Collection<? extends E> c) {
         checkPositionIndex(index);
 //查询是否超出边界。如果超出了,就抛出异常——所以,collection类也是有边界的——问题2:LinkedList是如何扩展它的边界的?为什么在这里不选择扩展边界,而选择抛出异常?
         Object[] a = c.toArray();

         int numNew = a.length;
         if (numNew == 0)
             return false;
 //检查新添加的collection类是否为空
         Node<E> pred, succ;
         if (index == size) {
             succ = null;
             pred = last;
         } else {
             succ = node(index);
             pred = succ.prev;
         }//插入

         for (Object o : a) {
             @SuppressWarnings("unchecked") E e = (E) o;
             //@SuppressWarnings——消除注释注解,
             问题3:为什么这里会选择用这个?都有什么情况会用这个?
             Node<E> newNode = new Node<>(pred, e, null);

             if (pred == null)
                 first = newNode;
             else
                 pred.next = newNode;
             pred = newNode;
         }

         if (succ == null) {
             last = pred;
         } else {
             pred.next = succ;
             succ.prev = pred;
         }

         size += numNew;
         modCount++;
         return true;
     }

link系列——创建链表

这里写图片描述

      void More ...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++;

clear()

这个类并不难懂,主要是有意思的是这个注解:
还有 modecount :这里引用一篇文章:

http://blog.csdn.net/u012926924/article/details/50452411

感觉自己的文章深度就不够。日了狗!
有意思的是,AbstractList中的clear(),是调用了一个removeRange来实现的。
先谈一谈LinkedList中的clear();
这里写图片描述
就算这里有一个可达的Iterator 对node节点的域置为null后,gc也会进行垃圾回收。
启发:不用的对象置为null,可以gc

q:为什么AbstractList会将clear转发给removeRandom?

学长任务:为什么List在使用迭代器迭代的时候,remove某个元素 会抛出异常

既然是List,那么先从AbstractList看起:

   public E More ...remove(int index) {
        throw new UnsupportedOperationException();
    }

额,这个实现总是抛出这个异常——不支持操作- -!;
我们往上看,
这里写图片描述
这里写图片描述这里写图片描述
抛出异常的原因——f==null
什么时候会造成f==null呢?
我们查看一下Iterator的构造方法:
http://blog.csdn.net/qh_java/article/details/50154405 我去,编不下去了,这篇文章高大上!

3.内部类

Node——节点类

 private static class More ...Node<E> {
         E item;
         Node<E> next;
     Node<E> prev;

     More ...Node(Node<E> prev, E element, Node<E> next) {
         this.item = element;
         this.next = next;
         this.prev = prev;
     }
 }

每个节点都有前驱和后继。

ListItr 类

private class More ...ListItr implements ListIterator<E> 

相对于Iterator,增加了与前驱和后继相关的操作,更贴近LinkedList,支持前后操作

DescendingIterator类

单纯实现了Iterator接口。采用了策略模式,封装了ListItr的算法
感觉不叫策略模式啊,这到底算不算个设计模式?
问题4:既然ListItr功能多,为什么还会出现DescendingIterator?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linked List 是一种常见的数据结构,它由一组节点组成,每个节点包含一个值和一个指向下一个节点的指针。在 C++ STL 中,LinkedList 的实现是通过双向链表(doubly linked list)来完成的。下面是部分 LinkedList分析。 ```cpp template <class T> class list { protected: struct list_node { list_node* prev; list_node* next; T data; }; ... }; ``` 在这段代码中,`list_node` 是双向链表的节点类型,包含了 `prev` 和 `next` 两个指针,以及存储的数据 `data`。 ```cpp template <typename T, typename Alloc = allocator<T> > class _List_base { public: typedef Alloc allocator_type; allocator_type get_allocator() const noexcept { return allocator_type(); } struct _Node { _Node* _M_next; _Node* _M_prev; T _M_data; }; ... }; ``` `_List_base` 作为 LinkedList 的底层实现,定义了节点类型 `_Node`,包含了 `_M_next` 和 `_M_prev` 两个指针,以及存储的数据 `_M_data`。此外,还提供了 `get_allocator()` 方法,用于获取当前 LinkedList 使用的内存分配器。 ```cpp template <typename T, typename Alloc = allocator<T> > class list : protected _List_base<T, Alloc> { protected: typedef _List_base<T, Alloc> _Base; typedef typename _Base::_Node _Node; public: typedef typename _Base::allocator_type allocator_type; ... }; ``` `list` 类继承自 `_List_base`,并且定义了一些类型别名,例如 `allocator_type`,用于表明当前 LinkedList 使用的内存分配器类型。 ```cpp template <typename T, typename Alloc = allocator<T> > class list { public: ... class iterator { public: typedef bidirectional_iterator_tag iterator_category; typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; ... }; ... }; ``` 在 LinkedList 中,迭代器(iterator)被广泛使用。在 C++ STL 中,迭代器的定义是一个 class,包含了一些成员类型,例如 `iterator_category`、`value_type`、`difference_type`、`pointer` 和 `reference` 等。这些成员类型用于描述当前迭代器的特征,例如 `iterator_category` 描述了迭代器的类别。 以上只是 LinkedList码的一部分,LinkedList 的实现非常复杂,涉及到很多内存管理、迭代器、算法等内容。如果想要深入理解 LinkedList 的实现,需要读者具备一定的 C++ 知识和数据结构基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值