《C++ Primer》 第九章 顺序容器

news2024/11/25 5:04:30

《C++ Primer》 第九章 顺序容器

9.1 顺序容器概述

容器:特定类型对象的集合

顺序容器类型

  • vector 可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除元素可能很慢
  • deque 双端队列。支持快速随机访问。在头尾位置插入/删除速度很快
  • list 双向列表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快
  • forward_list 单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快
  • array 固定大小数组。支持快速随机访问。不能添加或删除元素
  • string 与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快

9.2 容器库概览

某些类没有默认构造函数,我们可以定义一个保存这种类型对象的容器,但我们在构造这种容器时不能只传递给它一个元素数目参数:

//假设noDefault是一个没有默认构造函数的类型
vector<noDeault> v1(10, init);//正确,提供了元素初始化器
vector<noDefault> v2(10);	//错误,必须提供一个元素初始化器

容器操作:

  • iterator :此容器类型的迭代器类型
  • const_iterator:可以读取元素,但不能修改元素的迭代器类型
  • size_type:无符号整数类型,足够保存此种容器类型最大可能容器的大小
  • different_type:带符号整数类型,足够保存两个迭代器之间的距离
  • value_type:元素类型
  • reference:元素的左值类型;与value_type&含义相同
  • const_reference:元素的const左值类型(const value_type&)
  • C c; 默认构造函数,构造空容器。如果C是一个array, 则c中元素按默认方式初始化,否则c为空
  • C c1(c2); 构造c2的拷贝c1,c1和c2必须是相同类型(相同的容器类型和元素类型;对于array类型,两者还必须具有相同大小)
  • C c(b, e); 构造c,将迭代器b和e指定的范围内的元素拷贝到c(array不支持),元素类型需相容。
  • C c(a, b, c…); 列表初始化c
  • c1 = c2 将c1中的元素替换为c2中元素
  • c1={a, b, c…} 将c1中的元素替换为列表中元素(不适用于array)
  • a.swap(b) 交换a和b中的元素
  • c.size() c中元素的数目(不支持forward_list)
  • c.max_size() c可保存的最大元素数目
  • c.empty() 若c中存储了元素,返回false,否则返回true
  • c.insert(args) 将args中的元素拷贝进c
  • c.emplace(this) 使用inits构造c中的一个元素
  • c.erase(args) 删除args指定的元素
  • c.clear() 删除c中的所有元素,返回void
  • ==, != 所有容器都支持相等(不等)运算符
  • <,<=,>,>=: 关系运算符(无序关联容器不支持)
  • c.begin(), c.end() 返回指向c的首元素和尾元素之后位置的迭代器
  • c.cbegin(), c.end() 返回const_iterator
  • 反向容器的额外成员(不支持forward_list)
  • reverse_iterator 按逆序寻址元素的迭代器
  • const_reverse_iterator 不能修改元素的逆序迭代器
  • c.rbegin(), c.rend() 返回指向c的尾元素和首元素之前位置的迭代器
  • c.crbegin(), c.crend() 返回const_reverse_iterator
  • 只有顺序容器(不包括array)的构造函数才能接受大小参数
  • C seq(n) seq 包含n个元素, 这些元素进行了值初始化;此构造函数是explicit的 (string不适用)
  • C seq(n, t) seq包含n个初始化为值t的元素。
  • swap(c1,c2) 交换c1和c2的元素,c1和c2必须具有相同的类型。swap通过比从c2向c1拷贝元素快得多
  • c1.swap(c2)
  • assign操作不适合关联容器和array
  • seq.assign(b,e) 将seq中的元素替换为迭代器b和e所表示的范围中的元素。迭代器b和e不能指向seq中的元素
  • seq.assign(i1) 将seq中的元素替换为初始化列表i1中的元素
  • seq.assign(n, t) 将seq中的元素替换为n个值为t的元素

end():指向尾元素之后的位置,因此迭代器范围[begin, end)。end可以与begin指向相同的位置,但不能指向begin之前的位置。

反向迭代器是一种反向遍历容器的迭代器,与正向迭代器相比,各种操作的含义也都发生了颠倒。如对于一个反向迭代器执行++操作,会得到上一个元素。

