本文是实习过程中Java 常问问题的总结。
Java
SpringMVC调用过程:(1) Http请求:客户端请求提交到DispatcherServlet。 (2) 寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller。 (3) 调用处理器:DispatcherServlet将请求提交到Controller。 (4)(5)调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndView。 (6)(7)处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。 (8) Http响应:视图负责将结果显示到客户端。
HashMap:基于哈希表的Map接口的非同步实现,允许使用null值和null键。速度很快,存储键值对,此类不保证映射的顺序,底层就是一个数组结构 ,数组中的每一项又是一个链表。HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象。基于hashing的原理,当需要存储一个 Entry 对象时会用到put(key, value),会先对key调用hash算法来决定其在数组中的存储位置,若两个entry的hash值相同,则其在数组的下标存储位置相同,在根据equals方法决定其在该数组位置上的链表中的存储位置,equals若相同,则用新的entry的value来更新,不同时插入LinkedList链表头;当需要取出一个Entry时会用到get(key),也会根据hash算法找到该key在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。当map填充75%的数组时,会进行rehash,将会创建原来HashMap两倍的数组.不宜在多线程使用,String\Integer不变.“拉链法”,默认容量16,每次×2, 计算索引的hash&(length-1)
HashTable: 散列表, 键值对(key-value)映射, 继承于Dictionary,实现了Map、Cloneable\Serializable接口, 函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null,映射不是有序的。默认容量为11,每次×2+1,计算索引(hash&0x7FFFFFFF)%len(保证hash为正)。
ConcurrentHashMap锁分段:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一段数据的时候,其他段的数据也能被其他线程访问。
IOC(控制反转):本质就是构建对象的技术,指对组件对象控制权的转移,从程序代码本身转移到了外部容器,通过容器来实现对象组件的装配和管理。Spring提供容器,我们在xml文件里定义各个对象的依赖关系,由容器完成对象的构建(反射),当我们Java代码里需要使用某个实例的时候就可以从容器里获取,那么对象的构建操作就被Spring容器接管. DI(依赖注入):在运行期间由容器将依赖关系注入到组件中,就是在运行期,由spring根据配置文件将其他对象的引用通过组件提供的setter方法进行设定。
AOP(面向切面编程):OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,AOP技术恰恰相反,它利用一种称为”横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面。原理是动态代理,【静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理:在程序运行时,运用反射机制动态创建而成】
设计模式:a.创建型:1、简单工厂:创建一个工厂,通过增加分支语句的方式来增加创建新的对象。2、工厂方法模式:通过定义一个创建对象的接口来对类进行实例化。不用再对客户端代码进行修改,增加新的实例化。3、抽象工厂模式:通过定义一系列创建对象的接口来对创建对象。当类和操作类不断增多,单纯的创建一个接口实例化对象(工厂方法模式)已经不足以解决问题。这时便需要在此基础之上,创建一系列接口用于实例化,便可不用指定具体实例化那哪一个类。4、单例模式:保证让一个类仅拥有一个实例。便可保证只有这一个实例可以被创建,被访问。5、建造者模式:保证在创建对象时,将产品的内部组成与生成过程隔离开来,使用同样的创建过程便可以创建出胖瘦不同的对象。6、原型模式:利用原型实例来“克隆”创建新的对象。B.结构型:1、装饰模式:系统需要新的功能时,避免在主类中添加新字段,把某些特殊的功能(装饰物)选择性的单独放到一个类中。这就属于类与类之间的组合结构.2、适配器模式:姚明在NBA需要翻译,老外来中国也需要翻译。将一个类的接口转换成另一个希望的接口.【代理模式和装饰模式的区别?:代理是在内部生成一个代理对象,构造函数参数为空。装饰的构造函数参数有一个对象,就是对这个对象进行装饰。】 C.行为型:1、观察者模式:当几个对象之间,一个改变需要同时改变多个对象时,利用观察者模式解除耦合,让耦合双方都依赖于抽象。就像老板回来了,偷懒的同事应该依赖的是前台秘书这个抽象类,而不应依赖于具体的名为“小白”的秘书。
序列化(serialization)机制:能够将一个实例对象的状态信息写入到一个字节流中,使其可以通过socket进行传输、或者持久化存储到数据库或文件系统中;然后在需要的时候,可以读取字节流中的信息来重构一个相同的对象。
Java程序执行过程:首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。运行时数据区通常包括:程序计数器、Java栈、本地方法栈、方法区、堆。
类加载:类从加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载-验证-准备-解析-初始化-使用-卸载,其中验证-准备-解析称为链接。 加载阶段,虚拟机需要完成下面3件事:1)通过一个类的全限定名获取定义此类的二进制字节流;2)将这个字节流所表示的静态存储结构转化为方法区运行时数据结构3)在内存中生成一个代表这个类的class对象,作为方法区的各种数据的访问入口。 _验证_的目的是为了确保clsss文件的字节流中包含的信息符合当前虚拟机的要求,且不会危害虚拟机自身的安全。验证阶段大致会完成下面4个阶段的检验动作:1)文件格式验证2)元数据验证3)字节码验证4)符号引用验证{字节码验证将对类的方法进行校验分析,保证被校验的方法在运行时不会做出危害虚拟机的事,一个类方法体的字节码没有通过字节码验证,那一定有问题,但若一个方法通过了验证,也不能说明它一定安全}。 _准备_阶段是正式为类变量分配内存并设置变量的初始化值得阶段,这些变量所使用的内存都将在方法区中进行分配。(不是实例变量,且是初始值,若public static int a=123;准备阶段后a的值为0,而不是123,要在初始化之后才变为123,但若被final修饰,public static final int a=123;在准备阶段后就变为了123) _解析_阶段是虚拟机将常量池中的符号引用变为直接引用的过程。静态代码块只能访问在静态代码块之前的变量,在它之后的变量,在前面的静态代码块中可以复制,但是不可以使用。通过一个类的全限定名来获取定义此类的二进制字节流,实现这个动作的代码就是“类加载器”。比较两个类是否相同,只有这两个类是由同一个类加载器加载的前提下才有意义,否则即使这两个类来源于同一个class文件,被同一个虚拟机加载,只要加载他们的加载器不同,他们就是不同的类。 从Java虚拟机的角度来说,只存在两种不同的类加载器:一种是启动类加载器,这个类加载器使用c++实现,是虚拟机自身的一部分。另一种就是所有其他的类加载器,这些类加载器都由Java实现,且全部继承自java.lang.ClassLoader。
类加载器 分为:1)启动类加载器,这个加载器负责把
双亲委派模型:若一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把所这个请求委派给父类加载器去完成,每一层的加载器都是如此,因此all加载请求最终都应该传送到顶级的启动类加载器。只有当父类加载器反馈自己无法加载时(他的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。双亲委派模型好处:eg,object类。它存放在rt.jar中,无论哪个类加载器要加载这个类,最终都是委派给处于模型顶端的启动类加载器加载,因此object类在程序的各种加载环境中都是同一个类。如果程序自定义一个java.lang.Object:否则的话,如果不使用该模型的话,如果用户自定义一个java.lang.Object类且存放在classpath中,那么系统中将会出现多个Object类,应用程序也会变得很混乱。如果我们自定义一个rt.jar中已有类的同名Java类,会发现JVM可以正常编译,但该类永远无法被加载运行。
GC: 它使得编写程序时不在需要考虑内存管理1)引用计数法:对象是否存活堆中每个对象实例都有一个引用计数。当一个对象被创建时,且将该对象实例分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象实例的计数器+1),但当一个对象实例的某个引用超过了生命周期或者被设置为一个新值时,对象实例的引用计数器减1。任何引用计数器为0的对象实例可以被当作垃圾收集。当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器减1。2).tracing算法(Tracing Collector) 或 标记-清除算法(mark and sweep):程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。标记-清除从根集合进行扫描,对存活的对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。标记-整理算法:采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针3)拷贝算法:开始时把堆分成 一个对象 面和多个空闲面, 程序从对象面为对象分配空间,当对象满了,基于copying算法的垃圾 收集就从根集中扫描活动对象,并将每个 活动对象复制到空闲面(使得活动对象所占的内存之间没有空闲洞),这样空闲面变成了对象面,原来的对象面变成了空闲面,程序会在新的对象面中分配内存(停止复制算法)4)分代垃圾回收:新生代(停止-复制算法:它将可用内存按照容量划分为大小相等的两块,每次只使用其中一块。当这一块的内存用完了,则就将还存活的对象复制到另一块上面,然后再把已经使用过的内存空间一次清理掉。商业虚拟机:将内存分为一块较大的.) 老年代(标记-清除:当程序运行期间,若可以使用的内存被耗尽的时候,GC线程就会被触发并将程序暂停,随后将依旧存活的对象标记一遍,最终再将堆中所有没被标记的对象全部清除掉,接下来便让程序恢复运行【缺点1)产生大量不连续的内存碎片2)标记和清除效率都不高】。标记-清理:标记过程和“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清除,而是让all存活对象都向一端移动,然后直接清理掉端边界以外的内存。)
可作为GC roots 的对象: 1)java虚拟机栈(栈帧中的本地变量表)中引用的对象2)方法区中类的静态属性引用的对象3)方法区中常量引用的对象4)本地方法栈中JNI引用的对象. 强引用>软引用>弱引用>虚引用. 任何一个对象的finalize()方法都只会被系统调用一次。若对象在进行可达性分析后发现没有与GC roots相连接的引用链,那么他将会被第一次标记并进行一次筛选,筛选的条件是该对象是否有必要执行finalize()方法,当对象没有重写finalize()方法或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为没必要执行。 若该对象被判定为有必要执行finalize方法,则这个对象会被放在一个F-Queue 队列,finalize方法是对象逃脱死亡命运的最后一次机会,稍后GC 将对F-queue中的对象进行第二次小规模的标记,若对象要在finalize中成功拯救自己—只要重新与引用链上的任何一个对象建立关联即可,那么在第二次标记时他们将会被移出“即将回收”集合。
垃圾收集器:新生代MinorGC【1)serial收集器:单线程(单线程的意义不仅仅说明它会使用一个cpu or 一条垃圾收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集的时候,必须暂停其他all工作线程,直到他收集结束)。对于运行在client模式下的虚拟机来说是个很好的选择。停止-复制2)parNew搜集器:serial收集器的单线程版本,是许多运行在server模式下的虚拟机首选的新生代收集器。停止-复制3)parallel scaverge:目标达到一个可控制的吞吐量,适合在后台运算,没有太多的交互。停止-复制。】 老年代MajorGC【4)serial old:serial 的老年代版本,单线程,标记-清理5)parallel old:parallel scaverge老年代的版本,多线程标记-清理6)cms收集器:一种以获取最短回收停顿时间为目标的收集器“标记-清除”,有4个过程初始标记(查找直接与gc roots链接的对象)并发标记(tracing过程)重新标记(因为并发标记时有用户线程在执行,标记结果可能有变化)并发清除其中初始标记和重新标记阶段,要“stop the world”(停止工作线程)。优点:并发收集,低停顿缺点:1)不能处理浮动垃圾2)对cpu资源敏感3)产生大量内存碎片)】
对象的分配:1)大多数情况下,对象在新生代eden区中分配,当Eden区中没有足够的内存空间进行分配时,虚拟机将发起一次minor GC {minor gc:发生在新生代的垃圾收集动作,非常频繁,一般回收速度也比较快full gc:发生在老年代的gc} 2)大对象直接进入老年代3)长期存活的对象将进入老年代4)若在survivor空间中相同年龄all对象大小的总和>survivor空间的一半,则年龄>=改年龄的对象直接进入老年代,无须等到MaxTeuringThreshold(默认为15)中的要求。
空间分配担保:在发生minor gc 前,虚拟机会检测老年代最大可用的连续空间是否>新生代all对象总空间,若这个条件成立,那么minor gc可以确保是安全的。若不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。若允许,那么会继续检测老年代最大可用的连续空间是否>历次晋升到老年代对象的平均大小。若大于,则将尝试进行一次minor gc,尽管这次minor gc是有风险的。若小于或HandlePromotionFailure设置不允许冒险,则这时要改为进行一次full gc。
MVC 1)m:model。Dao。与数据库打交道2)V:view, jsp 在页面上填写java代码,实现显示3)C,controller,servlet受理请求,获取请求参数,调用dao方法,转发or重定向页面。
ArrayLsit和LinkedList的区别: ArrayList底层是用数组实现的,可以认为ArrayList是一个可改变大小的数组。随着越来越多的元素被添加到ArrayList中,其规模是动态增加的。LinkedList底层是通过双向链表实现的, LinkedList和ArrayList相比,增删的速度较快。但是查询和修改值的速度较慢。 使用场景:LinkedList更适合从中间插入或者删除(链表的特性)。 ArrayList更适合检索和在末尾插入或删除(数组的特性)
__http(超文本传输协议)__是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接的机制,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
网络七层协议:7 应用层 【6 表示层 5 会话层 】4 传输层 3 网络层 2 数据链路层 1 物理层
TCP(数据传输控制协议)三次握手: 建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立1. 传输数据之前,客户端首先向服务器端发送一个SYN=1(触发标志),seq=x的触发数据包,等待服务器端的确认。2. 服务器端收到该触发数据包之后,就开始回应,它会发送一个SYN=1,ack=1,seq=y,ack=x+1(确认号标志)的数据包,进行确认和进一步触发。3最后一步是客户端的最终的确定。它会发一个SYN=0,ack=1,seq=x+1,ack=y+1的确认包,进行最后的确认。确认完毕,三次握手就建立成功。此后,就可以进行数据通信了。
TCP四次挥手:即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。1.Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。2.Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。3.Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。4.Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为何4次挥手:这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
TCP/IP协议簇:【应用层】:超文本传输协议(HTTP):万维网的基本协议.文件传输(TFTP简单文件传输协议):远程登录(Telnet),提供远程访问其它主机功能。网络管理(SNMP简单网络管理协议),该协议提供了监控网络设备的方法,以及配置管理,统计信息收集,性能管理及安全管理等. 域名系统(DNS),该系统用于在internet中将域名及其公共广播的网络节点转换成IP地址. 【网络层】Internet协议(IP)、Internet控制信息协议(ICMP)、地址解析协议(ARP) 、反向地址解析协议(RARP) 【传输层端到端】:TCP,UDP
| Tcp与udp的区别:传输控制协议 | 用户数据报协议1.流模式与数据包模式2.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。基于TCP:Telnet、FTP、rlogin、X Windows和SMTP,SNMP,HTTP,基于UDP: DNS, TFTP, SNMP |
String 的不可变性:当一个字符串在堆中被分配内容时,它就是不可变的,任何String的方法都无法改变字符串本身,但它可以返回一个新的字符串对象。①字符串池(String pool)的需求:在Java中,当初始化一个字符串变量时,如果字符串已经存在,就不会创建一个新的字符串变量,而是返回存在字符串的引用。②缓存字符串hashcode码的需要:字符串的hashcode是经常被使用的,字符串的不变性确保了hashcode的值一直是一样的,在需要hashcode时,就不需要每次都计算,这样会很高效。③出于安全性考虑:字符串经常作为网络连接、数据库连接等参数,不可变就可以保证连接的安全性。
Http请求状态码:1消息2成功3重定向4请求错误5服务器错误 int的取值范围为(-2147483648~2147483647)负的2的31次幂——2的31次幂-1
__Java序列化__是指把Java对象保存为二进制字节码的过程
TopK问题:分而治之/hash映射 + hash统计 + 堆/快速/归并排序;双层桶划分;Bloom filter/Bitmap;Trie树/数据库/倒排索引;外排序;分布式处理之Hadoop/Mapreduce
Java8新特性:1. 接口的默认方法(扩展方法default)2. Lambda 表达式3. 函数式接口(仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法)4. 方法与构造函数引用5. Lambda 作用域6. 访问局部变量(直接在lambda表达式中访问外层的局部变量)7. 访问对象字段与静态变量(lambda内部对于实例的字段以及静态变量是即可读又可写)8. 访问接口的默认方法(Predicate接口、Function 接口、Supplier 接口、Consumer 接口、Comparator 接口、Optional 接口、Stream 接口、Filter 过滤、Sort 排序、Map 映射、Match 匹配、Count 计数、Reduce 规约)9. Date API(Clock 时钟、Timezones 时区、LocalTime 本地时间、LocalDate 本地日期、LocalDateTime 本地日期时间)10. Annotation 注解(注解使用多次,@Repeatable) Java9新特性:1. 模块化系统(减少Java应用和Java核心运行时环境的大小与复杂性)2. JShell–Java 9 REPL(于以即时结果和反馈的形式,简化原型的实现并帮助我们探索语言在编码时的可选项)3. 集合工厂方法 4. 接口中的私有方法5. 响应式流6. 多分辨率图像API–JEP 2517. 进程API的改进(os process拥有更好的控制和管理方式)8. 异常的处理9. diamond操作符范围的延伸(匿名类中使用)10增强的注释Deprecated、统一的JVM日志10. HTTP 2 客户端11. 保留下划线字符。变量不能被命名为_; 废弃Applet API; javac不再支持Java1.4以及之前的版本; 废弃Java浏览器插件; 栈遍历API–栈遍历API能过滤和迟访问在堆栈跟踪中的信息。
Java10新特性:1. 局部变量类型推断(var)2. GC改进和内存管理 3. 线程本地握手 4. 备用内存设备上的堆分配 5. 其他Unicode语言 - 标记扩展 6. 基于Java的实验性JIT编译器 7. 根证书8根证书颁发认证9. 将JDK生态整合单个存储库10.删除工具javah
NIO: nio是new io,块io,所以nio效率比io高。Java api中有2套nio:1)针对标准输入输出nio;2)网络编程nio。Io以流方式;nio以块方式处理数据。面向流的io一次处理一个字节,一个输入流产生一个字节,一个输出流消费一个字节。面向块的io,每一个操作都在一步中产生或消费一个数据块。 channel是对原io中流的模拟,任何来源和目的数据都必须通过一个channel对象。一个Buffer是一个容器对象,发给channel的所有对象都必须先放到Buffer中,同样的,从channel中读取的任何数据都要读到Buffer。 在nio中,数据是放入buffer对象的。在io中,数据是直接写入或读到stream对象。应用程序不能直接对channel进行读写操作,而必须通过buffer来进行。
Synchronized 和static Synchronized的区别: 一个是实例锁【Synchronized】(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全局锁【static synchronized】(该锁针对的是类,无论实例多少个对象,那么线程都共享该锁)。实例锁是锁特定的实例(只要有synchronized就会去锁该实例),全局锁是锁所有的实例。 synchronized是对类的当前实例(当前对象)进行加锁,防止其他线程同时访问该类的该实例的所有
继承与多态:抽象、封装、继承:子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。或子类从父类继承方法,使得子类具有父类相同的行为。多态:子类重写父类的方法。使子类具有不同的方法实现。把父类类型作为参数类型,该父类及其子类对象作为参数转入。运行时,根据实际创建的对象类型动态决定使用那个方法。
xml和Json的区别:【定义】1.类似于HTML的语言,无预先定义的标签,使用DTD文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准。2. 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON采用完全独立于语言的文本格式,理想的数据交换语言。【优势】1. .格式统一,符合标准;容易进行系统间数据交换、共享2. 轻量级数据交换格式,用简单的key:value键值对即可标识所有对象关系,不需要过多的标签;支持压缩,占用带宽小;易于解析,客户端用JavaScript可以采用面向对象的方式直接获取JSON对象的属性,能直接被客户端使用,减少了客户端开发【劣势】1. 文件格式庞大、复杂,网络传输占用带宽较大; 需要大量代码来解析XML格式文件,复用性较差;浏览器间存在差异,IE和其他浏览器对XML解析和操作存在差异。2. 没有XML格式这么推广的深入人心和使用广泛, 没有XML那么通用性,出现较晚,还处于推广阶段;对数据的描述性比XML差。【解析】1. 两种解析方式:DOM和 SAX;.DOM是把一个数据交换格式XML看成一个DOM对象,需要把XML文件整个读入内存.SAX不需要整个读入文档就可以对解析出的内容进行处理,是一种逐步解析的方法。2. JSON只提供整体解析方案,而这种方法只在解析较少的数据时才能起到良好的效果;而XML提 供了对大规模数据的逐步解析方案
5种IO模型:同步:1)阻塞I/O 2)非阻塞I/O 3)I/O复用(select和poll) 4)信号驱动I/O(SIGIO) 异步: 5)异步I/O
红黑树:平衡的二叉树,不是一个完美平衡二叉树。我们希望一个所有查找都能在lgN次比较内结束,但是这样在动态插入中保持树的完美平衡代价太高,放松逛一下限制找到一个能在对数时间内完成查找的数据结构,在普通二叉树上,对每个节点添加一个颜色属性,性质:①节点是红色或者是黑色②根节点是黑色③每个叶节点(NIL或空节点)是黑色④每个红色节点的两个子节点都是黑色的(也就是说不存在两个连续的红色节点)⑤对于任一结点而言,其到叶结点树尾端NIL指针的每一条路径都包含相同数目的黑结点。 相比BST和AVL有何优点:相比BST:①红黑树可以能确保树的最长路径不大于两倍的最短路径的长度,所以可以看出它的查找效果是有最低保证的。在最坏的情况下也可以保证O(logN)的,这是要好于二叉查找树的。因为二叉查找树最坏情况可以让查找达到O(N)。相比AVL:①算法时间复杂度和AVL相同,但统计性能比AVL树更高,所以在插入和删除中所做的后期维护操作肯定会比红黑树要耗时好多,但是他们的查找效率都是O(logN),所以红黑树应用还是高于AVL树的. 数据分布较好—— AVL树,杂乱——红黑树。