Java中的LinkedList集合详解

LinkedList集合

基础概念

可以在任何位置高效插入和删除的一个有序序列,简而言之就是数据结构里的链表。

我们都清楚在链表很容易进行插入和删除,但是我们在使用c/c++的时候需要新建一个链表项的结构体并且需要在里面设置指针,java不需要指针,java在这方面就很好的为程序员消除了这个问题。使用LinkedList类就可以解决问题。

如下代码将实现先添加3个元素,然后将第二个元素删除的操作,方便快捷So easy~

import java.util.*;
public class pred {
	public static void main(String[] args) {
	LinkedList staff=new LinkedList<String>();
	staff.add("Amy");
	staff.add("Bob");
	staff.add("Carl");
	ListIterator<String> it=staff.listIterator();
	String first=it.next();
	String second=it.next();
	it.remove();//remove the element "Bob"
		System.out.println(staff);
		System.out.println(first+" "+second);
	}
}

运行结果如下:请添加图片描述

LinkedList.add()是将对象添加到链表的尾部。

ListIterator接口

然而,我们平常经常会将元素添加到集合中间,这个时候我们就要使用迭代器来找到这个中间位置。在List里还有一个ListIterator子接口:

interface ListIterator<E> extends Iterator<E>{

void add(E element);//与Collection.add不同,这个方法不返回boolean类型的值,假定总会成功执行该方法
E previous();//与next相反,previous返回越过的对象
boolean hasPrevious();//与hasNext()一样效果

}

add方法

add方法是在迭代器位置之前添加一个新对象,例如下面就是在第二个元素之前添加“Mike”

import java.util.*;
public class pred {
	public static void main(String[] args) {
	LinkedList staff=new LinkedList<String>();
	staff.add("Amy");
	staff.add("Bob");
	staff.add("Carl");
	ListIterator<String> it=staff.listIterator();
	it.next();//skip the first element
	it.add("Mike");
		System.out.println(staff);
	}
}

运行结果:
在这里插入图片描述

set置换方法

set可以使用一个新元素替代next和previous方法返回的上一个元素

import java.util.*;
public class pred {
	public static void main(String[] args) {
	LinkedList staff=new LinkedList<String>();
	staff.add("Amy");
	staff.add("Bob");
	staff.add("Carl");
	ListIterator<String> it=staff.listIterator();
        //将第一个元素Amy替代为wyq
	String newvalue="wyq";
	it.next();
	it.set(newvalue);
	System.out.println(staff);
}
}

运行结果:
在这里插入图片描述

关于LinkedList的插入删除的记忆方法

我们使用迭代器对集合进行遍历的时候回经常类比backspace键,这个时候我要作一些解释:

调用next后调用remove确实可以达到与backspace效果相同的目的,删除左侧的元素。但是如果调用previous,就会删除右侧的元素。

集合头部用next(),集合尾部用previous()

import java.util.*;
public class pred {
	public static void main(String[] args) {
	LinkedList staff=new LinkedList<String>();
	staff.add("Amy");
	staff.add("Bob");
	staff.add("Carl");
	ListIterator<String> it=staff.listIterator();
        //新创建的迭代器的位置在第一个元素的前面,因此不能上来就是使用hasPrvious(),会返回false
        //正向遍历
	while(it.hasNext()) {
		System.out.println(it.next());
	}
	System.out.println();
        //反向遍历
	while(it.hasPrevious()) {
		System.out.println(it.previous());
	}
}
}

运行结果:
在这里插入图片描述

多个迭代器访问集合

一个迭代器对集合进行修改的时候另一个迭代器正在访问集合,那么肯定会出现混乱,迭代器之间各怀鬼胎,互相不告诉自己的位置以及自己干了啥,导致作战失败。

import java.util.*;
public class pred {
	public static void main(String[] args) {
	LinkedList staff=new LinkedList<String>();
	staff.add("Amy");
	staff.add("Bob");
	staff.add("Carl");
	//生成两个迭代器it与it2
	ListIterator<String> it=staff.listIterator();
	ListIterator<String> it2=staff.listIterator();
	it.next();
	it.remove();
	it2.next();
}
}

结果:
在这里插入图片描述
会抛出ConcurrentModificationException的异常。

按照索引值访问集合元素

如果只是想要索引查找元素而很少对元素进行插入和修改,用ArrayList不香嘛?

但是LinkedList还是有自己的索引方法—get(int index)

既然看到可以按照数字进行索引,那么我是不是就可以使用这种方式对集合进行遍历?就像如下所写的这样:

