LinkedList 实例

引用:http://hi.baidu.com/xinhua0228/blog/item/2600986e242e27dd80cb4aa3.html

 

LinkedList提供了将链接列表用作堆栈、队列或双端队列的方法,这里不再重复介绍List的标准操作,只给出其独特方法的使用。

请注意其已经实现的接口
     Serializable, Cloneable, Iterable<E>, Collection<E>, Deque<E>, List<E>, Queue<E>

  1. package collection.lession9;
  2. import java.util.Arrays;
  3. import java.util.Iterator;
  4. import java.util.LinkedList;
  5. import java.util.List;
  6. /**
  7. * 老紫竹JAVA提高教程(6)-认识List列表之LinkedList<br>
  8. * 实现了双向队列的控制,包括头尾的操作<br>
  9. * 可用于堆栈和FIFO操作等。 <br>
  10. * <br>
  11. * 相关API请查看 api.java2000.net/LinkedList
  12. *
  13. * @author 老紫竹 JAVA世纪网(java2000.net)
  14. *
  15. */
  16. public class Lession9 {
  17.   public static void main(String[] args) {
  18.     // 对于List的基础操作,这里不再重复
  19.     // 请自行查看介绍List的内容
  20.     // 这里专注于LinkedList所引入的特性部分
  21.     //
  22.      LinkedList<String> list = new LinkedList<String>();
  23.      list.add("1111");
  24.      list.add("2222");
  25.      list.add("3333");
  26.      showList(list); // [1111, 2222, 3333]
  27.     // 在列表的最头部增加一个
  28.      list.addFirst("head");
  29.      showList(list); // [head, 1111, 2222, 3333]
  30.     // 测试反向的迭代器
  31.     // 正常的迭代器应该是从第一个数据开始
  32.     // 这个是从最后一个开始,这也是LinkedList的特点
  33.      Iterator<String> it = list.descendingIterator();
  34.     while (it.hasNext()) {
  35.        System.out.print(it.next() + ","); // 3333,2222,1111,head,
  36.      }
  37.      System.out.println();
  38.     // 获取列表的第一个数据,且继续保留这个数据
  39.     // 内部都是 getFirst,无任何区别
  40.      System.out.println(list.element()); // head
  41.      System.out.println(list.getFirst()); // head
  42.     // 如果长度为0,会返回null,否则和getFirst相同
  43.      System.out.println(list.peek()); // head
  44.      System.out.println(list.peekFirst()); // head
  45.     // 获取列表的最后一个数据,且继续保留这个数据
  46.      System.out.println(list.getLast()); // 3333
  47.     // 如果长度为0,会返回null,否则和getLast相同
  48.      System.out.println(list.peekLast()); // 3333
  49.     // 在列表末尾增加一个数据
  50.      list.offer("tail");
  51.      showList(list); // [head, 1111, 2222, 3333, tail]
  52.     // 在列表最前面增加一个数据
  53.     // 内部通过 addFirst 实现的
  54.      list.offerFirst("----");
  55.      showList(list); // [----, head, 1111, 2222, 3333, tail]
  56.     // 在列表末尾增加一个数据
  57.     // 内部通过 addLast实现的
  58.      list.offerLast("====");
  59.      showList(list); // [----, head, 1111, 2222, 3333, tail, ====]
  60.     // 获取列表的第一个数据,并从删除这个数据
  61.      System.out.println(list.poll()); // ----
  62.      System.out.println(list.pollFirst()); // head
  63.     // 获取列表的最后一个数据,并从删除这个数据
  64.      System.out.println(list.pollLast()); // ====
  65.     // 以堆栈的形式存入一个数据
  66.     // 将该元素插入此列表的开头
  67.     // 内部通过 addFirst实现
  68.      list.push("xyz");
  69.      showList(list); // [xyz, 1111, 2222, 3333, tail]
  70.     // 以堆栈的形式弹出一个数据
  71.     // 移除并返回第一个数据
  72.     // 内部通过 removeFirst 实现
  73.      System.out.println(list.pop()); // xyz
  74.      showList(list); // [1111, 2222, 3333, tail]
  75.     // 删除并返回第一个数据
  76.      System.out.println(list.removeFirst()); // 1111
  77.      showList(list); // [2222, 3333, tail]
  78.     // 删除列表中第一次出现的这个数据
  79.     // 内部通过 remove(Object)实现
  80.      System.out.println(list.removeFirstOccurrence("3333")); // true
  81.      showList(list); // [2222, tail]
  82.     // 删除并返回最后一个数据
  83.      System.out.println(list.removeLast()); // tail
  84.      showList(list); // [2222]
  85.     // 删除列表中最后一次出现的这个数据
  86.      System.out.println(list.removeLastOccurrence("2222")); // true
  87.      showList(list); // []
  88.    }
  89.   /**
  90.     * 显示List里面的数据。
  91.     *
  92.     * @param list
  93.     */
  94.   private static void showList(List list) {
  95.      System.out.println(Arrays.toString(list.toArray()));
  96.    }
  97. }

