取经之路就在眼前--面经备战

Android 面经收集大全

注意: 本文是通过阅读大量的博文以及其他论坛的精彩好文简化版随手录,如有侵权马上删除!

持续更新~~

简述

<<<<<<< HEAD
但不仅限于Android方面,希望通过此方式把自己的知识台阶一步一步搭起,最后通向offer的大门,知识汇聚,知识分享,开源的力量是无穷尽的,也祝大家早些时日提取自己心满意足的offer.

PS: 本收集属于对其他各大技术论坛大佬精美好文的简短总结

数据库

1.数据库的索引和实现原理

  1. 索引就是一个查找问题,索引是一个排序的数据结构,实现通常是B树及其变种
  2. 优点
    1. 唯一索引,保证每一行数据的唯一性
    2. 加快检索速度
    3. 加速表之间的连接
    4. 减少分组和排序时间
    5. 使用优化隐藏器提高性能
  3. 缺点
    1. 创建和维护耗时
    2. 占据更多的物理空间
    3. 增删改需要动态维护索引
  4. 在什么列上需要创建索引
    1. 经常搜索的列
    2. 主键列 [唯一性]
    3. 经常连接的列 [外键]
    4. 经常需要排序的列
    5. 经常使用在where子句中的列 [条件判断]
  5. 什么列不需要索引
    1. 查询少的列
    2. 只有很少数据值的列
    3. 定义数据类型很大的列 [比如text image bit]
    4. 修改性能大于检索性能的列
  6. 存储结构 [B树,B+树,红黑树]

2.手撕MySQL分组查询

  1. 按照某个字段进行分组 group by

  2. having 指定查询的条件,对分组的内容尽心过滤

  3. 单独使用group by

    单独使用查询出来的是分组的第一条记录的值
    select * form student group by gender;
    
  4. 结合聚合函数使用

    select count(*) ,gender from student group by gender;
    
  5. 结合having一起使用

    select sum(grade),gender from student group by gender having sum(grade)<300
    

    having和where的区别:

    都是根据条件进行过滤,

    having后面可以跟随聚合函数

Linux

1.Linux中断命令

  1. 中断
    1. CPU暂停当前的程序执行,转去处理突发事件,处理完后返回原程序继续执行
    2. 中断请求线: 中断唯一标识的数值
    3. 中断处理函数:内核执行对应的处理函数,中断的优先级最高
  2. 分类
    1. 中断<外部中断或异步中断>: 外设向处理器发出中断请求
    2. 异常<内部中断或同步异常>: 处理器执行指令错误
  3. 终端命令
    1. CTRL+C 强制中断程序执行
    2. CTRL+z任务中断,进程挂起
    3. CTRL+d特殊字符 EOF
    4. CTRL+\退出
    5. kill pid

扩展: 后台进程管理命令:

  1. jobs查看当前有多少在后台运行的命令
  2. fg将后台的命令调至前台执行
  3. bg将后台暂停的命令继续执行

操作系统

1.操作系统线程和进程的同步机制和通信机制

  1. 同步机制

    1. 临界区

      多线程的串行化访问公共资源,一个线程进入临界区之后其余线程必须在临界区外部等待,等到临界区被释放后,其他线程就可以抢占
      
    2. 互斥量

      互斥对象机制,只有拥有互斥对象的线程才有访问共享资源的权限,互斥对象只有一个,还能实现不同应用程序的线程之间的资源访问
      
    3. 信号量

      允许多个线程同一时刻访问同一资源,但需要限制最大线程数量,类似于操作系统的PV操作
      

      PV操作

      信号量S>0,表示可供使用的资源实体数量
      
      信号量S<0,表示等待使用资源的进程数
      
      相关操作:
      	申请资源
      					S-- [资源实体少一个]
      						if(--S >= 0){线程继续执行}
      						if(--S < 0){该进程阻塞,进入进程调度}
      	释放资源
      					s++ [资源实体多一个]
      						if(++S > 0){进程继续执行}
      						if(++S <= 0){唤醒一个等待进程或者转入进程调度}
      

      关键词解释: 进程调度

      多个进程抢用CPU使用权,操作系统究竟给哪一个进程CPU资源,由操作系统决定,这个决定的方法就是调度策略,理所当然的<进程调度>就是<操作系统使用调度策略给某个具体的进程给予CPU资源的使用权>
      
      调度算法:
      			抢占式
      							进程拥有最大的运行时间,并且这个时间是确定的,进程运行时间大于最大运行时间,该进程就会被挂起,选择调度算法挑选下一个进程运行
      			非抢占式
      							一个进程一直运行到阻塞或者自愿退出
      
    4. 事件

      使用通知操作,生产者和消费者的关系<观察者模式>
      
  2. 通讯机制

    1. 无名管道

      数据单向流动,是在具有亲缘关系之间的进程之间通讯,存在于内存
      
       2.  命名管道
      
      数据双向流动,无关进程之间可以数据交换
      
    2. 消息队列

      消息的链表,存放在内核中,独立于发送和接收线程
      
    3. 信号量

      计数器,实现进程间的互斥和同步,不是存储数据
      
    4. 共享内存

      共享一个给定的存储区,最快的方式,进程直接对内存数据进行读取
      

