《第一章》
数据结构的特性:
数据结构 | 优点 | 缺点 |
数组 | 插入快,如果知道下标,可以非常快速的存取 | 查找慢,删除慢,大小固定 |
有序数组 | 比无序的数组查找快 | 删除和插入慢,大小固定 |
栈 | 提供后进先出的方式存取 | 存取其他项很慢 |
堆 | 插入,删除快,对最大数据项的存取很快 | 对其他数据项存取慢 |
队列 | 提供先进先出的方式存取 | 存取其他项很慢 |
链表 | 插入快,删除快 | 查找慢 |
二叉树 | 查找,插入,删除都快(如果树保持平衡) | 删除算法复杂 |
红黑树 | 查找,插入,删除都快(树总是保持平衡) | 算法复杂 |
2-3-4树 | 查找,插入,删除都快(树总是保持平衡,类似的树对磁盘存储有用) | 算法复杂 |
哈希表 | 如果关键字已知则存取极快,插入快 | 删除慢,如果不知道关键字则存取很慢,对存储空间使用不充分 |
图 | 对现实世界进行建模 | 有些算法慢且复杂 |
数据结构 | 特点 |
arrayList: | 1.arrayList 基于数组方式实现,无容量的限制 2.arrayList 在执行插入元素时可能要扩容,在删除元素时并不会减小数组的容量(可以手动调用trimToSize减小容量)。在查找元素时要遍历数组,对于非null 的元素采取equals 的方式寻找。 3.arrayList是非线程安全的。 |
linkedList: | linkedList: 基于双向链表机制的实现,双向链表机制就是集合中的每个元素都知道其前一个元素和其后一个元素的位置。在linkedList 中,以一个内部的Entry 类为代表集合中的元素,元素的值赋值给element 属性,Entry 中的next属性指向元素的后一个元素,Entry 的previous 属性指向元素的前一个元素,基于这样的机制可以快速实现集合中元素的移动。 总结: 2.linkedList 在插入元素时,必须建一个新的entry 对象,并切换相应元素的前后元素的引用;在查找元素时,需要比那里链表;在删除元素时,要遍历链表,找到要删除的元素,然后从链表上将次元素删除即可; 3.linkedList 是非线程安全的。 |
vector: | vector和 arrayList 一样,也是基于object 数组的方式来实现的。因为在add,remove 都有synchronized ,所以保证了安全性。 总结:vector 是基于 synchronized 实现的线程安全的arrayList ,但在插入元素时容量扩充的机制和arrayList 稍有不同,并可以通过传入capacityIncrement 来控制容量的扩充。 |
stack: | stack 继承于vector ,在其基础上实现了stack 所要求的后进先出LIFO的弹出及压入操作,其提供了push,pop,peek三个主要的方法。 push:push 操作通过调用vector的addElement来完成。 总结:stack 基于vector 实现,支持后进先出LIFO。 |
hashSet: | hashSet 是set接口的实现,set和list最明显的区别在于set不允许元素重复,而list允许重复。set 为了做到不允许元素重复,采用的是基于hashMap实现。 总结: |
treeSet: | treeSet 和hashSet 的主要不同在于treeSet 对于排序的支持,treeSet基于treeMap 实现。提供了一些排序方面的支持,例如传入comparator实现,descendingSet。 总结: |
hashMap: | hashMap:将loadFactor 设为默认的0.75,threshold 设置为12,并创建一个大小为16的entry 对象数组。 hash 冲突:不同的key找到相同的存储位置,就是hash冲突。 hash冲突解决方案:在找到要存储的目标数组的位置后,获取该数组对应的entry对象,通过调用entry 对象的next来进行遍历,寻找hash值和计算出来的hash值相等,且key 相等或equals的entry对象,如果寻找到,则替换此entry对象的值,完成put 操作,并返回旧的值;如果未找到,就往对应的数组位置增加新的entry对象,增加时采取的方法和key 为null 的情况基本相同,只是它是替换指定位置的entry对象,hashMap解决hash 冲突采用的是链表的方式,而不是开放定址的方法。 总结: 2.hashMap 基于key hash 寻找entry 对象存放到数组的位置,对于hash冲突采用链表的方式来解决。 3.hashMap 在插入元素时可能会要扩大数组的容量,在扩大容量时需要重新计算hash,并复制对象到新的数组中。 4.hashMap 是非线程安全的。 |
treeMap: | treeMap 是一个支持排序的map 实现。当调用put时,先判断root 属性是否为null,如果为空,则创建一个新的entry对象,并赋值给root 属性。如果不为空,则首先判断是否传入了指定的comparator 实现,如果已经传入,则基于红黑树的方式遍历,基于comparator来比较key应该放到树的坐标还是右边,如果找到相同的key,就直接替换其value。 总结: 1.treeMap 基于红黑树实现,无容量限制。 2.treeMap 是非线程安全的。 |
concurrentHashMap : | concurrentHashMap 是线程安全的hashMap的实现。concurrentHashMap 采用的方法即为遍历每个分段中的hashEntry 对象数组,完成集合中所有对象的读取。concurrentHashMap默认情况下采用将数据分为16个段进行存储,并且16个段分别持有各自的锁,锁仅仅用于put 和remove 等改变集合对象的操作,基于voliate 及hashEntry 链表的不变性实现读取的不加锁。这样使得concurrentHashMap 能够保持极好的并发支持。 |
各种协议
dubbo 协议 | 采用单一长连接和NIO异步通信,适用于“小数据量大并发”的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。 |
hessian协议 | 传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传输文件。 |
rmi协议 | 采用JDK标准的Java。rmi实现,常规远程方法调用,与原声RMI服务互相操作。 |
Http协议 | 可用浏览器查看,通过表单或URL传入参数。 |
webservice协议 | soap文本序列化,多用于系统集成,跨语言调用。 |
thrif协议 | 对thrift(Facebook 的rpc框架)的原生协议的扩展。 |
软件工程的整个生命周期:分析,设计,验证,编码,测试,生产,维护。
继承是指由基类扩展或派生形成的一个新类,这个扩展类拥有基类的所有属性,并加上了几种其他属性。
多态指的是以相同的办法处理来自不同类的对象。为了使多态能够正常运行,这些不同的类必须同一个基类中派生出来。
java 和 c++ 最大不同就在于java没有指针。
BankAccount bc1; bc1 存储了一个对象的地址,而不是保存对象的数据。bc1 是对象的一个引用,它并不是对象本身。如果对象没有被复制,它就不会成为引用。在赋值为某个对象之前,它保存一个被称为null 的特殊对象的引用。
垃圾回收:用new 向系统申请空间后,不需要对释放空间担心。java每隔一段时间就会查看每一块由new 开辟的内存,看指向它的有效引用是否依旧存在。如果这个引用不存在,系统就会自动的将这块空间归入空闲内存区,这个过程被称为垃圾回收。
char[字符]型是无符号的,采用两个字节的空间表示Unicode 字符集,这个字符集可以处理国际通用的字符。
int 型的变量永远是32位
数组可以分为:线性查找和二分查找
注意:二分查找比线性查找要快。
有序数组:有序数组查找的速度比无序数组快,但是在插入的操作中由于所有靠后的数据都需要移动以腾开空间,所以速度较慢。有序数据和无序数据的删除都很慢,因为数据项必须向前移动来填补已删除的数据项。
有序数据在查找频繁的时候十分有效,但是插入和删除也较为频繁时,则无法高效工作。
算法 | 大O表示运行的时间 |
线性查找 | O(N) |
二分查找 | O(logN) |
无序数组的插入 | O(1) |
有序数组的插入 | O(N) |
无序数组的删除 | O(N) |
有序数组的删除 | O(N) |
总结:
1.java中的数组是对象,由new 操作符创建
2.无序数组可以快速的插入,但是查找和删除慢
3.将数组封装到类中可以保护数组不被随意更改
4.类的接口由类用户可访问的方法组成
类的接口被设计成类用户的操作更加简单
5.有序数组可以使用二分查找
6.线性查找需要的时间和数组中数据项的个数成正比
7.二分查找需要的时间与数组中数据项的对数成正比
8.大O表示法比较算法的速度提供了一种方便的方法
9.O(1)级时间的算法是最好的,O(logN)次之,O(N)为一般,O(N²)最差。
《第三章》
排序包括:线性排序,二分排序,冒泡排序,选择排序,插入排序,希尔排序,快速排序。
冒泡排序: | 运行非常慢,但是最简单。与旁边的比较,若小靠左,若大靠右。 |
选择排序: | 选择排序是对冒泡排序的改进,比冒泡排序快,比插入排序慢。 |
插入排序: | 比冒泡排序快一倍,比选择排序复杂点。 |
《第四章》
1.栈,队列和优先级队列是经常用于简化某些程序操作的数据结构
2.在这些数据结构中,只有一个数据项可以被访问
3.栈允许访问最后一个插入的数据项
4.栈中重要的操作是在栈顶插入一个数据项,以及从栈顶移除一个数据项。
5.队列只允许访问第一个插入的数据项
6.队列的重要操作是在队尾插入数据项和在队头移除数据项
7.队列可以实现为循环队列,它基于数据,数组下标可以从数据末端回绕到数组的开始位置
8.优先级队列允许访问最小/最大的数据项
1.链表包含一个linkedList和许多Link对象
2.linkedList 对象包含一个引用,这个引用通常叫做first,它指向链表的第一个链结点。
3.每个link 对象包含数据和一个引用,通常叫做next,它指向链表的下一个链结点。
4.next字段为null值意味着链表的结尾。
5.在表头删除链结点要把first指向first.next。
6.为了遍历链表,从first开始,然后从一个链结点到下一个链结点,方法是用每个链结点的next字段找到下一个链结点。
7.通过遍历链表可以找到拥有特定值的链结点,一旦找到,可以显示,删除或用其他方式操纵该结点
8.新链结点可以插在某个特定值的链结点的前面或者后面,首先要遍历找到这个链结点。
9.双端链表在链表中维护一个指向最后一个链结点的引用,它通常和first一样,叫做last。
10.双端链表允许在表尾插入数据项
11.抽象数据类型是一种数据存储类,不涉及它的实现
12.栈和队列时ADT,他们既可以用数组实现,又可以用链表实现
13.有序链表中,链结点按照关键值升降序排序
14.双向链表允许反向遍历,并可以从表尾删除
15.迭代器是一个引用,它被封装在类对象中,这个引用指向相关联的链表中的链结点。
16.迭代器方法允许使用者沿链表移动迭代器,并访问当前指示的链结点。