C#集合——Queue<T>集合的使用

2 篇文章 0 订阅

目录

一、Queue集合的概述

二、Queue集合的构造函数

三、Queue集合的常用属性

四、Queue集合的常用方法

五、Queue集合的实例代码

六、Queue集合的源码分析

6.1、Enqueue(T object)方法的源码分析

6.2、Dequeue()方法的源码分析


一、Queue<T>集合的概述

Queue表示先入先出的对象集合,元素值可重复。常用Queue<T>泛型类型。

该类将泛型队列实现为循环数组。存储在Queue<T>中的对象在一端插入,从另一端删除。队列Queue和堆栈Stack在需要临时存储信息时很有用;也就是说,您可能希望在检索元素的值之后丢弃它。如果需要按照存储在集合中的顺序访问信息,请使用Queue<T>。如果需要以相反的顺序访问信息,则使用Stack<T>。如果需要从多个线程并发访问集合,则使用ConcurrentQueue<T>ConcurrentStack<T>

可以对Queue<T>及其元素执行三种主要操作:

1、Enqueue方法将一个元素添加到Queue<T>的末尾。

2、Dequeue方法从Queue<T>开始移除最先插入的元素。

3、Peek方法返回位于Queue<T>开头的最先插入的元素,但不会将其从Queue<T>中移除。

Queue<T>的容量是Queue<T>可以容纳的元素个数。当元素被添加到Queue<T>时,通过重新分配内部数组,容量会根据需要自动增加。可以通过调用TrimExcess()方法来减少容量。

Queue<T> 接受 null 作为引用类型的有效值,并允许重复元素。

二、Queue<T>集合的构造函数

Queue<T>的构造函数,有以下三个。

Queue<T>():初始化Queue<T>类的新实例,该实例包含从指定集合复制的元素,并且有足够的容量容纳复制的元素数量。

Queue<T>(IEnumerable<T> collections):初始化Queue<T>类的新实例,该实例包含从指定集合复制的元素,并且有足够的容量容纳复制的元素数量。

Queue<T>(Int32 count):初始化Queue<T>类的新实例,该实例为空并具有指定的初始容量。

三、Queue<T>集合的常用属性

Queue<T>的属性,只有一个:

Count:用于获取Queue<T>集合内部的元素个数。

四、Queue<T>集合的常用方法

Clear():将集合中的元素清空,全部删除。

Contain(T t):判断集合中是否包含某个元素。

CopyTo(T[] array , Int32 index):从指定的数组索引开始,将Queue<T>元素复制到现有的一维数组中。

Enqueue(T object):将对象object添加到Queue<T>的末尾。

Dequeue():移除并返回Queue<T>开头的对象。

Peek():返回Queue<T>开头的对象,但不删除它。

EnsureCapacity(Int32 capacity):确保此队列的容量至少为指定的capacity。如果当前容量小于capacity,则依次增加到当前容量的两倍,直到至少达到指定capacity。

Equals(Object object):确定指定object是否等于当前对象。

GetEnumerator():返回一个枚举数,该枚举数遍历Queue<T>。

GetHashCode():获取默认的哈希值。

MemberwiseClone():创建当前对象的浅拷贝。

ToArray():将Queue<T>集合中的元素,复制到另一个新数组中。

TimExcess():当数量少于当前容量的90%时,将Queue<T>集合的容量,调整为实际元素的数量。

TryDequeue(T result):删除Queue<T>开头的对象,并将其复制到result参数。返回布尔变量,用于指示是否删除成功。

TryPeek():返回一个值,该值指示Queue<T>的开头是否存在对象,如果存在,则将其复制到result参数。该对象未从Queue<T>中移除。

五、Queue<T>集合的实例代码

下面的代码示例演示了Queue<T>泛型类的几个方法。代码示例创建一个具有默认容量的字符串队列,并使用Enqueue方法对五个字符串进行排队。枚举队列的元素,这不会改变队列的状态。Dequeue方法用于将第一个字符串从队列中取出。Peek方法用于查看队列中的下一个项目,然后使用Dequeue方法将其从队列中取出。

ToArray方法用于创建数组并将队列元素复制到其中,然后将该数组传递给queue <T>构造函数,该构造函数接受IEnumerable<T>,从而创建队列的副本。显示副本的元素。

创建一个两倍于队列大小的数组,并使用CopyTo方法复制从数组中间开始的数组元素。再次使用Queue<T>构造函数来创建队列的第二个副本,该队列在开头包含三个null元素。

Contains方法用于显示字符串“four”位于队列的第一个副本中,之后Clear方法清除该副本,Count属性显示队列为空。

using System;
using System.Collections.Generic;