2.什么是缓存溢出

  1. 缓冲区
    1. 写入的缓冲区的数据超出缓冲区的大小,溢出的数据覆盖合法的数据 [溢出]
    2. 一段可读可写的内存区域
  2. 危害
    1. 程序崩溃,拒绝服务
    2. 执行恶意代码
    3. 缓冲区攻击 [驱使操作系统执行恶意的代码]
  3. 原因
    1. 没有检查用户的合法输入

3.操作系统分页分段管理

  1. 存储器层次结构

    1. 高速缓存

    2. 主存

    3. 磁盘

      物理内存
      			寄存器
      			内部缓存
      			外部缓存
      			主存
      			[内部和外部区别于CPU的内和外]
      
  2. 内存管理方式

    虚地址
    地址变换
    内存分配,回收,扩充,共享,保护
    
  3. 连续分配存储管理

    1. 单一连续
      1. 系统区
      2. 用户区
    2. 分区管理 [分时系统,程序并发执行,引入问题使内存碎片]
      1. 固定分区 [限制并发执行程序的数目]
      2. 动态分区 [没有内碎片,有外碎片,算法复杂]
        1. 分区分配算法
          1. 最先适配 :从头查找符合条件的第一个分区
          2. 下次适配:从上一次分配分区开始向下查找第一个符合的分区
          3. 最佳适配:查找大小相差最小的分区
          4. 最坏适配:查找最大的空闲分区
      3. 内存紧缩 [占用的分区移动到一端,其余空闲分区合成一个新的空闲分区]
      4. 覆盖技术 [较小的可用内存运行较大的程序 ,必要数据常驻内存,可选部分在外存,使用公共内存]
      5. 交换技术 [不执行的程序暂时送到外存,装入新的程序执行]
      6. 交换和覆盖的区别
        1. 交换不需要覆盖结构
        2. 交换在进程和作业之间
        3. 覆盖在同一作业或进程中
        4. 覆盖只能覆盖无关的程序段
  4. 页式存储

  5. 原理

    1. 逻辑地址划分为固定大小的
    2. 物理内存划分为相同大小的页框
    3. 将页转入页框
    4. CPU实现逻辑地址和物理地址的映射
  6. 优点

    1. 没有页外碎片,也内碎片比较小
    2. 程序不必连续存放
    3. 方便更改程序占用控件大小
  7. 缺点

    1. 一时刻装入整个程序
  8. 数据结构

    1. 进程表: 逻辑地址到物理地址的映射
    2. 物理页面表:描述物理内存的分配状况
    3. 请求表: 描述进程表的大小和位置
  9. 地址变换

  10. 使用逻辑页号最终找到物理地址

  11. 段式存储

    1. 原理
      1. 将程序地址空间划分为多个段
      2. 每个段分配一个连续的分区
      3. 各个段可以不连续在不同分区
      4. 动态分区管理物理内存
    2. 优点
    3. 分别编写和编译源程序的一个文件
    4. 没有内存碎片,外存碎片可以内存紧缩消除
    5. 内存共享
    6. 缺点
    7. 进程全部装入内存
    8. 数据结构
    9. 进程段表: 进程地址的各段
    10. 系统段表: 描述系统所有已分配的段
    11. 空闲段表:内存中所有空闲段
    12. 地址交换: 段表地址寄存器完成
  12. 区别

    1. 分页系统管理的需要
    2. 分段满足用户的需要
    3. 页使信息的物理单位
    4. 段是信息的逻辑单位
    5. 页大小固定,固定值由系统决定
    6. 段长度不固定,大小由用户程序决定
    7. 页式地址空间是一维的
    8. 段地址空间是二维的 <段名,段内地址>
    9. 段表比页表短

