基础知识整理

数据结构

概念:数据结构是指数据组织、管理、存储的格式,也可以说 数据与数据之间的关系就是数据结构。使用数据结构主要是提升我们再次使用数据的效率。

常见的四种基本数据结构

  1. 集合结构:存储某种类型的元素集合
  2. 线性结构:一对一的结构,如数组 (array)、列表(linked)、栈 (stack)、队列 (queue)
  3. 树形结构:一对多的结构,如二叉树 (binary tree)
  4. 图状结构:多对多的结构,可以分为无向图和有向图。

常见的数据结构:

  • 数组(Array)
    数据结构简介优点缺点补充
    数组(Array)数组是一块连续的内存空间,每个元素都有下标按照索引随机查找、修改元素,速度很快,命中率高。按照索引遍历数组方便。大小确定后无法改变 。增加、删除元素效率低,需要移动元素来维护下标。硬件角度
    稀疏数组(SparseArray)记录数组有几行几列,以及非空元素所在的行列和值数组中无效数据远大于有效数据,这时使用稀疏数组能更好的节省空间-一般只在需要存储数组时使用
  • 链表(Linked List)
    数据结构简介优点缺点补充
    单向链表(Linked List)由一个或多个节点组成,每个节点由数据域和指针域组成,单向链表指针域只存储下一个节点删除和插入速度快,只需要改变指针指向即可。从硬件的角度考虑,更好的利用了碎片空间。查询慢,需要从头遍历到查询的节点。
    双向链表相较于单向链表,指针域多了一个指针指向上一个节点。可以找到前驱和后继,比较灵活。查询速度也比单向快需要多维护一个指针,增加了一些空间和维护成本(几乎可以忽略)
    单向循环链表数组是一块连续的内存空间,每个元素都有下标按照索引随机查找、修改元素,速度很快,命中率高。按照索引遍历数组方便。大小确定后无法改变 。增加、删除元素效率低,需要移动元素来维护下标。
    双向循环链表双向链表添加删除效率高,随机查询效率低
    其中链表又分为 单向链表、双向链表、单向循环链表、双向循环链表
    优点: 删除和插入速度快,只需要改变指针指向即可。
    缺点: 查询慢,需要从头遍历到查询的节点。
  • 队列
  • 散列表/哈希表

补充:
Q:为什么数组比链表查询快?
A:数组是一块连续的内存空间,


Java集合

Java集合分为两大类Collection\MAP
Collection接口是存储一组无序的对象,下面的接口有
List,一组有序且重复的对象,通过索引访问集合中的元素
Set,一组无序且唯一的对象

MAP:
1)HashMap
底层原理及特点:
底层使用数组加链表的数据结构
特点:HashMap是无序的,线程不安全的,
put方法:
JDK1.7
1.第一次put先初始化数组,如果new hashmap没有指定长度那么默认是16,如果指定了大小进行算法运算出大于等于的二次幂数,
如:传一个9,初始化大小为16。(数组长度一定是2的幂次方)
2.再根据key使用hash算法算出随机的hashcode
3.通过哈希值和当前数组长度,算出当前key值对应在数组中的存放下标
4.获得下标后遍历该下标的链表,是否有key相同的,有相同的就把value覆盖。返回old value。
5.添加entry,先判断需不需要扩容,然后创建entry对象next指向原来数组上的entry,再把数组指向新的entry
扩容机制:
JDK1.7
1.创建一个新的数组是原来数组大小的2倍,也就是2的幂次加一,再根据新数组大小和key重新分列到新数组上。
扩容条件:
当hashmap中的元素总数 大于 数组大小*负载因子(0.75)并且 数组位置不为NULL。
多线程死循环:
两个线程同时使用同OldArray,第一个线程扩容后链表掉头了,第二个线程会造成死循环。
目的:
减少hash碰撞,缩减链表长度提高查询速度。
如何避免:
声明时指定数组大小
JDK1.7和JDK1.8的区别:
1.7: 扩容多线程可能会出现死循环
1.8: 因为链表查询效率低,时间复杂度为O(N),所以链表长度大于等于8使用红黑树时间复杂度为O(logN),
小于6时又装换为链表(不是小于8是为了避免频繁的转换)

2)ConcurrentHashMap康康瑞特(线程安全,put上面加了synchronized’森括莱斯特’)
构造方法:
初始化Segment[]和Segment的HashEntry[]的大小,生成一个原型Segment0放在0下标位置(下一次put的时候不需要重新计算,直接根据原型生成)

3)HashTable(线程安全,在整个hashtable上加了synchronized,效率低下)

List:
1)ArrayList:
底层原理及特点:
ArrayList底层数据结构是动态数组,
优点: 使用索引进行搜索和读取,所以查询速度非常快。
缺点: 但是删除数据开销非常大,因为ArrayList是一块连续的内存,删除需要重新排列数组数据。

add():

2)LinkedList
底层原理及特点:
LinkedList底层实现是双链表
优点:


Java数据类型

基本数据类型:byte short int long float double char boolean
金额使用类型:BigDecimal


Java虚拟机

