文末
初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。
而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。
而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。
通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。
混合式开发,微信小程序。都是得学会并且熟练的
这些是Android相关技术的内核,还有Java进阶
高级进阶必备的一些技术。像移动开发架构项目实战等
Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系
以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。
而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?
就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?
我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。
喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
目录
前言
我们前面介绍了vector容器的概念以及对其基本使用进行了介绍,如果你在这里不知道vector是什么以及不知道如何使用的话,可以进入本人主页,在C++专栏里有介绍
为了对小白友好,在这我简单介绍一下
C++中的vector是一个动态数组容器,可以存储不同类型的元素。它提供了一系列的成员函数来方便地操作和管理数组。
以下是C++ vector容器的一些特点和功能:
- 动态大小:vector的大小可以根据需要动态调整,可以在运行时添加或删除元素。
- 随机访问:可以通过索引直接访问vector中的元素,支持常数时间的随机访问。
- 自动内存管理:vector会自动处理内存分配和释放,无需手动管理内存。
- 插入和删除:可以在任意位置插入或删除元素,vector会自动调整其他元素的位置。
- 迭代器支持:可以使用迭代器遍历vector中的元素。
- 动态增长:当vector的容量不足时,会自动重新分配更大的内存空间,以容纳更多的元素。
- 元素访问:可以使用下标运算符[]或at()函数来访问元素,也可以使用front()和back()函数分别获取第一个和最后一个元素。
本章节主要对vector容器的手撕实现其简单功能
vector容器代码实现
内部成员简介
命名空间实现与库里vector的隔绝,实现自定义vector
namespace A
{
template<class T> //模版实现vector<类型>
class vector //vector功能实现
{
public:
// Vector的迭代器是一个原生指针
typedef T\* iterator;
typedef const T\* const_iterator;
....... //函数接口实现
.......
private:
iterator _start; // 指向数据块的开始
iterator _finish; // 指向有效数据的尾
iterator _endOfStorage; // 指向存储容量的尾
};
}
构造函数
vector()
: \_start(nullptr)
, \_finish(nullptr)
, \_endOfStorage(nullptr)
{}
vector(size_t n, const T& value = T())
: \_start(nullptr)
, \_finish(nullptr)
, \_endOfStorage(nullptr)
{
reserve(n);
while (n--)
{
push\_back(value);
}
}
* 理论上讲,提供了vector(size_t n, const T& value = T())之后
* vector(int n, const T& value = T())就不需要提供了,但是对于:
* vector<int> v(10, 5);
* 编译器在编译时,认为T已经被实例化为int,而10和5编译器会默认其为int类型
* 就不会走vector(size_t n, const T& value = T())这个构造方法,
* 最终选择的是:vector(InputIterator first, InputIterator last)
* 因为编译器觉得区间构造两个参数类型一致,因此编译器就会将InputIterator实例化为int
* 但是10和5根本不是一个区间,编译时就报错了
* 故需要增加如下构造方法
vector(int n, const T& value = T())
: \_start(new T[n])
, \_finish(_start + n)
, \_endOfStorage(_finish)
{
for (int i = 0; i < n; ++i)
{
_start[i] = value;
}
}
拷贝函数
// 若使用iterator做迭代器,会导致初始化的迭代器区间[first,last)只能是vector的迭代器
// 重新声明迭代器,迭代器区间[first,last)可以是任意容器的迭代器
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push\_back(\*first);
++first;
}
}
vector(const vector<T>& v)
: \_start(nullptr)
, \_finish(nullptr)
, \_endOfStorage(nullptr)
{
reserve(v.capacity());
iterator it = begin();
const_iterator vit = v.cbegin();
while (vit != v.cend())
{
\*it++ = \*vit++;
}
_finish = it;
}
vector<T>& operator=(vector<T> v)
{
swap(v);
return \*this;
}
析构函数
~vector()
{
if (_start)
{
delete[] _start;
_start = _finish = _endOfStorage = nullptr;
}
}
迭代器相关
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator cbegin() const
{
return _start;
}
const_iterator cend() const
{
return _finish;
}
容量相关
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _endOfStorage - _start;
}
bool empty() const
{
return _start == _finish;
}
void reserve(size_t n)
{
if (n > capacity())
{
size_t oldSize = size();
// 1. 开辟新空间
T\* tmp = new T[n];
// 2. 拷贝元素
// 这里直接使用memcpy会有问题吗?同学们思考下
//if (\_start)
// memcpy(tmp, \_start, sizeof(T)\*size);
if (_start)
{
for (size_t i = 0; i < oldSize; ++i)
tmp[i] = _start[i];
// 3. 释放旧空间
delete[] _start;
}
_start = tmp;
_finish = _start + oldSize;
_endOfStorage = _start + n;
}
}
void resize(size_t n, const T& value = T())
{
// 1.如果n小于当前的size,则数据个数缩小到n
if (n <= size())
{
_finish = _start + n;
return;
}
// 2.空间不够则增容
if (n > capacity())
reserve(n);
// 3.将size扩大到n
iterator it = _finish;
_finish = _start + n;
while (it != _finish)
{
\*it = value;
++it;
}
}
元素访问
T& operator[](size_t pos)
{
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos)const
{
assert(pos < size());
return _start[pos];
}
T& front()
{
return \*_start;
}
const T& front()const
{
return \*_start;
}
T& back()
{
return \*(_finish - 1);
}
const T& back()const
{
return \*(_finish - 1);
}
vector的修改操作
void push\_back(const T& x)
{
insert(end(), x);
}
void pop\_back()
{
erase(end() - 1);
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_endOfStorage, v._endOfStorage);
}
iterator insert(iterator pos, const T& x)
{
assert(pos <= _finish);
// 空间不够先进行增容
if (_finish == _endOfStorage)
{
//size\_t size = size();
size_t newCapacity = (0 == capacity()) ? 1 : capacity() \* 2;
reserve(newCapacity);
// 如果发生了增容,需要重置pos
pos = _start + size();
}
iterator end = _finish - 1;
while (end >= pos)
{
\*(end + 1) = \*end;
--end;
}
\*pos = x;
++_finish;
return pos;
}
// 返回删除数据的下一个数据
// 方便解决:一边遍历一边删除的迭代器失效问题
iterator erase(iterator pos)
{
// 挪动数据进行删除
iterator begin = pos + 1;
while (begin != _finish)
{
\*(begin - 1) = \*begin;
++begin;
}
--_finish;
return pos;
}
源代码
#pragma once
#include <iostream>
using namespace std;
#include <assert.h>
namespace A
{
template<class T>
class vector
{
public:
// Vector的迭代器是一个原生指针
typedef T\* iterator;
typedef const T\* const_iterator;
///
// 构造和销毁
vector()
: \_start(nullptr)
, \_finish(nullptr)
, \_endOfStorage(nullptr)
{}
vector(size_t n, const T& value = T())
: \_start(nullptr)
, \_finish(nullptr)
, \_endOfStorage(nullptr)
{
reserve(n);
while (n--)
{
push\_back(value);
}
}
/\*
\* 理论上将,提供了vector(size\_t n, const T& value = T())之后
\* vector(int n, const T& value = T())就不需要提供了,但是对于:
\* vector<int> v(10, 5);
\* 编译器在编译时,认为T已经被实例化为int,而10和5编译器会默认其为int类型
\* 就不会走vector(size\_t n, const T& value = T())这个构造方法,
\* 最终选择的是:vector(InputIterator first, InputIterator last)
\* 因为编译器觉得区间构造两个参数类型一致,因此编译器就会将InputIterator实例化为int
\* 但是10和5根本不是一个区间,编译时就报错了
\* 故需要增加该构造方法
\*/
vector(int n, const T& value = T())
: \_start(new T[n])
, \_finish(_start + n)
, \_endOfStorage(_finish)
{
for (int i = 0; i < n; ++i)
{
_start[i] = value;
}
}
// 若使用iterator做迭代器,会导致初始化的迭代器区间[first,last)只能是vector的迭代器
// 重新声明迭代器,迭代器区间[first,last)可以是任意容器的迭代器
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
{
push\_back(\*first);
++first;
}
}
vector(const vector<T>& v)
### 总结
最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,**从来都是我们去适应环境,而不是环境来适应我们!**
这里附上上述的技术体系图相关的几十套**腾讯、头条、阿里、美团等公司2021年的面试题**,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含**知识脉络 + 诸多细节**,由于篇幅有限,这里以图片的形式给大家展示一部分。
**相信它会给大家带来很多收获:**
![](https://img-blog.csdnimg.cn/img_convert/2f1be9bde4c96b5edf9b265eb5953175.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/ab9c76f85b00acf8d1d6cb41cf178f7c.webp?x-oss-process=image/format,png)
> 当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
2021年的面试题**,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含**知识脉络 + 诸多细节**,由于篇幅有限,这里以图片的形式给大家展示一部分。
**相信它会给大家带来很多收获:**
[外链图片转存中...(img-DOjZbhrX-1715670111916)]
[外链图片转存中...(img-eVe6Eqvg-1715670111916)]
> 当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**