Java基础

1.Java四种引用

目的: 决定对象的生命周期利用JVM进行垃圾回收

  1. 强引用

    直接创建对象赋值,只要有引用变量就永远不被回收,宁可抛出异常;
    
    中断强引用和某个对象之间的关联,直接就是变量置null
    
  2. 软引用

    内存空间足够,垃圾回收器就不会回收他;
    
    否则对象会被回收,get获取对象就是null
    
    
  3. 弱引用

    只要垃圾回收器需要回收,弱引用必定会被回收
    
  4. 虚引用

    任何时候都有可能会被回收
    

2.Java synchronized的类锁和对象锁

  1. 对象锁

    1. 仅仅有关键字synchronized
    2. 也称实例锁
    3. 防止其他线程同时访问该实例的synchronized方法块
    4. 每个实例拥有自己的监视块
  2. 类锁

    1. static synchronized
    2. 也称全局锁,
    3. 控制类的所有实例的并发访问 [限制都线程该该类的所有实例同时访问jvm中对应的代码块]
    4. 所有实例公用一个监视块
  3. demo

    pulbic class Something(){  
        public synchronized void isSyncA(){}  
        public synchronized void isSyncB(){}  
        public static synchronized void cSyncA(){}  
        public static synchronized void cSyncB(){}  
    }
    
  4. 总结

    类锁和对象锁是两个不一样的锁,控制着不同的区域,它们是互不干扰的。同样,线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的。
    

3.JavaGC机制 [hotspot为例]

    1. 新生代
      1. eden region
        1. 分配所得空间较大
        2. 垃圾回收时,eden和survivor存活的对象被复制一遍到两一个survivor中
      2. from survivor region
      3. survivor空间不够依赖老生代
      4. to survivor region
    2. 老生代
      1. 保存大对象
      2. 这个区满了就报出outofmemory异常
    3. 永久代 [一般不会被回收]
      1. 方法去
  1. 判断一个类是否无用,满足下列条件

    1. 类的所有实例被回收,队中不存在该类的任何实例
    2. 该类的classloader被回收
    3. 该类的java.lang.class没有任何地方被引用
  2. 什么时候执行GC操作

  3. Eden区空间不足,执行较小的GC

  4. 老年代空间不足,执行重大的GC

  5. 老年代连续可用空间小于新生代对象总大小,指向Full GC

  6. 对象的年龄计数器判断对象应该在新生代还是老生代 <判断依据有两个: 最大年龄 ; 相同年龄对象大小总和占比重>

  7. 确定对象是否不可用

  8. 引用计数法

  **判断对象是否可用**

  ```java
  给对象添加引用计数器
  每引用一次计数+1
  引用失效一次-1
  当引用计数=0,对象不可用  <ps:不是对象死亡,因为相互循环引用难以解决>
    
  ```
  1. 可达性分析
  **判断对象是否存活**

  ```java
  当一个对象没有到达GCRoots的路径就是不可达
  ```
  1. 垃圾收集算法

    1. 标记清除 : 标记需要回收的对象,清除被标记对象占用的内存 <缺点: 内存碎片严重>
    2. 复制算法: 内存一分为二,一部分用于直接存储对象,另一部分备用,解决内存碎片问题 <缺点:实际可用内存缩短一半>
    3. 标记整理:对象移动到内存的一端,清除边缘对象,标记的对象时需要移动的
    4. 分代收集:
      1. 根据对象的生命周期收集垃圾对象
      2. eden和另一个surivivor的存活对象复制到两一个surivivor中,再清除eden和surivivor区域