1)JVM由三个子系统构成:
将class文件通过Class Loader(类加载器)加载到runtime data area
1.1》class loader(类加载器)
1.2》runtime data area(运行时数据区)
1-》虚拟机栈:描述java方法执行的动态内存模型
a.栈帧:每个方法执行都会创建一个栈帧,方法执行完毕栈帧销毁。用于存储局部变量表,操作数栈,动态链接,方法出口。
c.局部变量表:存放编译期间可知的各种基本类型,引用类型,局部变量表的大小在编译期就已经确定,运行时不会发生改变。
d.栈的大小:如果栈满了,StackOverFolwError,递归调用很常见。
2-》本地方法栈:虚拟机的native方法。
3-》程序计数器(PC寄存器):看成当前线程所执行的字节码的行号指示器。
4-》方法区:存储类的信息(如:类的版本号、字段、方法、接口),常量,静态常量。
5-》堆:jvm最大的内存区域,存放对象的实例,也是垃圾收集器管理的主要区域,分为新生代和老生代。
1.3》execution engine(执行引擎)


Java常用设计模式

设计模式分为3种,常用设计模式有
创建型模式:工厂模式、单例模式。。。
结构型模式:适配器模式、代理模式。。。
行为型模式:观察者模式
1)单例模式
懒汉模式:顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则返回,没有则新建。
有线程安全和线程不安全两种写法,区别就是synchronized关键字。
饿汉模式:从名字上也很好理解,就是“比较勤”,实例在初始化的时候就已经建好了,不管你有没有用到,都先建好了再说。
好处是没有线程安全的问题,坏处是浪费内存空间。
public class lh{
private static lh instance;
private lh(){}
public static lh getInstance(){
if(instance != null){
instance = new lh();
}
return instance;
}
}

public class eh{
private static eh instance = new eh();
private eh(){}
public static lh getInstance(){
return instance;
}
}
2)工厂方法模式
3)策略模式
4)观察者模式
5)迭代器模式


4.多线程:
三大特性:原子性、可见性、有序性。
一个程序启动最少创建两个线程。一个main主线程,一个垃圾回收线程。
并发是一个CPU轮流处理多个任务,并行是多个CPU同时处理多个任务。
1)实现方式:
a.实现Runnable接口 //–实例化Thread类并指定实现Runnable类作为参数传入,实例对象.start()方法,
Thread t = new Thread(new MyRunnable); t.start();
b.继承Thread类 //–实例化继承类,实例对象.start()方法,MyThread t = new MyThread(); t.start();
c.Callable(考了博)接口和Future
d.线程池
2)start和run的区别
run只是一个普通的方法在主线程中
而start会启动一个新的线程,是可运行状态的,然后等待cpu调度,获得cpu的时间片后再执行run中的方法
3)怎么手动关闭线程
a.设置退出的判断,run方法执行完自动终止
b.使用stop方法强制终止 //–不推荐使用,可能会导致线程死锁
c.使用interrupt方法中断线程。
4)线程生命周期:
新建:new一个线程对象后,JVM为线程分配内存空间,初始化成员变量。
就绪:线程调用start()方法进入就绪态,JVM为线程创建方法栈和程序计数器,等待获得cpu时间片
运行:获得cpu时间片后开始运行run()方法进入运行态
阻塞:run()方法执行中可能获取资源时发现资源被锁定,或者调用sleep()方法主动放弃处理器资源,进入阻塞态
死亡:run()/call()方法正常执行完毕进入死亡态

)线程安全:
线程同步:
a.同步代码块 synchronized(锁){ 需要}
b.同步方法 public synchronized handl(){}
c.同步锁 lock

5)线程死锁:
p1->r2->p2->r1->p1…
产生死锁的四个必要条件:
(1)互斥条件:一个资源每次只能被一个进程使用。
(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

死锁处理:(死锁预防和避免会导致编码执行效率下降)
	a.死锁预防:在死锁发生之前通过设置某些限制条件,去破坏四个必要条件的其中一个或多个,来防止死锁
		    (互斥条件不可被破坏)
	b.避免死锁:在资源分配过程中,用某种方法进入不安全状态,从而避免死锁发生。
		     (银行家算法)
	c.检测死锁:死锁检测分为两部分,当前分配矩阵()和请求矩阵
			1.系统现有总资源数 系统
	d.解除死锁:
		1.破坏互斥条件	

6)线程通讯:
系统CPU调用线程是通过随机分配时间片执行的,我们想要程序按自己的逻辑进行执行就需要进行‘线程通讯’。
线程通讯方式:
a.休眠唤醒方式
b.CountDownLatch
c.CyclicBarrier
d.Semaphore
wait和sleep的区别:
方法属性 wait是实例方法 / sleep是静态方法
同步 wait必须要在synchronized中使用,否则抛出异常 / sleep不需要
作用对象 wait方法定义在Object类中,作用于对象本身 / sleep方法定义在java.lang.Thread中,作用于当前线程
释放锁资源 wait会释放,而且会加入等待队列中 / sleep不会释放锁
唤醒方式 wait其它线程通过notify()或notifyAll()方法唤醒 / sleep不需要唤醒
wait和notify
wait和notify都是Object类的方法,都依赖synchronized
wait是将当前线程进入阻塞状态,notify就是唤醒等待当前线程锁的线程

6)线程池(Executers)
4)在项目中具体的实现:


MySql
1)如何优化?
a.sql优化:
避免*号的出现,查询什么列就给什么字段
SQL语句用大写
使用join代替子查询
b.使用索引:
2)关键字

3)数据类型

单词
synchronized(森果莱斯特)同步化;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值