java基础:13.6 集合框架 - Queue(LinkedList)

本文详细介绍了Java中的Queue接口及其主要方法,强调了队列的FIFO特性。LinkedList作为Queue的实现,允许null值并具有双向链表结构。文章对比了LinkedList和ArrayList在插入/删除数据速度及定位速度上的差异,并提供了使用LinkedList实现Stack栈的实践练习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 概述

Queue一种队列结构集合,用来存储将要进行处理的元素.通常以FIFO的方式排序元素,但这并不是必须的.

比如优先度队列就是一个例外,它是以元素的值来排序.

但无论怎样,每个Queue的实现都必须指定它的排序属性.Queue通常不定义元素的equal和hashCode方法.

队列(queue) 是一种先进先出的数据结构。元素被追加到队列末尾,然后从队列头删。
在优先队列( priority queue) 中,元素被赋予优先级。当访问元素时,拥有最高优先级的元素首先被删除。
Queue 接口继承自java. util .Collection

队列有两种实现方式:一种是使用循环数组;另一种是使用链表。如果需要一个循环数组队列,使用ArrayDeque类;如果需要一个链表队列,就使用LinkedList,这个类实现了Queue接口。
在这里插入图片描述

二. 主要方法

每个Queue方法都存在两种形式
(1)操作失败则抛出异常
(2)操作失败返回一个特定值,通常是null或者是false

操作类型抛出异常返回特定值
Insertadd(e)offer(e)
Removeremove()poll()
Examineelement()peek()

Queue的实现可能会限制集合存储的元素数,这种队列被称为有界队列
对于有界队列当调用add方法时,如果元素数超出其容量限制,就会抛出 IllegalStateException 异常,.offer方法就是专门为有界队列设计的,和add不同的是当插入元素失败的的时候,它返回false而不是抛出异常.

Remove和poll方法都是从队列头部弹出元素。具体是那个元素被弹出,这要看队列的排序策略。

remove和poll仅当是空集合的时候才有区别,remove会抛出NoSuchElementException,而poll返回null值。

Element和peek方法都是返回队列的头部元素,但并不会从队列中将其删除。
同remove和poll一样仅当是空集合时两者才有差别,element抛出NoSuchElementException而peek返回null值。

Queue的实现通常不允许插入null值,除了LinkedList这个例外,出于历史原因它允许插入null值,但是必须十分注意的是null也是poll和peek方法返回的特别值。
 
 

三. 实现

Queue的实现可以划分为通用实现并发实现

通用实现主要有两个,一个是LinkedList ,一个是PriorityQueue.

LinkedList在List总我们已经说过,它继承自Queue接口,提供FIFO的队列操作形式.

PriorityQueue 是一个基于栈结构的优先度队列,它可以根据元素的自然排序或者给定的排序器进行排序.

java.util.concurrent 包中包含了一系列的同步Queue接口和实类。BlockingQueue继承自Queue,它会在检索元素时等待队列是非空队列处于可用状态,并在存入一个元素后将状态更改为可用状态,下面是它的实现类。

  • LinkedeBlockingQueue —基于链接节点的可选有界FIFO方式阻塞式队列

  • ArrayBlockingQueue —基于数组的有界FIFO方式的阻塞式队列

  • PriorityBlockingQueue —基于栈结构无界阻塞式队列

  • DelayQueue —基于栈结构的时间调度队列

  • SychronousQueue —通过使用BlockingQueue接口的简单对接机制的队列  
      在JDK7中 ,TransferQueue是一个特殊额BlockingQueue,它向队列添加一个元素后,可以选择处于等待(阻塞)状态,以让另一个线程检索元素,TransferQueue只有一个实现类

  • LinkedTransferQueue—基于链接节点的无界TransferQueue
     
     

四、LinkedList

LinkedList 实现了:ListDeque (双向链表结构)、Queue(队列接口)。

Queue是在两端出入的List,所以也可以用数组或链表来实现。
队列:先进先出FIFO
offer 在最后添加元素
poll 取出第一个元素
peek 查看第一个元素