for(int i=0;i<list.size();i++){
	System.out.println(list.get(i));
}

注意这段代码的效率很低,不建议使用。

每次查找一个元素都是从列表的头部重新开始搜索,很费时间。(这里的get做了一些细小的优化:如果索引大于size/2的时候从表尾开始查找)

迭代器有自己的索引:nextIndex()返回下一次调用next()方法所返回的元素的整数索引;previousIndex()方法返回下一次调用previous()方法所返回的整数索引。

import java.util.*;
public class pred {
	public static void main(String[] args) {
	LinkedList staff=new LinkedList<String>();
	staff.add("Amy");
	staff.add("Bob");
	staff.add("Carl");
	ListIterator<String> it=staff.listIterator();
	it.next();//位于第0个和第1个元素之间
	System.out.println(it.nextIndex());
	System.out.println(it.previousIndex());
}
}

运行结果如下:
在这里插入图片描述
最后说明一点:将整数index作为listIterator()的参数 list.listIterator(index),这个迭代器将会指向索引为n的元素的前面。就是火调用next()与get(index)得到的元素都是索引为n的元素。二者相比迭代器效率低一些。

LinkedListTest.java

import java.util.*;
public class LinkedListTest {
	public static void main(String[] args) {
		LinkedList<String> a=new LinkedList<String>();
		a.add("Amy");
		a.add("Carl");
		a.add("Erica");
		LinkedList<String> b=new LinkedList<String>();
		b.add("Bob");
		b.add("Doug");
		b.add("Frances");
		b.add("Gloria");
		//merge the words from b to a
		ListIterator<String> aIt=a.listIterator();
		Iterator<String> bIt=b.iterator();
		while(bIt.hasNext()) {
			if(aIt.hasNext())
				aIt.next();
			aIt.add(bIt.next());
		}
		System.out.println(a);
		//remove every second word from b
		bIt=b.iterator();//将迭代器bIt返回到列表头
		while(bIt.hasNext()) {
			bIt.next();//skip one element
			if(bIt.hasNext()) {
				bIt.next();//skip next element
				bIt.remove();//remove that element
			}
			
		}
		System.out.println(b);
		//bulk operation:remove all words in b from a
		a.removeAll(b);
		System.out.println(a);
	}
}

运行结果如下:
在这里插入图片描述

List、ListIterator、LinkedList的API

[API]java.util.List<E>

集合.方法

1.ListIterator<E> listIterator();

返回一个列表迭代器,用来访问列表中的元素。

2.ListIterator<E> listIterator(int index);

返回一个列表迭代器,用来访问列表中的元素,第一次调用这个迭代器调用的next会返回索引(index)的元素

3.void add(int i,E element);

在给定的位置添加一个元素

4.void addAll(int i,Collection<? extends E> elements);

将一个集合中的所有元素添加到给定位置

5.E remove(int i);

删除并返回给定位置的元素

6.E get(int i);

获取给定位置的元素

7.E set(int i,E element);

用一个新元素替代给定位置的元素,并返回原来的元素。

8.int indexOf(Object element);

返回与指定元素相等的元素在列表中第一次出现的位置,如果没有这样的元素就返回-1.

9.int lastIndexOf(Object element);

返回与指定元素相等的元素在列表中最后一次出现的位置,如果没有这样的元素就返回-1.

第八个和第九个都是用集合调用的

java.util.ListIterator<E>

1.void add(E element);

在当前位置前添加一个元素

2.void set(E element);

用新元素替代next与previous访问的上一个元素。如果上一个next和previous调用之后列表结构发生了变化,将会抛出一个IllegalStateException的异常

3.boolean hasPrevious();

当反向迭代列表的时候,如果还有可以访问的元素,返回true

4.E previous();

返回前一个对象,迭代器刚开始创建的时候,迭代器一般是在列表的头部,这个时候调用previous会抛出NoSuchElementException的异常

5.int nextIndex();

返回下一次调用next方法时将返回的元素的索引

6.int previousIndex();

返回下一次调用previous方法时将返回的元素

java.util.LinkedList<E>

LinkedList();//构建一个空链表
LinkedLis(Collection<? extends E> elements);//构造一个链表,并将集合中所有的元素添加到这个链表中
void addFirst(E element);
void addLast(E element);//将元素天教导表头或者表尾
E getFirst();
E getLast();//返回列表头部或者尾部的元素
E removeFirst();
E removeLast();//删除并返回列表头部或者尾部的元素
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明璐花生牛奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值