显示使用类名使用相应类型:

//iter是通过list<string>定义的一个迭代器类型
list<string>::iterator iter;
//count是通过vector<int>定义的一个difference_type类型
vector<int>::difference_type count;

将一个容器初始化为另一个容器的拷贝:

  • 直接拷贝整个容器
  • (array除外) 拷贝由一个迭代器对指定的元素范围

当一个容器初始化另一个容器的拷贝时,两个容器的容器类型和元素类型必须相同

list<string> authors ={"Milton","Shakespeare","Austen"};
vector<const char*> articles = {"a", "an", "the"};

list<string> list2(authors);	//正确:类型匹配
deque<string> authList(authors);//错误:容器类型不匹配
vector<string> words(articles); //错误:容器类型必须匹配
//正确:可以将const char* 元素转换为string
forward_list<string> words(articles.begin(), articles.end());

//拷贝元素,直到(但不包括)it指向的元素
deque<string> authList(authors.begin(), it);

标准库array具有固定大小:

当定义一个array时,除了指定元素类型,还要指定容器大小:

array<int, 42>  //保存为42个int的数组
array<string, 10>//保存为10个string的数组
//使用array类型时需要同时指定元素类型和大小
array<int, 10>::size_type i;	//数组类型包括元素类型和大小
array<int>::size_type j;      //错误:array<int>不是一个类型

虽然我们不能对内置数组进行拷贝和对象赋值操作,但array并无此限制。

int digs[10] = {0,1,2,3,4,5,6,7,8,9};
int cpy[10] = digs;//错误:内置数组不支持拷贝或赋值
array<int,10> digits = {0,1,2,3,4,5,6,7,8,9};
array<int,10> copy = digits;//正确:只要数组类型匹配即合法

使用assign(仅顺序容器)

assign操作用参数所指定的元素(的拷贝)替换左边容器中的所有元素。

list<string> names;
vector<const char*> oldstyle;
names = oldstyle;//错误:容器类型不匹配
//正确:可以将const char* 转换成string
names.assign(oldstyle.cbegin(), oldstyle.cend())

assign的第二个版本接受一个整型值和一个元素值。它用指定数目且具有相同给定的元素替换容器中原有的元素:

//等价于slist1.clear()
//后跟slist1.insert(slist1.begin(), "Hiya!");
list<string> slist1(1);  //一个元素,为空string
slist1.assign(10,"Hiya!"); //10个元素, 每个都是"Hiya!“

使用swap:交换两个相同类型容器的内容。调用swap之后,两个容器内的元素将会交换:

vector<string> svec1(10);
vector<string> svec2(24);
swap(svec1, svec2);

9.3 顺序容器操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6JU6NL4O-1677738374134)(C:\Users\21147\AppData\Roaming\Typora\typora-user-images\1673515074120.png)]

使用push_front:

list<int> ilist;
//将元素添加到ilist开头
for (size_t ix=0; ix!=4;++ix)
	ilist.push_back(ix);
//ilist保存序列3,2,1,0

insert函数将元素插入到迭代器所指定的位置之前。

slist.insert(iter, "Hello!"); //将"Hello“添加到iter之前的位置
vector<string> svec;
list<string> slist;
//等价于调用slist.insert(iter, "Hello!")
slist.insert(slist.begin(),"Hello!");
//vector不支持push_front,但我们可以插入到begin()之前
svec.insert(svec.begin(), "Hello!");

插入范围元素:

svec.insert(svec.end(), 10, "Anna");
//将10个元素插入到svec的末尾,并将所有元素初始化为string "Anna"
vector<string> v={"quasi", "simba", "frollo","scar"};
//将v的最后两个元素添加到slist的开始位置
slist.insert(slist.begin(), v.end()-2, v.end());
slist.insert(slist.end(),{"these", "words", "will",
							"go","at","the","end"});
//运行时错误:迭代器表示要拷贝的范围,不能指向与目的位置相同的容器
slist.insert(slist.begin(), slist.begin(), slist.end());

使用insert的返回值:通过使用insert的返回值,可以在容器中一个特定位置反复插入元素

