查找算法——二分查找与插值查找
二分查找二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。
具体的算法流程是:当表中的元素是升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功,直接返回;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
使用二分查找的场景:数组有序
非递归版1234567891011121314public static int binarySearch(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; //防止溢出 if (nums[mid] == target) { retu ...
源码分析Arrays.sort中使用的排序算法
Java 主要排序方法为 java.util.Arrays.sort(),粗略的来讲,对于基本数据类型使用双轴快排,对于引用类型使用归并排序。接下来我们深入 Arrays.sort 的源码,更具体的分析其中所使用的排序算法。
Arrays.sort底层一开始会判断数组是否是小数组(元素个数小于286),是则使用快速排序。
1234567static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen) { // Use Quicksort on small arrays 对小数组使用快速排序 if (right - left < QUICKSORT_THRESHOLD) { sort(a, left, right, true); return; }
但其实也并不是直接就开始使用快速排序,点进 sort(a, left, right, true) 看,会发现元素个数小于 ...
十大排序算法——Java实现
冒泡排序从要排序序列的第一个元素开始,不断比较相邻元素的值,发现逆序则交换,将值较大的元素逐渐从前向后移动。
每找到待排序序列的最大值时,就将该最大值固定在待排序序列的尾部,且每找到一个待排序序列最大值需要循环一次,n 个值则需要循环 n 次,但最后一个值无需比较,则实际需循环 n-1 次,即 i < arr.length - 1 。
1234567891011public void bubbleSort (int[] arr) { for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; ...
深入理解Java虚拟机——类加载机制
类加载机制类的生命周期一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称为连接(Linking)。
类的加载过程
1、加载类加载过程的第一步,Java虚拟机需要完成以下三件事情:
通过一个类的全限定名来获取定义此类的二进制字节流。
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
2、验证确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
主要包括四种验证:文件格式验证、元数据验证、字节码验证、符号引用验证
3、准备准备阶段是正式为类变量分配内存并设置类变量初始值(零值)的阶段,这些变量所使用的内存都应当在方法区中进行分配。
这时候进行内存分配的仅 ...
CMS与G1垃圾收集器详解
CMS 收集器CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户交互体验的应用上使用。CMS 收集器是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
作用域:老年代
垃圾收集算法:标记 - 清除算法
线程数:并发线程
特点:以缩短停顿时间为目标
从名字中的Mark Sweep可以看出,CMS 收集器是基于 “标记-清除”算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:
初始标记: 仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快。
并发标记:并发标记阶段从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。
重新标记: 重新标记阶段是为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段的时间稍长,但也远比并发标记阶段的时间短。
并发清除: 清理删除 ...
深入理解Java虚拟机——垃圾收集器与内存分配策略
对象已死?引用计数算法给对象中添加一个引用计数器,每当有一个地方引用它,计数器值就加 1;当引用失效时,计数器值就减 1;任何时刻计数器为 0 的对象就是不可能再被使用的。
引用计数算法实现原理简单,判定效率高,但目前主流的虚拟机中都没有选择这个算法来管理内存,其主要原因是有很多例外情况要考虑,比如它很难解决对象之间相互循环引用的问题。所谓对象之间的相互引用问题,即对象 objA 和 objB 都有字段 instance ,且令 objA.instance = objB 及 objB.instance = objA ,除此之外,这两个对象之间再无任何引用。然后将 objA 与 objB 都置为 null,实际上着两个对象已经不可能再被访问,但是他们因为互相引用对方,导致它们的引用计数器都不为 0,于是引用计数算法无法通知 GC 回收器回收他们。
可达性分析算法这个算法的基本思路就是通过一系列称为 “GC Roots” 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为 “引用链” ,如果某个对象到 GC Roots 间没有任何引用链相连,或者用图论的 ...
字符串常量池与包装类详解
字符串常量池设计思想JVM为了提升性能和减少内存开销,避免重复创建字符串,其维护了一块特殊的内存空间,即字符串常量池。当需要使用字符串时,先去检查字符串常量池是否存在该字符串,若存在,则直接返回该字符串的引用地址;若不存在,则在字符串常量池中创建字符串对象,并返回对象的引用地址。
123String a = "abc"; // 放至常量池String b = "abc"; // 从常量池中取出System.out.println(a == b); // trzue
注意:在 JDK7 之前,字符串常量池位置在永久代(方法区)中,此时字符串常量池存放的是对象及其引用。到 JDK7 时,字符串常量池被移动至堆中,此时字符串常量池只存放引用,字符串对象在堆中。
所处内存区域
在 JDK 1.7 之前,运行时常量池(包括字符串常量池)存放在方法区,此时HotSpot虚拟机对方法区的实现为永久代。
在 JDK 1.7 时,字符串常量池被从方法区转移至 Java 堆中,注意并不是运行时常量池,而是字符串常量池被单独转移到堆,运行时常量池剩下的东西还是 ...
深入理解Java虚拟机——HotSpot虚拟机对象探秘
对象的创建
1、类加载检查当虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在Metaspace的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。(通过双亲委派模式,将类加载进内存)
2、分配内存在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存块从 Java 堆中划分出来。分配方式有 “指针碰撞” 和 “空闲列表” 两种,选择哪种分配方式由 Java 堆是否规整决定,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
内存分配的两种方式:
选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器的算法是”标记-清除”,还是”标记-整理”(也称作”标记-压缩”),复制算法内存也是规整的。
内存分配并发问题:
在创建对象的时候有一个很重要的问题,就是线程安全,因为在实际开发过程中,对象创建在虚拟机中是非常频繁的行为,即使 ...
深入理解Java虚拟机——Java内存区域
运行时数据区
程序计数器(线程私有)
虚拟机栈(线程私有)
本地方法栈(线程私有)
堆(线程共享)
方法区(线程共享)
Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。JDK 1.8 和之前的版本略有不同:
程序计数器程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
Java虚拟机的多线程通过CPU不停切换各个线程,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
虚拟机栈与程序计数器一样, Java 虚拟机栈也是线程私有的,它的生命周期与线程相同。
虚拟机栈描述的是 Java 方法执行的线程内存模型:每个方法被执行的时候, Java 虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个 ...
MongoDB学习总结
初始什么是MongoDBMongoDB 是一个基于分布式文件存储的数据库。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
与MySQL相比的优势1、弱一致性(最终一致),更能保证用户的访问速度2、文档结构的存储方式,高扩展性高扩展性,存储的数据格式是json格式
3、第三方支持丰富4、性能优越MySQL在海量数据处理的时候效率会显著变慢。
在适量级的内存的Mongodb的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快。
缺点1、不支持事务操作2、占用空间过大
安装下载下载地址:https://www.mongodb.com/try/download/community
配置在data目录下创建db文件夹,在mongodb的bin目录下打开cmd输入命令 mongod -dbpath 所在位置
1D:\Environment\MongoDB\bin>mongod -dbpath D:\Environment\Mongo ...