一、单例模式实例应用
qaq
设计模式是面向对象编程中,使其更高效或者解决问题的设计思想(例如重用代码、让代码更容易被他人理解、保证代码可靠性)
例如,单例模式
特点:
应用场景:
单例实现的方式:
懒汉式和饿汉式
懒汉式:类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例
饿汉式:类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。
三、使用ArrayList,HashMap集合,以及底层相应的数据结构、核心实现方法
1. ArrayList(线程不安全)
-
ArrayList 继承了 AbstractList ,并实现了 List 接口
·····························································································································
(1) List的常见具体实现有:ArrayList、LinkedList、Vctor、 CopyOnWriteArrayList、Collections.synchronizedList等
(2)在多线程的环境下使用ArrayList,如何线程安全性第一,使用synchronized关键字; 第二,可以用Collections类中的静态方法synchronizedList();对ArrayList进行调用即可。 第三,使用concurrent并发包下的CopyOnWriteArrayList类
·····························································································································
-
(底层实现):数组,其容量能够自动增加(默认是10,当新建时候数组长度为0,;当插入第一个元素时候才会将内部的Object数组开辟)
-
(扩容机制)如果使用无参构造方法,每当容量到达最大量就会自动扩容原来容量的1.5倍。如果扩容前的容量为0,则先扩容容量为10 使用grow()方法进行扩容。
-
ArrayList优点:
-
底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找也就是get的时候非常快 添加、遍历、下标访问很高效 自动扩容1.5倍数
-
ArrayList缺点
插入删除效率不高 线程不安全
源码解析博客:https://blog.csdn.net/weixin_46157889/article/details/114550528
2. HaspMap描述(线程不安全)
-
键值对存储
-
HashMap的初始容量是16,容量必须是 2 的指数次幂
如果初始化设置为 13 ,那么会给你升级到 16,如果是7,那就会自动升级到8。 -
为什么初始容量是16,且容量必须是2的指数次幂呢?
(1)、初始容量设置为16,(与运算哈希函数处理时候1111使分布较均匀)hash均匀分布的原则,是为了降低hash碰撞的几率
(2)在jdk1.8之后,设置了高位指针和低位指针,在进行扩容时,保证位运算出来的值始终是0或者1。
jdk1.7 jdk1.8的区别细节参考博客:https://blog.csdn.net/Vince_Wang1/article/details/105888297
3、hashMap和hashset的联系
底层实际是用HashMap实现的(HashSet本质就是一个简化版的HashMap)Set中不允许有重复的元素,类似于集合,在HashSet的实现的时候,通过Map来实现,每次往Set里添加数据,都会将数据设置为Map的键值,Map的值设置为一个默认值,因为Map的键值不能重复,所以每次添加到Set内的数据也不能重复。
4、为什么到8转换为红黑树 到6转换为链表
-
TreeNodes(红黑树)占用空间是普通的Nodes(链表)的两倍,为了时间和空间的权衡
-
红黑树的查找效率为o(logN),要优于链表的o(N),但是当链表长度比较小的时候,即使全部遍历,时间复杂度也不会太高。
-
如果真的碰撞发生了8次,这个时候说明由于元素本身和hash函数的原因,此时的链表性能已经已经很差,操作的hash碰撞的可能性非常大,后序可能还会继续发生hash碰撞。此情况适合转换为红黑树
-
节点的频率分布会遵循泊松分布,链表长度达到8个元素的概率为0.00000006,几乎是不可能事件
-
为什么转化为红黑树的阈值和链表的阈值6不一样,是避免频繁的来回转化
-(如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果HashMap不停的插入,删除元素,链表个数在8左右徘徊,就会频繁的发生红黑树转链表,链表转红黑树,效率会很低下。)
相关小结
一:List
List的常见具体实现有:ArrayList、LinkedList、Vctor、 CopyOnWriteArrayList、Collections.synchronizedList等
1:ArrayList 底层数据结构是基于数组,查询和修改快,增删慢。线程不安全,以前的默认初始化容量是10,现在是0,可动态扩容,扩容后的容量=初始容量+初始容量/2。
2:LinkedList 底层数据结构是基于链表结构,增加和删除快,查询和修改慢,线程不安全。
3:Vctor 底层数据结构是基于数组,因为在每个方法是前面都加了synchronized同步锁机制,所有线程安全。但是效率不高,现在比较少用
4:CopyOnWriteArrayList 底层是基于数据结构,在部分方法上加了分段的同步锁机制,线程安全。但是由于添加的时候需要先复制一份数据出来,需要多消耗一些资源,因此多应用于查询多的高并发场景。
5:Collections.synchronizedList 线程安全,一般用于高并发的场景。
二: Set
Set的常见实现有HashSet 、TreeSet、LinkedHashSet
1:HashSet 底层数据结构基于hash算法实现,可保证元素不重复,但是无序
2:TreeSet 底层数据结构是基于二叉树结构,可保证元素有序
3:LinkedHashSet 用链表来保证元素的有序性,遍历整个集合时,效率比HashSet高,插入元素时效率略低
三:Map
Map的常见实现有HashMap、HashTable、LinkedHashMap、ConcurrentHashMap、Collections.synchronizedMap
1:HashMap 1.7版本及以前底层数据结构是数组+链表 1.8开始是数组+链表+红黑树,在链表的深度大于8时自动转换成红黑树结构。 默认初始化容量是16,负载因子为0,75,可动态扩容。线程不安全,key和value 值允许为空。
2:HashTable 区别于HashMap在加了synchronized同步锁机制,线程安全,key和value 值不允许为空,但效率低,较少使用。
3:与HashMap的区别在与可通过链表结构,保证元素的相对有序性,线程不安全。
4: ConcurrentHashMap 底层数据结构与HashMap类似,但是由于有synchronized同步锁机制,线程安全。通常用在高并发场景下保证数据一致性。
5:Collections.synchronizedMap 线程安全,但是效率低,一般不使用。
四、Linux基本操作指令
- 基本指令
ls 展示所有子目录和文件(后面加-l查看属性信息;-a显示隐藏文件;-al显示隐藏文件信息)
pwd 显示用户当前所在目录对应的路径
tar -zxvf 文件名 (解压命令)
unzip zipFileName
sudo apt-get install 安装的东西
unrar rarFileName(解压rar文件)
unrar 原目录文件夹 目标文件夹
ls 查看文件夹
cd 名字 (进入指定文件夹)
rm -rf 目标文件 (删除文件)
mkdir 文件名(创建文件夹)
vim 文件名(打开文件)
i (可插入可编辑)
kill 端口号(杀死一个进程)
ifconfig 查看网络IP地址
history (查看之前历史命令)
pwd 查看当前文件夹的绝对路径
cat a.txt 查看a文件内容
tail xxx 作用:查看某个文件,默认最后十行
tail -n 20 文件名 (查看文件后20行)
tail -f 文件名9
tail -f a.log(查看a文件log日志)
touch a.txt 创建a文件
vim a.txt 创建编写文件
************************************************************
a.先返回到一般模式 Esc
b.冒号切换到命令行模式
c.保存文件 :w
d.退出vim :q
************************************************************
ps -ef|grep 服务包名称 作用:查看服务的进程号以及判断该服务是否处于生存状态
netstat -nap|grep port 查看端口号port被哪一进程占用
kill -9 xxxx 作用:杀死进程号为xxxx的进程。
gedit xxx 作用:打开并编辑xxx文件
vi xxx 作用:编辑xxx文件
vi配套命令,按住i,进入插入模式,编辑完成后按esc键退出编辑模式,:wq 回车保存,:q!强制退出不保存 。
find / -name xxx 作用:从根目录开始查找名为xxx的文件或文件夹
whereis xxx 作用:搜索xxx文件或者命令
chmod 777 xxx 作用:是给xxx文件或者文件夹授予最高权限
sudo su 作用:切换为超级管理员
apt install xxxx 作用:在线包管理安装命令,安装xxxx软件
dpkg -i xxxx 作用:安装离线本地包xxxx
cp -r 原路径文件夹或文件 目的路径文件夹 作用:将文件夹或文件 复制到目的文件夹下
tar zxvf xxxx.tar 作用:解压后缀为.tar的压缩包。(注:压缩命令较多,压缩包后缀不同使用的解压和压缩的命令也不相同)
ip addr 或 ifconfig 作用:查看当前ip地址
五、熟悉数组,链表,树,栈,堆等数据结构
1. 数组的基本操作
Insert - 在某个索引处插入元素
Get - 读取某个索引处的元素
Delete - 删除某个索引处的元素
Size - 获取数组的长度
这里解释一个概念问题。
一维数组是线性结构的,那么二维乃至多维数组不是线性结构
2. 栈(后进先出,线性结构)
Push — 在栈的最上方插入元素
Pop — 返回栈最上方的元素,并将其删除
isEmpty — 查询栈是否为空
Top — 返回栈最上方的元素,并不删除
3.队列(先进先出)
Enqueue — 在队列末尾插入元素
Dequeue — 将队列第一个元素删除
isEmpty — 查询队列是否为空
Top — 返回队列的第一个元素
4、链表(线性结构)
链表分为 2 种:单向链表、双向链表
链表的基本操作
InsertAtEnd — 在链表结尾插入元素
InsertAtHead — 在链表开头插入元素
Delete — 删除链表的指定元素
DeleteAtHead — 删除链表第一个元素
Search — 在链表中查询指定元素
isEmpty — 查询链表是否为空
5.树(特殊的图,多用于存储)
树(Tree)是一个分层的数据结构,由节点和连接节点的边组成。
树是一种特殊的图,它与图最大的区别是没有循环。
树被广泛应用在人工智能和一些复杂算法中,用来提供高效的存储结构。
树有很多分类,这里简单列举,另外做解释:
N 叉树(N-ary Tree)
平衡树(Balanced Tree)
二叉树(Binary Tree)
二叉查找树(Binary Search Tree)
平衡二叉树(AVL Tree)
红黑树(Red Black Tree)
6.hash(key-value键值对存储)
- value=f(key) 或者 存储地址=f(关键字),f()为哈希函数或者散列函数。
- 哈希表就是一种以键值对存储数据的结构,采用散列函数将记录存储在一块连续的存储空间中,这块连续的存储空间称为哈希表。
- 所得的存储地址称为哈希地址或散列地址。
结论
常用的线性结构有:线性表,栈,队列,双队列,数组,串。
常见的非线性结构有:二维数组,多维数组,广义表,树(二叉树等),图。
六、八大排序算法
1.冒泡排序
- 思想:
1、每一次遍历比较,将最大值筛选出来放到数组的最后一个位置array[length-1]
2、继续遍历数组0-array[length-2]
3、重复上述步骤,直到比较到数组下标0 - 循环:两层循环
- 代码:
2.快速排序
- 思想:
以基准分 小于基准 和 大于基准的两个部分 + 递归
1、以第一个数为基准,遍历将大于基准的数值放到数组后半部分位置,小于基准数组放到前半部分位置,最后将基准值放到中间的空位
2、被划分的两个子数组递归执行上述过程 - 代码:
七、反射、代理、内部类·、多态、接口
1、反射
- Java反射机制是在运行状态中,对于任意的一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用他的任意一个方法和属性(通过动态获取的信息以及动态调用对象的方法的功能机制)
熟悉Java 基础如反射,内部类,代理,多态,接口等基础知识
了解Jvm 内存结构,对象创建过程,类加载机制和各个内存区域的垃圾回收算法、对象分配策略等
了解ThreadLocal的使用,Java多线程中volatile关键字,synchronized锁的实现原理以及优化后锁升级的过程等
了解os中进程、线程,管程、纤程、协程的概念以及区别
熟悉Mysql有数据库设计经验,了解B+树索引和Hash索引,了解聚簇索引和非聚簇索引以及数据库的相关优化
熟悉常用的悲观锁、乐观锁和分布式锁以及实现原理,了解线程池和自定义线程池以及线程池参数等
了解数据库中的事务以及隔离级别,熟悉数据库中的共享锁,排它锁以及更新锁等,了解cas算法原理 熟练掌握数据库的sql命令
了解java常用的设计模式,如单例模式,代理模式,工厂模式等
了解Spring框架原理,了解IOC与AOP的设计以及编程思想,使用过切面编程
了解Redis的常用数据类型以及内存模型、持久化方式,主从复制以及哨兵机制,了解缓存穿透、雪崩以及击穿等原理和解决方案等
理解计算机网络的相关知识,了解TCP三次握手、四次挥手,TCP、UDP的区别,了解http长短链接概念以及区别,了解对称加密以及非对称加密等
理解Nginx负载均衡原理,用Nginx部署过项目
了解RabbitMQ原理,了解消息队列如何保持幂等性,消息丢失消息顺序性等和如何处理