list<string> lst;
auto iter = lst.begin();
while(cin>>word)
	iter = lst.insert(iter,word);//等价于调用push_front

使用emplace操作:emplace_front emplace和emplace_back,这些操作分别对应push_front、insert和push_back,允许我们将元素放置在容器头部、一个指定位置之前或容器尾部。

调用push或Insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。当我们调用一个emplace成员函数时,则是将参数传递给元素类型的构造函数。emplace成员使用这些参数在容器管理的内存空间中直接构造函数。

//在c的末尾构造一个Sales_data对象
//使用三个参数的Sales_data构造函数
c.emplace_back("978-33743673",25,15.99);
//错误:没有接受三个参数的push_back版本
c.push_back("978-33743673",25,15.99);
//正确:创建一个临时的Sales_data对象传递给push_back
c.push_back(Sales_data("978-33743673",25,15.99));

在调用emplace_back时,会在容器管理的内存空间中直接创建对象。而调用push_back则会创建一个局部临时对象,并将其压入容器中。

emplace函数的参数根据元素类型而变换,参数必须与元素类型的构造函数相匹配:

//iter指向c中一个元素,其中保存了Sales_data元素
c.emplace_back();//使用Sales_data的默认构造函数
c.emplace(iter, "999-9999999");//使用Sales_data(string)
//使用Sales_data的接受一个ISBN、一个count和一个price的构造函数
c.emplace_front("999-99999",25,25.9);

emplace函数在容器中直接构造元素。传递给emplace函数的参数必须与元素类型的构造函数相匹配。

包括array在内的每个顺序容器都有一个front成员函数,而除forward_list之外的所有顺序容器都有一个back成员函数。这两个操作分别返回首元素和尾元素的引用:

//在解引用一个迭代器或调用front或back之前检查是否有元素
if(!c.empty()){
	//val和val2是c中第一个元素值的拷贝
	auto val = *c.begin(), val2 = c.front();
	//val3和val4是c中最后一个元素值的拷贝
	auto last = c.end();
	auto val3 = *(--last);//不能递减forward_list迭代器
	auto val4 = c.back();
}

在这里插入图片描述

访问成员函数返回的是引用:在容器中访问元素的成员函数(front、back、下标和at ) 返回的都是引用。如果容器是一个const对象,则返回值是const的引用。

if(!c.empty()){
	c.front() = 42; //将42赋予c中的第一个元素
	auto &v = c.back();	//获得指向最后一个元素的引用
	v = 1024;	//改变c中的元素
	auto v2 = c.back();	//v2不是一个引用,它是c.back()的一个拷贝
	v2 = 0;未改变c中元素
}

如果我们希望确保下标是合法的,可以使用at成员函数。at成员函数类似下标运算符,如果下标越界,at会抛出一个out_of_range异常。

在这里插入图片描述

成员函数erase从容器中指定位置删除元素:

list<int> lst={0,1,2,3,4,5,6,7,89};
auto it=lst.begin();
while(it!=lst.end())
	if(*it%2)
		it = lst.erase(it);
	else
		++it;

//删除两个迭代器表示的范围内的元素
//返回指向最后一个被删元素之后位置的迭代器
elem1 = slist.erase(elem1, elem2); //调用后,elem1==elem2

forward_list操作:

在这里插入图片描述

从forward_list中删除元素:

forward_list<int> flst = {0,1,2,3,4,5,6,7,8,9};
auto prev = flst.before_begin();   //表示flst的"首前元素"
auto curr = flst.begin();	//表示flst中的第一个元素
while(curr!=flst.end()){
	if(*curr%2)
		curr = flst.erase_after(prev);
	else{
		prev = curr;//移动迭代器curr,指向下一个元素,prev指向curr之前的元素
		++curr;
	}
}

改变容器大小resize():如果当前大小小于所要求的大小,容器后部的元素会被删除;如果当前大小小于新大小,会将新元素添加到容器后部。

在这里插入图片描述

编写改变容器的循环:

