面试题

SparseArray三大特点

双数组删除O(1)二分查找

为什么省内存?

1.HashMap 为了避免过多的哈希冲突,引入了负载因子,打个比方,负载因子使用默认值 0.75,这意味着容量达到了 75%,就会开始扩容,也就是必然有 25% 的空间是不存储数据而被浪费的。而 SparseArray 可以把数组利用到最后一个空间。  2.HashMap 有自动拆装箱

复杂度为什么这么低?

SparseArray 做了两个优化:

1.引入 DELETE 标记

既然底层使用了数组,数组的缺点是什么?—— 删除数据时需要搬移元素。SparseArray 对数组的删除不做数据搬移,引入 DELETE 标记,以此达到在删除时做到 O(1) 的时间复杂度。

在调用 size()和put()需要扩容时,才去清理 DELETE 标识。

2.优化追加元素

SparseArray 提供了一个 append() 方法,来优化追加的情况。该方法会判断追加的 key 值,是否大于数组中最大的值,如果是则直接追加在数组末尾,否则执行 put() 方法插入 mKey 数组。


HashMap与HashTable的区别?

大家都提到了 HashTable 不支持 null 的键和值,为什么 HashTable 不支持呢?是出于什么原因和考虑呢?

你有没有发现,只要是用于多线程场景的 Map,HashTable和 ConcurrentHashMap,都不支持 null 键和 null 值,这是为什么呢?

回答这个问题前,我们先来思考下:

假设你在使用 HashMap 时,调用 map.get(key) 方法得到的值是 null,是因为这个 key 在 map 里面value = null?还是这个 key 在 map 里面根本就不存在?

你肯定说,这好办,我调用一下map.contains(key) 不就知道了?

那如果是ConcurrentHashMap呢?在多线程的场景下。假设ConcurrentHashMap允许存放值为null的 value,此时线程 1 get(key)方法(这个key本来在Map里不存在),返回为 null,线程 2 执行了put(key,null),线程 1 调用contains(key)就会返回 true,这就会出现误导了。

所以总结一下,用于多线程场景的 Map 不允许 null,是为了避免二义性

请回答一下Android进程间的通信方式?

从Linux系统上来说,有Socket、消息队列、管道、共享内存、Binder。理论上,这些都可以实现跨进程。
在Android的本地进程间通信,见识过两种:
1,基于binder,例如AIDL、广播、Intent等,这些内部实现都是通过Binder。Binder基于CS通信模式,通过mmap技术,单次拷贝实现的跨进程通信。
2,基于socket,例如:通知Zygote进程进行进程的孵化,就是通过socket通知过去的。

面试一问一答:http、https?

详细解释     详细解释2
1.https协议需要到ca申请ssl证书
2.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议
3.http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4.http的连接很简单,是无状态的;
5.HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。


TCP/IP协议分为哪几层?TCP和HTTP分别属于哪一层?

* 四层:应用层, 传输层, 网络层 ,数据链路层。
* http是应用层, tcp 是传输层 ,ip是网络层,http 每次请求 需要 三次握手四次挥手
* tcp是基于连接的 所以相对可靠, udp是直接发送 速度快但是不可靠
* tcp可靠基于三次握手和四次挥手,和ack(回执机制) 如果客户端给服务端发送数据后没收到回执,会在一定条件下重复发送, 并且他们在连接     过 程中中断 又会重新三次握手
* http1.1 引入了 keepalive机制 长连接 不必每次请求 都是三次握手四次挥手, 而是在超时时间内利用同一个 连接
* http2.0 把基于文本传输改为基于二进制传输 多路复用
* https 是在 http的基础上加上ssl 安全套接字 加入了认证加密 增加了一定的安全性,但也不是完全安全.在app中需要将https证书改为严格模     式,并且要提前将证书放在客户端,如果放在服务端下证书有可能被人抓走. https 如果不是严格模式 也是可以进行抓包的

图片压缩优化,Glide

图片的像素点的压缩。

 1.实现在java堆里面操作(利用池)-----所以内存缓存是2级!(8.0开始bitmap管理放在了native层,在profile里面可看到native一直增加)
 2. 使用RGB565(一个像素点只要两个字节),易变(inMutable)实现复用内存块 android19,以后比较方便。
 3.缓存:内存缓存(lru),磁盘缓存(dislru),再到网络找。

------------------>Android 中的图片优化方案?
1.在不同的环境下采用不同的规则(不同尺寸的缩略图)
2.可以考虑将图片有损转换为webp
3.可以把图片转为rgb565
4.加在大图可以考虑局部加载 防止oom
6.及时做好图片缓存,避免每次都去网络图片取
7.做好lru缓存策略,避免一直缓存的用不到的图片
8.可把一些切图用 xml图形表示 或者.9png
10.在gradle中配置 去除无用资源 

热修复

将修复好的class2.dex下载到本机,替换有bug的dex文件。

Java -->Class -->Dex  类加载的原理
BaseDexClassLoader--》DexClassLoader,  DexPathList(dexElements)

DeClassLoader  de=new DeClassLoader(..); //这个加下载的dex
PathClassLoader p=context.getClassLoader();//系统的...
//进行合并...

谈谈List,Set,Map的区别?

List中的元素,有序、可重复、可为空;
Set中的元素,无序、不重复、只有一个空元素;
Map中的元素,无序、键不重,值可重、可一个空键、多可空值;

ThreadLocal是如何实现一个线程一个Looper的?

主线程的Looper ,在ActivityThread类的main方法中被第一次调用,是在应用被打开的时候执行。
Looper.loop()方法中去获取的Looper是从sThreadLocal中获取的,
threadLocal的get方法实际使用的就是threadLocalMap的get方法 ,
threadLocal是以thread做为key,New一个Loop的。相当于HashMap.


9.你了解 HandlerThread 吗?

答:HandlerThread是Thread的一个子类,只是内部创建了一个Handler,这个Handler是子线程的handler,其中子线程的looper的创建和管理也提供了方法方便使用。

10.你对 Message.obtain() 了解吗, 或者你知道 怎么维护消息池吗?

答:Message.obtain其实是从缓冲的消息池中取出第一个消息来使用,避免消息对象的频繁创建和销毁;消息池其实是使用Message链表结构实现,在消息在loop中被handler分发消费之后会执行回收的操作,将该消息内部数据清空并添加到消息链表最前边。

你可能感兴趣的:(面试题)