运行结果
[1111, 2222, 3333]
[head, 1111, 2222, 3333]
3333,2222,1111,head,
head
head
head
head
3333
3333
[head, 1111, 2222, 3333, tail]
[----, head, 1111, 2222, 3333, tail]
[----, head, 1111, 2222, 3333, tail, ====]
----
head
====
[xyz, 1111, 2222, 3333, tail]
xyz
[1111, 2222, 3333, tail]
1111
[2222, 3333, tail]
true
[2222, tail]
tail
[2222]
true
[]


总结:
     这个类具有很大的灵活性,也是常用的列表实现类之一。不多说了,总之必须掌握就是了。

 

<think>嗯,用户想了解Java中的LinkedList,包括它的概念、特性以及线程安全性,还特别提到了实现细节、线程安全和外部同步方法,比如Collections.synchronizedList。那我得先整理一下LinkedList的基本概念和特性,比如它是基于双向链表实现的,每个节点有前驱和后继指针。然后要说明它的优缺点,比如随机访问慢,但插入删除快,尤其是在头部和尾部。 接下来是线程安全的部分,记得LinkedList本身不是线程安全的,这点需要强调。然后得解释为什么,比如它的方法没有同步机制,多线程环境下可能导致数据不一致。这时候要提到如何实现线程安全,比如使用Collections.synchronizedList进行包装,或者手动同步代码块。还有可能提到其他并发类,比如ConcurrentLinkedQueue,不过用户的问题里主要提到的是synchronizedList,所以这部分可能需要详细说明。 然后需要引用站内的资料,比如引用[2]提到LinkedList未实现同步,可以用Collections.synchronizedList包装;引用[4]说明synchronizedList的使用和注意事项,特别是在复合操作时需要手动同步。还有引用[5]中的代码示例,说明synchronizedList返回的是SynchronizedList或SynchronizedRandomAccessList,但LinkedList因为是链表结构,所以返回的是SynchronizedList,并且其方法通过同步块实现线程安全,但迭代器仍需手动同步。 可能还需要比较不同的同步方法,比如手动同步和使用并发集合的优缺点。此外,用户可能想知道实现细节,比如节点结构、内部类等,但根据引用内容,可能不需要深入到代码级别,而是概括底层数据结构即可。 最后,生成相关问题的时候,要围绕LinkedList的特性、线程安全方法、性能比较和应用场景来设计问题,确保覆盖用户可能感兴趣的方面。</think>### Java LinkedList详解 #### 一、概念与特性 Java的`LinkedList`是基于**双向链表**实现的数据结构,每个节点包含前驱指针、数据域和后继指针。特性包括: 1. **动态内存分配**:无需预先指定容量,按需扩展 2. **插入/删除高效**:首尾操作仅需$O(1)$时间,中间位置操作为$O(n)$[^2] 3. **顺序访问结构**:随机访问需要遍历链表,时间复杂度为$O(n)$ 4. **多接口实现**:同时实现了`List`和`Deque`接口,支持队列和栈操作 #### 二、线程安全性分析 1. **非线程安全**:默认实现未使用同步机制,多线程并发操作可能导致数据不一致 2. **复合操作风险**:例如先`contains()`检查再`add()`操作,需要外部同步[^4] 3. **快速失败机制**:迭代器在检测到并发修改时会抛出`ConcurrentModificationException` #### 三、线程安全实现方案 1. **手动同步**(粗粒度锁): ```java LinkedList<String> list = new LinkedList<>(); synchronized (list) { list.add("example"); } ``` 2. **包装同步**(推荐方法): ```java List<String> syncList = Collections.synchronizedList(new LinkedList<>()); // 使用时仍需同步迭代操作 synchronized (syncList) { Iterator<String> it = syncList.iterator(); while (it.hasNext()) { // 处理元素 } } ``` * 原理:通过`SynchronizedList`包装器给所有方法添加`synchronized`块[^5] * 锁对象:默认使用包装器自身作为互斥锁(可通过`Collections.synchronizedList(list, mutex)`自定义) 3. **并发容器替代**: ```java ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>(); ``` #### 四、实现细节 ```java // JDK源码片段(简化) 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; } } ``` * **头尾指针**:维护`first`和`last`两个指针实现快速端点操作 * **结构变化**:增删节点只需修改相邻节点的指针引用 * **迭代优化**:`ListIterator`会根据访问方向选择从头或尾开始遍历
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值