vector<int> vi={0,1,2,3,4,5,6,7,8,9};
auto iter=vi.begin();//调用begin而不是cbegin,因为要改变vi
while(iter!=vi.end()){
	if(*iter % 2){
		iter = vi.insert(iter,*iter);//复制当前元素
		iter += 2;//向前移动迭代器,跳过当前元素以及插入到它之前的元素
	}else
		iter = vi.erase(iter); //删除偶数元素
		//不应向前移动迭代器,iter指向我们删除元素之后的元素
}

不要保存end返回的迭代器:此代码会导致无线循环。问题在于我们将end操作返回的迭代器保存在一个名为end的局部变量中。在循环体中,我们向容器中添加了一个元素,这个操作使保存在end中的迭代器失效了。这个迭代器不再指向任何元素或是v中尾元素之后的位置。

//此循环的行为是未定义的
auto begin = v.begin(), end = v.end();//保存尾迭代器的一个坏主意
while(begin != end){
	//插入新值,对begin重新赋值,否则的话它会失效
	++begin;//向前移动begin,因为我们想在此元素之后插入元素
	begin = v.insert(begin, 42);	//插入新值
	++begin;//向前移动begin跳过刚刚加入的元素
}

如果在一个循环中插入/删除 deque, string或vector中的元素,不要缓存end返回的迭代器。

必须在每次插入操作后重新调用end(),而不能在循环开始前保存它返回的迭代器。

//安全的方法:在每个循环步添加/删除元素后都重新计算end
while(begin!=v.end()){
	++begin;
	begin = v.insert(begin, 42);
	++begin;
}

9.4 vector 对象是如何增长的

管理容量的成员函数:
在这里插入图片描述

capacity和size: 容器中的size是指它已经保存的元素的数目;而capacity则是在不分配新的内存空间的前提下它最多可以保存多少元素。可以调用shrink_to_fit来要求vector将超出当前大小的多余内存退回给系统。

9.5 额外的string操作

在这里插入图片描述

通常从一个const char*创建string时,指针指向的数组必须以空字符结尾,拷贝操作遇到空字符时停止。

substr操作:返回原始string的一部分或全部的拷贝。

string s("hello world");
string s2=s.substr(0,5);//s2=hello
string s3=s.substr(6); //s3=world
string s4=s.substr(6,11);//s4=world
string s5=s.substr(12);//抛出一个out_of_range异常

如果开始位置超过了string的大小,则substr函数抛出一个out_of_range异常。如果开始位置加上技术支持大于string的大小,则substr会调整计数值,只拷贝到string的末尾。

在这里插入图片描述

改变string: assign、insert和erase操作。

在这里插入图片描述

在这里插入图片描述

string 搜索:
在这里插入图片描述
在这里插入图片描述

compare函数:

在这里插入图片描述

数值转换:

在这里插入图片描述

9.6 容器适配器

在这里插入图片描述

栈适配器:

在这里插入图片描述

队列适配器:

在这里插入图片描述

在这里插入图片描述

9.7 概念总结

begin和cbegin之间的区别:

  • cbegin与auto结合使用。它返回指向容器第一个元素的const迭代器,可以用来只读地访问容器元素,但不能对容器元素进行修改。因此,当不需要写访问时,应该使用cbegin
  • begin则是被重载过的,有两个版本:其中一个是const成员函数,也返回const迭代器;另一个则返回普通迭代器,可以对容器元素进行修改。

vector初始化方式:

  • vector list1; 默认初始化,vector为空,size返回0,表明容器中尚未有元素;capacity返回0,意味着尚未分配存储空间。这种方式适用于元素个数位置,需要在程序运行中动态添加的情况
  • vector list2(list1); list2初始化list1的拷贝, list1必须与list2类型相同,且具有相同的容量和元素。
  • vector list = {1, 2, 3.0, 4, 5, 6, 7}; 初始化为列表中元素的拷贝,列表中的元素类型必须与list的元素类型相同。对于整型,对直接拷贝其值,对于其它类型,则需进行类型转换。
  • vector list3(list.begin()+2, list.end()-1); list3初始化为两个迭代器指定范围中元素的拷贝,范围中的元素类型必须与list3的元素类型相容。
  • vector list4(7); 默认初始化,list4中将包含7个元素,每个元素进行缺省的值初始化。
  • vector list5(7,3); 指定值初始化,list5被初始化为包含7个值为3的int。