4.哪些对象可以作为GC ROOTS对象

GC会收集那些不是GC roots且没有被GC roots引用的对象

  1. JVM中的栈引用对象
  2. 方法区中的类静态属性引用对象
  3. 方法区中常量引用对象(final常量)
  4. 本地方法栈jni引用对象
作者:Accelerator
链接:https://www.zhihu.com/question/50381439/answer/120846441
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1.System Class   
系统类

2.JNI Local
Java 本地接口

3.JNI Global
全局变量

4.Thread Block
线程块

5.Busy Monitor
频繁的监控

6.Java Local

7.Native Stack
本地堆栈

7.Finalizable
final常量

8.Unfinalized

9.Unreachable

10.Java Stack Frame
栈帧
11.Unknown

5.volatile关键字和synchronize关键字

  1. volatile
    1. 使变量具有可见性 [可见性:我理解是有点同步的意思,就是一个变量被修改,最新的值立马更新到主存供其他线程使用最新之,以至于不会继续使用旧的值]
    2. 直接读写内存
    3. 禁止指令重排 [指令重排: 处理器优化代码,可能改变代码执行顺序,但在单线程下不会改变执行结果, 多线程上则不能]
  2. synchronize
  3. 既保证可见性 [同一时刻只有一个线程获得锁然后执行代码,释放锁之前将最新之刷新到主存]
  4. 也保证原子性 [要么执行,要么不执行]

6.Java内存模型的可见性,重排序,原子性

  1. 可见性:使用的是直接缓存到CPU中

  2. 重排序:改变指令执行顺序,优化代码,但不会改变执行结果

  3. 原子性 :操作单一不可见

计算机网络

1.OSI网络模型 [七层]

  1. 物理层

    提供物理连接
    
    关心比特流传输
    
    关心机械,电气,功能和规程特性
    
    IEEE 802.2的电器协议
    
  2. 数据链路层

    PPP SLIP ARPANE协议,隧道通讯协议,思科的CDP协议,地址解析协议
    
    物理寻址
    
    将原比特流转换成逻辑传输线路
    
    
    
  3. 网络层

    ICMP  ARP RARP IP,安全协议AH,路由协议OSPF最短路径优先
    
    外部网关EGP 内部网关IGRP IP/IPV6
    
    控制子网运行
    
    分组传输
    
    路由选择
    
    逻辑编址
    
  4. 传输层

    TCP  UDP
    
    分割数据
    
    保证数据有效到达端
    
  5. 会话层

    SMTP  DNS
    
    SSL TLS安全协议
    
    不同机器上用户之间简历管理会话
    
    
  6. 表示层

    SNMP TELNET
    
    信息的语法语义和之间的关联 [加密解密,转换翻译,压缩解压]
    
  7. 应用层

    HTTP TFTP FTP SMTP应用程序协议
    
  8. img

2.TCP/IP模型 [四层]

  1. 应用层: 传输协议

  2. 传输层: TCP UDP

  3. 网络层: IP ICMP

    IP层传输
    				点到点传输
    				传输IP分组
    
    TCP层传输
    				端到端的传输
    				传输TCP段
    
  4. 物理链路层: 根据需要选择不同的物理链路

3.网络设别工作在那一层

  1. 网卡

    物理层

  2. 中继器

    物理层 [复原网络中的信号,从新发送到其他网段]

  3. 集线器

    物理层 [连接各个物理设备]

  4. 网桥

    数据链路层的MAC子层上<介质访问控制层> [网段中相同协议传输数据包]

  5. 交换机

    数据链路层 [和网桥类似的功能]

  6. 路由器

    网络层 [分组转发和路由]