class Example
{
    public static void Main()
    {
        Queue<string> numbers = new Queue<string>();
        numbers.Enqueue("one");
        numbers.Enqueue("two");
        numbers.Enqueue("three");
        numbers.Enqueue("four");
        numbers.Enqueue("five");

        // A queue can be enumerated without disturbing its contents.
        foreach( string number in numbers )
        {
            Console.WriteLine(number);
        }

        Console.WriteLine("\nDequeuing '{0}'", numbers.Dequeue());
        Console.WriteLine("Peek at next item to dequeue: {0}",
            numbers.Peek());
        Console.WriteLine("Dequeuing '{0}'", numbers.Dequeue());

        // Create a copy of the queue, using the ToArray method and the
        // constructor that accepts an IEnumerable<T>.
        Queue<string> queueCopy = new Queue<string>(numbers.ToArray());

        Console.WriteLine("\nContents of the first copy:");
        foreach( string number in queueCopy )
        {
            Console.WriteLine(number);
        }

        // Create an array twice the size of the queue and copy the
        // elements of the queue, starting at the middle of the
        // array.
        string[] array2 = new string[numbers.Count * 2];
        numbers.CopyTo(array2, numbers.Count);

        // Create a second queue, using the constructor that accepts an
        // IEnumerable(Of T).
        Queue<string> queueCopy2 = new Queue<string>(array2);

        Console.WriteLine("\nContents of the second copy, with duplicates and nulls:");
        foreach( string number in queueCopy2 )
        {
            Console.WriteLine(number);
        }

        Console.WriteLine("\nqueueCopy.Contains(\"four\") = {0}",
            queueCopy.Contains("four"));

        Console.WriteLine("\nqueueCopy.Clear()");
        queueCopy.Clear();
        Console.WriteLine("\nqueueCopy.Count = {0}", queueCopy.Count);
    }
}

/* This code example produces the following output:

one
two
three
four
five

Dequeuing 'one'
Peek at next item to dequeue: two
Dequeuing 'two'

Contents of the first copy:
three
four
five

Contents of the second copy, with duplicates and nulls:



three
four
five

queueCopy.Contains("four") = True

queueCopy.Clear()

queueCopy.Count = 0
 */

六、Queue<T>集合的源码分析

Enqueue中,是将数据保存到一个数组中,数组的初始容量为0。在插入第一个数据时,进行扩容,此时数据的容量个数为4。

6.1、Enqueue(T object)方法的源码分析

下列代码是Enqueue(T object)方法的源码。根据源码可以得到以下几点信息:

1、在插入新数据时,是先判断是否有多余空间,如果有,则直接插入,如果没有则先扩容再插入。

2、扩容时,一般是将容量扩大为当前容量的2倍。但是容量的增加数不能小于4,如果小于4则直接扩容4个。

3、Enqueue<T>集合在初始化时,默认的容量数为0,只有向集合中添加第一个元素的时候,才进行容量初始化,初始容量为4。

[__DynamicallyInvokable]
public void Enqueue(T item)
{
    //先判断集合是否有多余空间, 如果没有多余空间,则进行扩容操作,如果有多余空间,则跳过
	if (_size == _array.Length)
	{
        //扩容时,一般是将容量扩大为当前容量的2倍
		int num = (int)((long)_array.Length * 200L / 100);
        容量的新增数不能小于4,否则容量直接增加4
		if (num < _array.Length + 4)
		{
			num = _array.Length + 4;
		}
		SetCapacity(num);
	}
	_array[_tail] = item;
	_tail = (_tail + 1) % _array.Length;
	_size++;
	_version++;
}

6.2、Dequeue()方法的源码分析

下列代码是Dequeue(T object)方法的源码。根据源码可以得到以下几点信息:

1、先判断当前集合中是否含有元素,如果不含有元素,报错。

2、创建一个泛型类型的对象,并赋值为数组里,索引为head的元素。然后head数+1。

3、该方法不会使数组的元素总个数减少,只是删除刚刚获取的数据,将该数据值改为泛型的默认值。然后将指针向后移。这也就给了一个感觉:Queue是先进先出,Dequeue()将获取的元素删除。

[__DynamicallyInvokable]
public T Dequeue()
{
	//判断当前集合中是否有元素
	if (_size == 0)
	{
		ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EmptyQueue);
	}
	//创建一个泛型类型的对象,并赋值为数组里的索引为head的元素
	T result = _array[_head];
    //然后将数组里的索引为head的元素,改为泛型类型的默认值。
	_array[_head] = default(T);
	_head = (_head + 1) % _array.Length;
	_size--;
	_version++;
	return result;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

木林森先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值