为什么list或array没有capacity成员函数?

  • list是链表,当有新元素加入时,会从内存空间中分配一个新节点保存它;当从链表中删除元素时,该节点占用的内存空间会被立刻释放。因此,一个链表占用的内存空间总是与它当前保存的元素所需空间相等,即capacity总是等于size
    表中的元素类型必须与list的元素类型相同。对于整型,对直接拷贝其值,对于其它类型,则需进行类型转换。
  • vector list3(list.begin()+2, list.end()-1); list3初始化为两个迭代器指定范围中元素的拷贝,范围中的元素类型必须与list3的元素类型相容。
  • vector list4(7); 默认初始化,list4中将包含7个元素,每个元素进行缺省的值初始化。
  • vector list5(7,3); 指定值初始化,list5被初始化为包含7个值为3的int。

为什么list或array没有capacity成员函数?

  • list是链表,当有新元素加入时,会从内存空间中分配一个新节点保存它;当从链表中删除元素时,该节点占用的内存空间会被立刻释放。因此,一个链表占用的内存空间总是与它当前保存的元素所需空间相等,即capacity总是等于size
  • array是固定大小数组,内存一次性分配,大小不变,不会变化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/383760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【2022-09-14】米哈游秋招笔试三道编程题

第一题&#xff1a;最短子串 题目描述 米小游拿到了一个字符串&#xff0c;她想截取一个连续子串&#xff0c;使得该子串中包含至少k个连续的“mihoyo”。 你可以帮米小游求出最短的子串长度&#xff0c;以及对应的子串位置吗&#xff1f; 输入描述 第一行输入两个正整数n…

产品父子流程技术方案设计

产品父子流程技术方案设计 一、整体设计 根据业务需求分析&#xff0c;产品涉及法人代表及实控人风控决策流程调用&#xff0c;旨在降低风险&#xff0c;提高行内线上贷款业务风险决策的能力。 二、业务流程 1.业务流程图 2.交易流程 在授信交易切面入口处对法人代表及实控…

Spark性能优化三 checkpoint

&#xff08;一&#xff09;checkpoint介绍 checkpoint&#xff0c;是Spark提供的一个比较高级的功能。有时候&#xff0c;我们的Spark任务&#xff0c;比较复杂&#xff0c;从初始化RDD开始&#xff0c;到最后整个任务完成&#xff0c;有比较多的步骤&#xff0c;比如超过10个…

关于flex盒子padding-right/margin-right不生效

错误代码实例&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"width…

论文投稿指南——中文核心期刊推荐(科学、科学研究)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

element input 输入框校验

element input 输入框校验 很久之前有写过一篇&#xff1a;element 输入框只可以输入正整数 在这里对它进行补充 校验input输入框是否符合 以下是常用的一些&#xff1a; 限制输入中文&#xff1a;/^[\u4e00-\u9fa5]$/ const checkName (rule, value, callback) > {if…

逆约瑟夫问题

约瑟夫问题可以说十分经典&#xff0c;其没有公式解也是广为人知的~ 目录 前言 一、约瑟夫问题与逆约瑟夫问题 1.约瑟夫问题 2.逆约瑟夫问题 二、思考与尝试&#xff08;显然有很多失败&#xff09; 问题分析 尝试一&#xff1a;递归/递推的尝试 尝试二&#xff1a;条件…

Doris入门篇-分区分桶实验

简介 测试分区分桶效果。 分区的基本操作 添加分区 ALTER TABLE v2x_olap_database.government_car ADD PARTITION p20221203 VALUES LESS THAN ("2022-12-04");动态分区表不能添加分区&#xff0c;需要转为手动分区表。 查看分区 show partitions from <表…

【深度估计】单目深度估计

文章目录什么是深度估计&#xff1f;什么是视差深度估计与三维重建单目深度估计研究历程单目深度估计方法传统方法基于线索线性透视聚焦/散焦度天气散射阴影纹理遮挡高度运动线索基于物体自身运动基于摄像机的运动基于机器学习参数学习方法开创性工作改进加入语义信息条件随机场…

