当前位置: 首页 > news >正文

沈阳旅游集团网站建设最新电大网站开发维护

沈阳旅游集团网站建设,最新电大网站开发维护,wordpress会员推广插件,南京网站建设一条龙LinkedList 一个双向链表。 本身是基于链表进行封装的列表, 所以具备了链表的特性: 变更简单, 容量是无限的, 不必像数组提前声明容量等。 同时 LinkedList 支持存储包括 null 在内的所有数据类型。 1 链表 了解 LinkedList 之前, 我们需要先了解一下双向链的特点 单链表, 双…LinkedList 一个双向链表。 本身是基于链表进行封装的列表, 所以具备了链表的特性: 变更简单, 容量是无限的, 不必像数组提前声明容量等。 同时 LinkedList 支持存储包括 null 在内的所有数据类型。 1 链表 了解 LinkedList 之前, 我们需要先了解一下双向链的特点 单链表, 双链表, 循环链表的定义, 可以看一下这个链表内存是散乱的, 每一个元素存储本身内存地址的同时还存储下一个元素的地址链表具备了增删快, 查找慢的特点LinkedList 是基于双向链表设计的, 所以具备了链表的特点 2 LinkedList 中每个节点的定义 private static class NodeE {/** 当前节点的内容 */E item;/** 下一个节点 */NodeE next;/** 上一个节点 */NodeE prev;Node(NodeE prev, E element, NodeE next) {// 当前节点的数据 elementthis.item element;// 当前节点的后置节点 nextthis.next next;// 当前节点的前置节点 prevthis.prev prev;} }Node 节点中除了指向下一个节点的 next, 还包含指向上一个节点的 prev, 所以 LinkedList 是一个双向的链表。 3 LinkedList 中的几个属性 public LinkedListE {transient int size 0;transient NodeE first;transient NodeE last; }3.1 size 表示当前链表中的节点个数。 3.2 first 整个双向链表的头节点 3.3 last 整个双向链表的尾节点 重要的就这个几个属性了 4 LinkedList 的构造方法 public LinkedListE {// 构造函数 1: 无参构造函数public LinkedList() {}// 构造函数 2: 给定一个 Collection 的构造public LinkedList(Collection? extends E c) {// 省略} }4.1 无参的构造函数 public LinkedList() { }就是单纯的声明 LinkedList 的实例, 没有其他的逻辑了 4.2 给定一个 Collection 的构造 public LinkedList(Collection? extends E c) {// 调用自身无参的构造函数this();// 将集合 c 添加到当前的链表中addAll(c); }/*** 将集合对象全部添加到当前链表中*/ public boolean addAll(Collection? extends E c) {// 调用 addAll 重写方法在 size 的位置添加数据return addAll(size, c); }/*** 指定位置的批量插入*/ public boolean addAll(int index, Collection? extends E c) {// 判断 0 index size, 不满足抛出异常checkPositionIndex(index);// 集合转为数组Object[] a c.toArray();int numNew a.length;// 需要插入的集合没有数据, 直接结束if (numNew 0)return false;// pred: 新增的元素的将要插入的位置的前一个节点 // succ: 新增的元素的将要插入的位置的节点// 如果新增的元素的节点位置为 a, 那么 pred 就是 a 的前一位的节点, succ 就是 a 节点NodeE pred, succ;// 需要添加的元素刚好追加在已有的后面的if (index size) {succ null;pred last;} else {// 获取指定位置的节点succ node(index);pred succ.prev;} for (Object o : a) {E e (E) o;NodeE newNode new Node(pred, e, null);// 第一次创建时, 那么第一个节点就是 first节点if (pred null)first newNode;else// 将 pred 的下一个节点指向新创建的节点pred.next newNode; // 将 pred 改为当前节点, 方便下一个元素操作pred newNode; } // succ 是为空的, 表示直接在已有的数据后面追加元素的话, 所以将最后节点设置为新增元素的最后一个元素的节点if (succ null) {last pred;} else {// 原有数据后半部分拼接到现在链表的后半部分pred.next succ;succ.prev pred;} // 当前的长度size numNew;// 修改次数加1 modCount;return true; }/*** 校验 index 的值满足: 0 index size*/ private void checkPositionIndex(int index) {if (!isPositionIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }/** 判断 index 是否大于等于 0 并且小于等于 size*/ private boolean isPositionIndex(int index) {return index 0 index size; }/*** 获取指定位置的节点*/ NodeE node(int index) {// 此次做了一个小优化: 当要查找的位置小于现有数据的一半, 从前往后找, 大于的话, 从后面开始找// size 1 相当于 size / 2if (index (size 1)) {// 从前向后找NodeE x first;for (int i 0; i index; i)x x.next;return x;} else {// 从后向前找NodeE x last;for (int i size - 1; i index; i--)x x.prev;return x;} }从代码可知 LinkedList 是基于双向链表实现了LinkedList 的数据是通过 first(节点) 和 last(节点) 和 size 三个共同维护的LinkedList 内部的数据通过泛型, 保持了自己的类型, 没有转为 Object。 5 LinkedList 几个常用的方法 5.1.1 添加数据 直接在链表末尾添加元素 // 直接添加一个元素 public boolean add(E e) {// 默认新增到链表的末尾linkLast(e);return true; }/*** 将入参的元素添加到链表的末尾*/ void linkLast(E e) {// 获取链表的尾结点final NodeE l last;// 将数据封装为 Node 节点final NodeE newNode new Node(l, e, null);// 链表的尾结点等于新的节点last newNode;// 如果链表一开始的尾结点为空, 表示链表一开始没有数据if (l null)// 链表的头节点也等于当前的新节点first newNode;else// 一开始的为节点有值, 将原来的尾结点的下一个节点设置为当前新的节点l.next newNode; // 链表个数 1size;// 修改次数 1modCount }指定位置的插入 public void add(int index, E element) {// 判断 0 index size, 不满足抛出异常checkPositionIndex(index);// index size 要插入的位置刚好在末尾if (index size)linkLast(element);else // 插入到某个节点的前面linkBefore(element, node(index)); }/*** 将元素插入到某个节点的前面*/ void linkBefore(E e, NodeE succ) {// 获取某个节点的前置节点final NodeE pred succ.prev;final NodeE newNode new Node(pred, e, succ);// 设置插入位置的节点的前置节点为需要插入的新节点succ.prev newNode;// 插入位置的节点的前置节点为空, 表示没有头节点if (pred null)first newNode;else// 需要插入的位置的前置节点的下一个节点为新节点pred.next newNode; // 个数加 1size;// 修改次数 1modCount; }在头部插入 public void addFirst(E e) {linkFirst(e); }/*** 在链表的头节点前新增元素*/ private void linkFirst(E e) {// 获取头节点final NodeE f first;final NodeE newNode new Node(null, e, f);// 头节点等于新节点first newNode;// 原本的头节点为空, 表示没有数据if (f null)// 设置尾节点为新节点last newNode;else// 设置原本的头节点的前置节点为当前的节点f.prev newNode;size;modCount; }还有前面看到的 插入一个 Collection 的 addAll(Collection c)指定位置的插入一个 Collection 的 addAll(int index, Collection c) 5.1.2 删除数据 直接删除 (默认删除第一个元素) public E remove() {return removeFirst(); }/*** 删除链表第一个元素*/ public E removeFirst() {final NodeE f first;// 头节点为空if (f null)throw new NoSuchElementException();return unlinkFirst(f); }/*** 删除指定的节点*/ private E unlinkFirst(NodeE f) {// 获取删除节点的数据final E element f.item;// 找到删除元素的下一个元素final NodeE next f.next;// 清空删除元素的信息f.item null;f.next null;// 将头节点重新设置为删除元素的下一个元素first next;// 如果原本删除元素就是没有后续元素时, 将最后的元素设置为 nullif (next null)last null;else// 将新的第一个元素的前置节点设置为 nullnext.prev null; // 元素个数 - 1 size--;// 修改次数 1modCount;// 返回数据return element; }指定位置的删除 public E remove(int index) {// 检测删除的位置是否正确checkElementIndex(index);return unlink(node(index)); }private void checkElementIndex(int index) {// 如果不满足 0 index size, 就抛出异常if (!isElementIndex(index))throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }private boolean isElementIndex(int index) {return index 0 index size; }E unlink(NodeE x) {final E element x.item;// 得到将要移除的元素的后置节点final NodeE next x.next;// 得到将要移除的元素的前置节点final NodeE prev x.prev;// 如果前置节点为空, 说明移除的为头节点, 重新设置头节点为删除节点的后置节点if (prev null) {first next;} else {// 将前置节点的下一个节点设置为后置节点prev.next next;// 设置删除节点前置节点为 nullx.prev null;}// 如果后置节点为空, 说明移除的为尾节点, 重新设置尾节点为删除节点的前置节点if (next null) {last prev;} else {// 将后置节点的前置节点设置为前置节点next.prev prev;// 设置删除节点后置节点为 nullx.next null;}// 将删除节点的数据设置为 nullx.item null;size--;modCount;return element; }指定删除元素 public boolean remove(Object o) {// 需要删除的节点为 nullif (o null) {// 找到第一个为 null 的元素, 进行删除for (NodeE x first; x ! null; x x.next) {if (x.item null) {unlink(x);return true;}}} else {for (NodeE x first; x ! null; x x.next) {// 找到节点的数据等于要删除的节点if (o.equals(x.item)) {unlink(x);return true;}}} }除了上面几个还有 删除第一个 removeFirst()删除最后一个 removeLast()删除第一个符合的元素 removeFirstOccurrence(Object o)删除最后一个符合的元素 removeLastOccurrence(Object o) 5.1.3 获取数据 获取指定位置的数据 public E get(int index) {// 确保 0 index sizecheckElementIndex(index);// 定位到对应位置的节点的数据return node(index).item; }获取第一个的数据 public E getFirst() {final NodeE f first;if (f null)throw new NoSuchElementException();return f.item; }获取最一个的数据 public E getLast() {final NodeE l last;if (l null)throw new NoSuchElementException();return l.item; }5.1.4 更新数据 更新指定位置节点的属性值 public E set(int index, E element) {// 确保 0 index sizecheckElementIndex(index);// 获取指定位置的节点数据NodeE x node(index);// 获取指定节点是旧数据E oldVal x.item;// 更新指定节点的数据x.item element;// 返回旧数据return oldVal; }6 LinkedList 补充 1. LinkedList 实现了 Serializable 接口, 但是他的属性都是设置为 transient ? LinkedList 重写了序列化方法 writeObject 和反序列化方法 readObject。 在序列化中, 重新通过遍历所有节点, 把所有节点数据写入到 ObjectOutputStream。 2. LinkedList 支持 fail-fast 机制 ? 通过继承关系可以指定 LinkedList 也是实现了 AbstractList, 具备了 modCount, 在修改中也会增加 modCount 的值, 所以 LinkedList 也支持 fail-fast 机制。 3. LinkedList不是一个线程安全的集合 ? LinkedList 是线程不安全的, 如果需要保证线程的安全性, 可以考虑使用 Collections.synchronizedList(Lise l) 函数返回一个线程安全的 LinkedList 类。 4. 不要用 for 遍历 LinkedList ? 遍历的代码 ListString list2 new LinkedList(); list.add(1); list.add(2); list.add(3);for (int i 0; i list2.size(); i) {String item list2.get(i);System.out.println(item); }源码中涉及的代码: public class LinkedList {public E get(int index) {checkElementIndex(index);return node(index).item;}NodeE node(int index) {if (index (size 1)) {NodeE x first;for (int i 0; i index; i)x x.next;return x;} else {NodeE x last;for (int i size - 1; i index; i--)x x.prev;return x;}} }如上: 我们通过 for 遍历 LinkedList, 第一次 get(0), node(0), 就是 first 节点第二次 get(1), node(1), 就是 first - node1第三次 get(2), node(2), 就是 first - node1 - node2 每次通过 get() 就是需要从第一个节点一直找到对应的位置, 才能找到需要的节点。 所以遍历 LinkedList 可以使用 foreach (foreach 循环的原理就是迭代器) 或者迭代器。 5. LinkedList 还有其他的作用吗 LinkedList 实现了 Deque 接口, 所以 LinkedList 可以作为双端队列, 同时 LinkedList 的双向链表的特点, 还可以作为 Stack 使用, 但是 LinkedList 的这 2 个功能, 如果没有什么特殊的要求的话, 都可以使用 ArrayDeque 替代, 后者的性能更好。
http://www.w-s-a.com/news/494938/

相关文章:

  • 有瀑布流的网站小型商城网站
  • 百石网怎么做网站二次开发软件
  • 网站域名是什么东西制作网页哪家好
  • 合肥网站建设团队简述网站内容管理流程
  • 网站广告是内容营销吗wordpress增加背景图片
  • 网站建设技术jsp课程设计响应式布局网站开发
  • 东莞网站排名优化seo套路网站怎么做的
  • 我做网站网络建站一般多少钱
  • 如何快速提升网站关键词排名房地产网站开发毕业设计
  • 做网站 提交源码 论坛sem分析是什么意思
  • 网站建设与部署阿里云大学百度付费推广有几种方式
  • 作品集怎么做网站个人简历模板免费下
  • 工业网站素材重庆关键词自动排名
  • 拖拽式网站建设费用微网站怎么做的好名字
  • 长沙电信网站备案谷歌推广怎么做最有效
  • 网站建设与管理总结报告华为开发者联盟
  • 门诊部网站建设天空建筑网站
  • 扬州市城乡建设网站高端品牌鞋子有哪些牌子
  • 杭州网站建设招聘网长沙网络销售公司
  • 网站制作一年多少钱免费做电子章网站
  • 信誉好的营销网站建设徐州市铜山新区建设局网站
  • 建行网站关于我们山西seo和网络推广
  • 1m带宽做网站怎么样深圳网站建设制作开发公司
  • 网站建设 服务内容 费用郴州网站建设公司哪里有
  • 网站关键词重要性育才网站建设
  • 网络安全形势下怎么建设学校网站wordpress最新主题下载
  • 自己建设网站需要什么条件.gs域名做网站怎么样
  • 网上做公益的网站推广手机卡返佣平台
  • 网站是公司域名是个人可以南京建设银行官方网站
  • 做互联网网站的会抓百度网盟推广 网站