Java集合——LinkedList
1. Java LinkedList 特性
- LinkedList(链表)底层是用双向链表实现的存储。是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
- 链表可分为单向链表和双向链表:
- 与 ArrayList 相比,LinkedList 的增加和删除对操作效率更高,而查找和修改的操作效率较低。
- 以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
- 以下情况使用 LinkedList :
- 需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
2. Java LinkedList 方法
方法 | 描述 |
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
3. LinkedList 模拟实现
- 添加元素方法;在指定位置添加元素;根据下标获取节点;根据下标获取元素;删除指定位置的元素;输出。
public class MyLinkedList<E> {
private Node first;
private Node last;
private int size;
/**
* 无参构造方法
*/
public MyLinkedList(){}
/**
* 获取容器的容量
* @return
*/
public int size(){
return size;
}
/**
* 判断下标合法性
* @param index
*/
public void rangeCheck (int index){
if(index < 0 || index > size-1){
throw new RuntimeException("下标不合法");
}
}
/**
* 添加元素
* @param e
*/
private void add(E e){
Node node = new Node(e);
if(first == null){
first = node;
last = node;
}else{
last.setNext(node);
node.setPre(last);
last = node;
}
size++;
}
/**
* 在指定位置添加元素
* @param index
* @param e
*/
public void add(int index, E e){
Node newNode = new Node(e);
Node node = this.getNode(index);
if(node != null){
Node up = node.getPre();
node.setPre(newNode);
if(up != null){
up.setNext(newNode);
}
newNode.setPre(up);
newNode.setNext(node);
}
if(index == 0){
first = newNode;
}
if(index == size - 1){
last = newNode;
}
}
/**
* 根据下标获取元素的值
* @param index
* @return
*/
public E get(int index){
Node node = this.getNode(index);
return node != null ? (E)node.getElement() : null;
}
/**
* 根据下标获取节点
* @param index
* @return
*/
private Node getNode(int index){
//判断下标的合法性
rangeCheck(index);
Node node = first;
if(index <= (size >> 1)){ //顺着取
for(int i = 0; i < index; i++){
node = node.getNext();
}
}else{ //倒着去
node = last;
for(int i = size - 1; i > index; i-- );
node = node.getPre();
}
return node;
}
/**
* 删除指定位置的元素
* @param index
*/
public void remove(int index){
//获取节点
Node node = this.getNode(index);
if(node != null){
Node up = node.getPre();
Node down = node.getNext();
if(up != null){
up.setNext(down);
}
if(down != null){
down.setPre(up);
}
if(node == first){
first = down;
}
if(node == last){
last = up;
}
node.setPre(null);
node.setNext(null);
size--;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
Node node = first;
while(node!=null){
sb.append(node.getElement() + ",");
node = node.getNext();
}
sb.setCharAt(sb.length()-1, ']');
return sb.toString();
}
public static void main(String[] args) {
MyLinkedList<String> mll = new MyLinkedList<String>();
mll.add("a");
mll.add("b");
mll.add("c");
mll.add("d");
mll.add("e");
mll.add(0,"aaa");
mll.add(4,"fff");
//mll.remove(0);
System.out.println(mll.size());
System.out.println(mll.toString());
System.out.println(mll.get(3));
//System.out.println(mll.get(8));
}
}
//Node类
public class Node {
private Node pre;
private Object element;
private Node next;
public Node(){
}
public Node(Object element) {
this.element = element;
}
public Node getPre() {
return pre;
}
public void setPre(Node pre) {
this.pre = pre;
}
public Object getElement() {
return element;
}
public void setElement(Object element) {
this.element = element;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}