《工业机器视觉检测123》(1.1) 目标检测样本类别不平衡的问题(持续更新...)

部分内容转载自&#xff1a;https://www.cnblogs.com/inchbyinch/p/12642760.html 参考分类任务中解决类别不平衡的办法&#xff1a; 1 什么是类别不平衡问题&#xff1f; 类别不平衡&#xff08;class-imbalance&#xff09;&#xff0c;也叫数据倾斜&#xff0c;数据不平衡…

Tomcat面试问题总结

1.Tomcat是什么&#xff1f;Tomcat 服务器Apache软件基金会项目中的一个核心项目&#xff0c;是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP 程序的首…

EasyCVR视频融合平台的视频处理与AI智能分析流程实操案例介绍

EasyCVR基于云边端一体化架构&#xff0c;能支持海量视频的轻量化接入与汇聚管理。在视频能力上&#xff0c;可提供视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联等。 除了视频能力之外&#xff0c;将…

浅谈设备防漏扫

场景描述 随着社会的信息化&#xff0c;互联网安全被国家越来越重视&#xff0c;漏洞扫描&#xff08;简称漏扫&#xff09;业务也在被规范列入企事业单位的信息安全的标准中。 从安全角度来看&#xff0c;漏扫本身是为用户的用网安全做保障&#xff0c;避免木马、病毒等通过…

vue中点击空白处改变dom状态实现显隐,监听dom(addEventListener)

需求来源&#xff1a;点击铃铛之后弹出右侧抽屉&#xff0c;实现文件下载 现在是点击小铃铛出现弹框没问题&#xff0c;点击关闭图标关闭弹框也没问题&#xff0c;但是点击空白区域消失不了&#xff0c;这个时候需要dom监听属性document.addEventListener来实现需求了 主要是用…

c++学习笔记之基础

目录前言零碎知识点C核心内存分区引用函数类和对象对象的初始化和清理构造函数和析构函数构造函数的分类和调用拷贝构造函数的调用时机深拷贝与浅拷贝初始化列表类对象作为类的成员静态成员C对象模型和this指针成员变量和成员函数分开存储this指针空指针访问成员函数const修饰成…

IDEA2022 配置spark开发环境

本人强烈建议在 linux环境下 学习 spark&#xff01;&#xff01;&#xff01; Introduction Apache Spark是一个快速且通用的分布式计算引擎&#xff0c;可以在大规模数据集上进行高效的数据处理&#xff0c;包括数据转换、数据清洗、机器学习等。在本文中&#xff0c;我们将…

NDK C++ map容器

map容器// TODO map容器 #include <iostream> #include <map>using namespace std;int main() {// TODO map<int, string>按key值排序&#xff0c;同一个key不可以重复插入map<int, string> map1;map1.insert(pair<int, string>(1, "111&qu…

ChatGPT没有API?OpenAI官方API带你起飞

目录ChatGPT没有API&#xff1f;OpenAI官方API带你起飞安装 OpenAI 的 API 库包装个函数包装个UIChatGPT没有API&#xff1f;OpenAI官方API带你起飞 前段时间ChatGPT爆火&#xff0c;OpenAI 的 GPT API也被大家疯狂调用&#xff0c; 但其实这个API是基于GPT3的&#xff0c;和基…

【RabbitMQ】Producer之mandatory、alternative exchange、TTL - 基于AMQP 0-9-1(一)

RabbitMQ系列文章&#xff0c;前几篇介绍了基础概念&#xff0c;AMQP 0-9-1 协议&#xff0c;和服务端安装&#xff0c;准备工作都完成后&#xff0c;就开始着手开发了。这篇文章主要介绍RabbitMQ生产者的开发&#xff0c;包括Producer、Message常见的参数&#xff0c;读完这篇…

20.hadoop系列之Yarn资源调度器

Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&#xff0c;相当于一个分布式的操作系统&#xff0c;而MapReduce等运算程序则相当于运行于操作系统之上的应用程序 1.Yarn基础架构 Yarn主要由ResourceManager、NodeManager、ApplicationMaster和Contai…