LinkedList:以双向链表实现的LinkedList既是List,也是Queue。它是唯一一个允许放入null的Queue。
Queue<Hero> q= new LinkedList<Hero>();

还有很多Quene,比如ArrayDequePriorityQueue。。。
 
 

方法:addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()

	 LinkedList <xxx> ll = new LinkedList<xxx>();
	 ll.addFirst("q0");  //头部加入
	 ll.addLast("q1");  // 尾部加入
     System.out.println(ll.getFirst());   //查看最前面的对象
	 System.out.println(ll.getLast());      //查看最后面的对象
	 System.out.println(ll.removeFirst());    // 从该线性表中返回并删除第一个对象
	 System.out.println(ll.removeLast());   // 从该线性表中返回并删除最后一个对象
	 System.out.println(ll);  // 取出会导致对象被删除

 

特点
双向链表实现。链表无容量限制,但双向链表本身使用了更多空间,也需要额外的链表指针操作。

使用方法 list.get(i) 或者 list.set(15,"Lindon") 要悲剧的遍历链接,直到指针移到相应位置(如果 i 大于数组的一半,会从末尾开始)。不要使用get来遍历线性表中的所有元素,应该使用迭代器!!

for(listElementType s :List){  //foreach 循环隐式地使用了迭代器
	process s;
}

 
插入、删除元素时修改前后节点的指针即可,但还是要遍历部分链表的指针才能移动到下标所指的位置,只有在链表两头的操作–add(), addFirst(),removeLast()或用iterator()上的remove()能省掉指针的移动。

 

ArrayList 和 LinkedList 的区别

ArrayList

  1. 插入/删除数据速度慢。因为要把插入点后所有对象移位。
  2. 顺序结构,可直接定位到某个位置的对象,定位速度快。

LinkedList

  1. 插入,删除数据快。只要断开插入点的连接,重新连接到别的块就OK。
  2. 链表结构,不可以直接定位到某个位置的对象,必须根据链表的方向一个一个找,定位速度慢。
public class TestCollection {

    public static void main(String[] args) {

        List<Integer> l1 = new ArrayList<>();
        List<Integer> l2 = new LinkedList<>();
        insertFirst(l1,"ArrayList");
        insertFirst(l2,"LinkedList");        
    }
    
    private static void insertFirst(List<Integer> l, String type) {
        int total = 1000 * 100;
        final int number = 5;
        long start = System.currentTimeMillis();
        for (int i = 0; i < total; i++) {
            l.add(0, number);
        }
        long end = System.currentTimeMillis();
        System.out.printf("在%s 最前面插入%d条数据,总共耗时 %d 毫秒 %n", type, total, end - start);
    }        
}

在ArrayList 最前面插入100000条数据,总共耗时 1006 毫秒
在LinkedList 最前面插入100000条数据,总共耗时 4 毫秒

 

练习

练习-使用LinkedList实现Stack栈
与FIFO(先入先出的)队列类似的一种数据结构是FILO先入后出栈Stack
根据接口Stack :
实现类:MyStack
public class MyStack implements Stack
并向这个栈中,压入5个英雄,接着弹出5个英雄
package collection;
import charactor.Hero;
public interface Stack {
//把英雄推入到最后位置
public void push(Hero h);
//把最后一个英雄取出来
public Hero pull();
//查看最后一个英雄
public Hero peek();
}

package collection;

import java.util.LinkedList;
import java.util.List;

public class MyStack implements Stack{

	LinkedList<Hero> heros = new LinkedList<>();

	@Override  
	//把英雄推入到最后位置
	public void push(Hero h) {
		heros.addLast(h);
		
	}

	@Override
	public Hero pull() {
		// TODO Auto-generated method stub
		Hero h = heros.removeLast();
		return h;
	}

	@Override
	public Hero peek() {
		// TODO Auto-generated method stub
		Hero h = heros.getLast();
		return h;
	}	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值