4.``HTTP,HTTPS,HTTP1,HTTP2`

  1. HTTP
    1. 明文方式发送内容
    2. 不提供加密
    3. 80端口
    4. 无状态连接
  2. HTTPS
  3. 在HTTP基础上加入了SSL协议<通讯加密,依靠证书验证服务器的身份>
  4. 用途
    1. 保证数据传输的安全
    2. 确认网站的真实性
  5. 需要申请证书
  6. 443端口
  7. 短连接
  8. 缺点
    1. 握手阶段耗时
    2. 缓存效率相对HTTP底
    3. ssl证书需要钱
    4. ssl证书需要绑定ip,不能在同一个ip上绑定多个域名
    5. 加密范围有限
  9. HTTP1.0
  10. 无状态 <不记录客户端过去的请求>
  11. 无连接 <处理完任务马上断开连接>
  12. HTTP1.1
  13. 持久连接 <默认keep-alive,避免重新连接和释放>
  14. 管道化
  15. 增加缓存
  16. host字段
  17. 断点传输
  18. <不允许同时存在两个响应>
  19. HTTP2.0
  20. 二进制分帧
    1. 流:双向字节流
    2. 消息:逻辑对应的数据帧集合
    3. 帧:最小单位,标记当前帧所属的流
  21. 多路复用
    1. TCP连接 <承载任意数量的双向数据流>
    2. 数据流以消息的形式发送 <可乱序发送,后根据帧头部标识的所属流进行重装>
    3. 并行传输
  22. 头部压缩
    1. HTTP1.x头部数据以纯文本形式传输
    2. HTTP2.0使用encoder,双方各自缓存一份header Fiedls <注意使缓存,重复利用,避免重传>
  23. 服务器推送
    1. 无需客户端明确请求,主动向客户端推送资源
  24. HTTP2和HTTPS的关系

5.三次握手及其相关

img

img

  1. 为何连接
    1. 客户端和服务器的内存里保存对方的一份信息
    2. 双方需要交换参数 <参数放在TCP头部>
    3. 可靠,面向连接,字节流,传输层服务
    4. 三次握手连接 <两次初始化序列号,两次确认> ,四次握手关闭
  2. 序列号
  3. 作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段
  4. 标识符
  5. ACK 确认
  6. RST 重连
  7. SYN 初始化序列号
  8. FIN 发送方结束向对方发送数据

6.https加密过程

  1. 对称加密

    1. 加密和解密使用同一个密钥
  2. 非对称加密

  3. 私钥: 不让其他人知道 [解密]

  4. 公钥:任何人可以知道 [加密]

  5. 加密过程

  6. 非对称加密

  7. 结合 对称加密

  8. 结合 数字证书

在这里插入图片描述
4.

设计模式

1.手写Java双重检验的单列模式

  1. 侧重考点就是在如何实现双重验证

    双重验证的逐渐演化过程

    1.单线程适用

    缺点:只能适用与单线程

    class	A{
      
      private A instance;
      
      private A(){}
      
      public static A getInstance(){
        if(instance == null){
          instance = new A();
        }
        return instance;
      }
    }
    

    2.多线程适用 [适用synchronized方法]

    缺点:每次调用方法都需要同步的代价,实际上是只有if语句需要同步

    class	A{
      
      private A instance;
      
      private A(){}
      
      public static synchronized A getInstance(){
        if(instance == null){
          instance = new A();
        }
        return instance;
      }
    }
    

    3.降低同步调用代价 [适用synchronized代码块]

    缺点: 当两个线程进入if判断之后,有一个线程进入了同步代码块,还有另外一个线程在同步块外,if语句内等待,所以当同步块线程创建完对象之后退出同步块,另一个线程没有再次判断instance是否为null

    class	A{
      
      private A instance;
      
      private A(){}
      
      public static A getInstance(){
        if(instance == null){
          synchronized(A.class){
          	instance = new A();
          }
        }
        return instance;
      }
    }
    

    4.双重检查 [在创建对象之前再加一个if判断null]

    缺点:理想很美好,现实很骨感,不能保证在单处理器和多处理器上顺序执行,因为内存模型写入是无序的

    class	A{
      
      private A instance;
      
      private A(){}
      
      public static A getInstance(){
        if(instance == null){
          synchronized(A.class){
            if(instance == null){
          		instance = new A();
            }
          }
        }
        return instance;
      }
    }
    

    5.解决无序写入问题 [双重同步代码块]

    class	A{
      
      private A instance;
      
      private A(){}
      
      public static A getInstance(){
        if(instance == null){
          synchronized(A.class){
            A tmp = instance;
            if(tmp == null){
          		synchronized(A.class){
                tmp = new A();
              }
              instance = tmp;
            }
          }
        }
        return instance;
      }
    }
    

    6.优化无序写入

    class	A{
      
      private A instance;
      
      private A(){}
      
      public static A getInstance(){
        if(instance == null){
          synchronized(A.class){
            A tmp = instance;
            if(tmp == null){
          		synchronized(A.class){
                instance = new A();
              }
            }
          }
        }
        return instance;
      }
    }
    

    7.考虑到内存模型和写入顺序,最终选择方案

    1. 使用static关键字的单例模式

      class A{
        private static A instance = new A();
        
        private A(){}
        
        public static A getinstance(){
          return instance;
        }
      }
      
    2. 使用同步方法

      public static synchronized A getinstance(){
        if(instance == null){
          instance = new A();
        }
        return instance;
      }
      

Android框架使用

1.Glide的使用 [加载图片]

  1. 特点

    1. 可以加载gif动图
    2. 播放本地MP4
    3. 加载默认图片 .fallback(id)
    4. 重置大小.resize(int,int)
    5. 裁剪图片.fitcenter()
    6. 缩放图片thumbnail(0.1f)
    7. 圆角图片bitmaptransform(new )
    8. 缓存 [自定义缓存] diskCacheStrategy
    9. 修改缓存大小,位置,图片质量
    10. 请求优先级,加载图片的优先级.priority(int)
  2. 加载网络图片

    Glide.with(context).load(url).into(imageview)

  3. 加载文件

    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"Test.jpg");
    Glide.with(context).load(file).into(imageViewFile);
    
  4. 根据id加载

    int resourceId = R.mipmap.ic_launcher;
    Glide.with(context).load(resourceId).into(imageViewResource);
    
  5. uri加载

    Glide.with(context).load(uri).into(imageViewUri);
    

2. EventBus的使用

  1. 发布订阅<观察者模式>的事件总线
  2. 作用
    1. 简化组件之间通讯 [两个fragment之间的]
    2. 组件和后台线程间的通讯 [网络请求]
  3. 使用
    1. event事件 [任意类型的对象]
    2. subscribe订阅者 [指定线程模型]
    3. publisher发布者 [任意线程位置发送事件post方法]
  4. 线程模型
    1. posting事件发布和事件接受在同一个线程 [默认] <避免执行耗时操作,因会阻塞事件传递>
    2. main在ui线程中处理事件,不能耗时操作,ui线程本来就不能耗时操作
    3. background在子线程中处理事件 [一般是网络请求等耗时操作] <子线程发布事件就在子线程中处理事件,ui线程发布事件就创建新的子线程处理事件>
    4. async无论在哪个线程发布事件,都将新建子线程处理事件

3.Rxjava通讯机制

  1. 扩展的观察者模式
    1. observable被观察者
    2. observer观察者
    3. subscribe订阅
  2. 事件回调方法
    1. onnext<类似于点击>
    2. oncompleted事件队列完成
    3. onerror错误
  3. 使用
    1. 创建观察者
      1. [重写三个回调方法] observer
      2. <这个的一个抽象类subscriber> 用法一致
      3. [onstart方法在所在线程处理事件,不能更新ui,更新ui需要用doonsubscribe方法中]
    2. 创建被观察者observable
      1. 从写call方法,内部调用subscriber.onnext() oncompleted()等方法,一次执行事件
      2. 还有just() from()
    3. subscribe订阅事件
      1. 把观察者和被观察者关联起来observable.subscribe(observer);
  4. Action0() Action1()将对象打包起来内部打包了不同的回调方法
  5. scheduler线程控制器 [指定一段代码运行在什么样的线程下]
    1. 默认下: 在哪一个线程调用subscriber()就在该线程产生事件,就在该线程消费事件
    2. immediate()默认情况,在当前线程运行
    3. newThread()总是创建新的线程执行代码
    4. ioio操作[网络,数据库,文件读取],内部实现有一个无数量上限的线程池
    5. computationCPU计算密集型
    6. mainthreadAndroid主线程
  6. 变换
    1. 加工整个序列,转换成不同的事件序列
    2. Func1具有返回值的包装
    3. map flatmap

Android基础

1.你常用的组件有哪些

常用组件 用途
text view 文本显示
edit text 注册框,搜索框
button 登录按钮
float action button <悬浮按钮> flutter中印象深刻的一个按钮,登录
recycle view list view少用了,动态列表
switch 白天和黑夜模式的开关
scroll view 上下滑动
fragment 结合view page使用布局切换
image view 显示各种图片
check box 订单的选择
web view 新闻网页的显示
progress bar 加载进度
spinner 下拉消息选项
rating bar 订单评价
search view 搜索框
constraint layout 最喜欢的一个布局
linear layout 常常使用等比例均分的属性
grid layout 搜索预选择的格子
horizontal scroll view 横向布局 ,切换页面
tool bar 首页的顶部文字显示
bottom navigation view 主界面的底部导航栏
view 一些分割线

2.Android四大组件

  1. activity

    1. 单独的窗口
    2. 通过intent通讯
    3. 必须在AndroidManifest.xml配置文件中声明
  2. service

    1. 用于后台完成用户操作
    2. 启动,调用startService()
      1. 与启动服务的组件无关
      2. 可以无限期运行
      3. 销毁服务需要调用stopSelf() 或者 stopService()
    3. 绑定,调用bindService()
      1. 与绑定服务的组件相关联
    4. 配之文件需要声明service
  3. content provider

    1. 不同程序之间的数据共享
    2. 使用uri标实数据集
  4. broadcast receiver

    1. 对感兴趣的外部事件进行接受并作出响应
    2. 可以启用一个activity或者service来响应接收到的信息
    3. 也可以使用notificationmanager通知用户
    4. 动态注册
      1. 生命周期随注册的activity共存亡
    5. 静态注册
      1. 生命周期独立于程序

3. 自定义view

  1. 自绘控件

    1. 继承view或者view group

    2. 自定义view属性

      1. 在res/values创建xml定义属性
    3. 在构造方法中获取 自定义的属性

      		TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);
      
      循环获取属性并赋值给成员变量
      
    4. 重写onDraw方法

    5. [可选]重写onMesure方法

  2. 控件组合

4.约束布局

  1. 特点
    1. 百分比适配屏幕和控件
    2. 解决布局嵌套过多问题
    3. 添加动画
    4. 支持代码布局控件(不需要写xml)
  2. 和相对布局的区别

算法题

1.归并排序

2. 汉诺塔

递归实现

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
	    int n = scanner.nextInt();
	    han(n,1,2,3);
	}
	
	public static void han(int n,int a,int b,int c){
	    if (n == 1){
	       System.out.printf("Move %d from %d to %d\n",n,a,c);
	    }
	    else{
	        han(n-1,a,c,b);
	        System.out.printf("Move %d from %d to %d\n",n,a,c);
	        han(n-1,b,a,c);
	    }
	}
}

非递归实现

一个美国学者总结得到:所有的汉诺塔移动可以总结为重复的两步,我们假设现在最小的圆盘在a柱子上,柱子为a,b,c

第一步:将最小圆盘移动到下一个柱子上,也就是b

第二步:对a柱子和c柱子进行顶上最小的元素进行判断,把小一点的那个圆盘移动到大一点的那个圆盘(有空则摞在空柱子上)。

重复上述两步就可以得到答案。

注意:这样得到的最后的答案不一定是摞在c上,如果N是偶数将摞在b上,所以如果N是偶数我们就令第二个柱子为c,第三个柱子为b,这样就一定最后是摞在c上的

3.数组反转

4.给一对无序数组,给一个target整数,找出数组中两个数字相加为target,并输出下标(不能用哈希)

5.数组反转,给一个target整数,每target长度反转一次

6.最长连续子序列 O(n)

7.数组反转,给一个target整数,每target长度反转一次

发布了92 篇原创文章 · 获赞 15 · 访问量 8612

猜你喜欢

转载自blog.csdn.net/printf123scanf/article/details/104283240