mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-16 18:10:13 +08:00
Merge branch 'master' of github.com:Snailclimb/JavaGuide
This commit is contained in:
commit
221635d61e
@ -14,38 +14,36 @@ n<=39
|
||||
**采用迭代法:**
|
||||
|
||||
```java
|
||||
int Fibonacci(int number) {
|
||||
if (number <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (number == 1 || number == 2) {
|
||||
return 1;
|
||||
}
|
||||
int first = 1, second = 1, third = 0;
|
||||
for (int i = 3; i <= number; i++) {
|
||||
third = first + second;
|
||||
first = second;
|
||||
second = third;
|
||||
}
|
||||
return third;
|
||||
}
|
||||
int Fibonacci(int number) {
|
||||
if (number <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (number == 1 || number == 2) {
|
||||
return 1;
|
||||
}
|
||||
int first = 1, second = 1, third = 0;
|
||||
for (int i = 3; i <= number; i++) {
|
||||
third = first + second;
|
||||
first = second;
|
||||
second = third;
|
||||
}
|
||||
return third;
|
||||
}
|
||||
```
|
||||
|
||||
**采用递归:**
|
||||
|
||||
```java
|
||||
public int Fibonacci(int n) {
|
||||
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (n == 1||n==2) {
|
||||
return 1;
|
||||
}
|
||||
public int Fibonacci(int n) {
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (n == 1||n==2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Fibonacci(n - 2) + Fibonacci(n - 1);
|
||||
|
||||
}
|
||||
return Fibonacci(n - 2) + Fibonacci(n - 1);
|
||||
}
|
||||
```
|
||||
|
||||
### 二 跳台阶问题
|
||||
@ -71,24 +69,24 @@ f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5, 可以总结出f(n) = f(n-1) + f(n-2)
|
||||
#### **示例代码:**
|
||||
|
||||
```java
|
||||
int jumpFloor(int number) {
|
||||
if (number <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (number == 1) {
|
||||
return 1;
|
||||
}
|
||||
if (number == 2) {
|
||||
return 2;
|
||||
}
|
||||
int first = 1, second = 2, third = 0;
|
||||
for (int i = 3; i <= number; i++) {
|
||||
third = first + second;
|
||||
first = second;
|
||||
second = third;
|
||||
}
|
||||
return third;
|
||||
}
|
||||
int jumpFloor(int number) {
|
||||
if (number <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (number == 1) {
|
||||
return 1;
|
||||
}
|
||||
if (number == 2) {
|
||||
return 2;
|
||||
}
|
||||
int first = 1, second = 2, third = 0;
|
||||
for (int i = 3; i <= number; i++) {
|
||||
third = first + second;
|
||||
first = second;
|
||||
second = third;
|
||||
}
|
||||
return third;
|
||||
}
|
||||
```
|
||||
|
||||
### 三 变态跳台阶问题
|
||||
@ -113,9 +111,9 @@ f(n)=f(n-1)+f(n-2)+...+f(1)
|
||||
#### **示例代码:**
|
||||
|
||||
```java
|
||||
int JumpFloorII(int number) {
|
||||
return 1 << --number;//2^(number-1)用位移操作进行,更快
|
||||
}
|
||||
int JumpFloorII(int number) {
|
||||
return 1 << --number;//2^(number-1)用位移操作进行,更快
|
||||
}
|
||||
```
|
||||
|
||||
#### **补充:**
|
||||
@ -124,7 +122,7 @@ f(n)=f(n-1)+f(n-2)+...+f(1)
|
||||
|
||||
1. “<<” : **左移运算符**,等同于乘2的n次方
|
||||
2. “>>”: **右移运算符**,等同于除2的n次方
|
||||
3. “>>>” **无符号右移运算符**,不管移动前最高位是0还是1,右移后左侧产生的空位部分都以0来填充。与>>类似。
|
||||
3. “>>>” : **无符号右移运算符**,不管移动前最高位是0还是1,右移后左侧产生的空位部分都以0来填充。与>>类似。
|
||||
例:
|
||||
int a = 16;
|
||||
int b = a << 2;//左移2,等同于16 * 2的2次方,也就是16 * 4
|
||||
@ -147,22 +145,22 @@ f(n)=f(n-1)+f(n-2)+...+f(1)
|
||||
#### **示例代码:**
|
||||
|
||||
```java
|
||||
public boolean Find(int target, int [][] array) {
|
||||
//基本思路从左下角开始找,这样速度最快
|
||||
int row = array.length-1;//行
|
||||
int column = 0;//列
|
||||
//当行数大于0,当前列数小于总列数时循环条件成立
|
||||
while((row >= 0)&& (column< array[0].length)){
|
||||
if(array[row][column] > target){
|
||||
row--;
|
||||
}else if(array[row][column] < target){
|
||||
column++;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
public boolean Find(int target, int [][] array) {
|
||||
//基本思路从左下角开始找,这样速度最快
|
||||
int row = array.length-1;//行
|
||||
int column = 0;//列
|
||||
//当行数大于0,当前列数小于总列数时循环条件成立
|
||||
while((row >= 0)&& (column< array[0].length)){
|
||||
if(array[row][column] > target){
|
||||
row--;
|
||||
}else if(array[row][column] < target){
|
||||
column++;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
### 五 替换空格
|
||||
@ -175,38 +173,37 @@ f(n)=f(n-1)+f(n-2)+...+f(1)
|
||||
|
||||
这道题不难,我们可以通过循环判断字符串的字符是否为空格,是的话就利用append()方法添加追加“%20”,否则还是追加原字符。
|
||||
|
||||
或者最简单的方法就是利用: replaceAll(String regex,String replacement)方法了,一行代码就可以解决。
|
||||
或者最简单的方法就是利用:replaceAll(String regex,String replacement)方法了,一行代码就可以解决。
|
||||
|
||||
#### **示例代码:**
|
||||
|
||||
**常规做法:**
|
||||
|
||||
```java
|
||||
public String replaceSpace(StringBuffer str) {
|
||||
StringBuffer out=new StringBuffer();
|
||||
for (int i = 0; i < str.toString().length(); i++) {
|
||||
char b=str.charAt(i);
|
||||
if(String.valueOf(b).equals(" ")){
|
||||
out.append("%20");
|
||||
}else{
|
||||
out.append(b);
|
||||
}
|
||||
public String replaceSpace(StringBuffer str) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
for (int i = 0; i < str.toString().length(); i++) {
|
||||
char b = str.charAt(i);
|
||||
if(String.valueOf(b).equals(" ")){
|
||||
out.append("%20");
|
||||
}else{
|
||||
out.append(b);
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
```
|
||||
|
||||
**一行代码解决:**
|
||||
|
||||
```java
|
||||
public String replaceSpace(StringBuffer str) {
|
||||
//return str.toString().replaceAll(" ", "%20");
|
||||
//public String replaceAll(String regex,String replacement)
|
||||
//用给定的替换替换与给定的regular expression匹配的此字符串的每个子字符串。
|
||||
//\ 转义字符. 如果你要使用 "\" 本身, 则应该使用 "\\". String类型中的空格用“\s”表示,所以我这里猜测"\\s"就是代表空格的意思
|
||||
return str.toString().replaceAll("\\s", "%20");
|
||||
}
|
||||
|
||||
public String replaceSpace(StringBuffer str) {
|
||||
//return str.toString().replaceAll(" ", "%20");
|
||||
//public String replaceAll(String regex,String replacement)
|
||||
//用给定的替换替换与给定的regular expression匹配的此字符串的每个子字符串。
|
||||
//\ 转义字符. 如果你要使用 "\" 本身, 则应该使用 "\\". String类型中的空格用“\s”表示,所以我这里猜测"\\s"就是代表空格的意思
|
||||
return str.toString().replaceAll("\\s", "%20");
|
||||
}
|
||||
```
|
||||
|
||||
### 六 数值的整数次方
|
||||
@ -279,17 +276,17 @@ public class Solution {
|
||||
当然这一题也可以采用笨方法:累乘。不过这种方法的时间复杂度为O(n),这样没有前一种方法效率高。
|
||||
|
||||
```java
|
||||
// 使用累乘
|
||||
public double powerAnother(double base, int exponent) {
|
||||
double result = 1.0;
|
||||
for (int i = 0; i < Math.abs(exponent); i++) {
|
||||
result *= base;
|
||||
}
|
||||
if (exponent >= 0)
|
||||
return result;
|
||||
else
|
||||
return 1 / result;
|
||||
// 使用累乘
|
||||
public double powerAnother(double base, int exponent) {
|
||||
double result = 1.0;
|
||||
for (int i = 0; i < Math.abs(exponent); i++) {
|
||||
result *= base;
|
||||
}
|
||||
if (exponent >= 0)
|
||||
return result;
|
||||
else
|
||||
return 1 / result;
|
||||
}
|
||||
```
|
||||
|
||||
### 七 调整数组顺序使奇数位于偶数前面
|
||||
@ -434,22 +431,21 @@ public class ListNode {
|
||||
}
|
||||
}*/
|
||||
public class Solution {
|
||||
public ListNode ReverseList(ListNode head) {
|
||||
ListNode next = null;
|
||||
ListNode pre = null;
|
||||
while (head != null) {
|
||||
//保存要反转到头来的那个节点
|
||||
next = head.next;
|
||||
//要反转的那个节点指向已经反转的上一个节点
|
||||
head.next = pre;
|
||||
//上一个已经反转到头部的节点
|
||||
pre = head;
|
||||
//一直向链表尾走
|
||||
head = next;
|
||||
public ListNode ReverseList(ListNode head) {
|
||||
ListNode next = null;
|
||||
ListNode pre = null;
|
||||
while (head != null) {
|
||||
//保存要反转到头来的那个节点
|
||||
next = head.next;
|
||||
//要反转的那个节点指向已经反转的上一个节点
|
||||
head.next = pre;
|
||||
//上一个已经反转到头部的节点
|
||||
pre = head;
|
||||
//一直向链表尾走
|
||||
head = next;
|
||||
}
|
||||
return pre;
|
||||
}
|
||||
return pre;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
@ -538,20 +534,20 @@ public class Solution {
|
||||
|
||||
```java
|
||||
public ListNode Merge(ListNode list1,ListNode list2) {
|
||||
if(list1 == null){
|
||||
return list2;
|
||||
}
|
||||
if(list2 == null){
|
||||
return list1;
|
||||
}
|
||||
if(list1.val <= list2.val){
|
||||
list1.next = Merge(list1.next, list2);
|
||||
return list1;
|
||||
}else{
|
||||
list2.next = Merge(list1, list2.next);
|
||||
return list2;
|
||||
}
|
||||
}
|
||||
if(list1 == null){
|
||||
return list2;
|
||||
}
|
||||
if(list2 == null){
|
||||
return list1;
|
||||
}
|
||||
if(list1.val <= list2.val){
|
||||
list1.next = Merge(list1.next, list2);
|
||||
return list1;
|
||||
}else{
|
||||
list2.next = Merge(list1, list2.next);
|
||||
return list2;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 十一 用两个栈实现队列
|
||||
@ -642,8 +638,6 @@ https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106
|
||||
….
|
||||
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
|
||||
|
||||
|
||||
|
||||
#### **考察内容:**
|
||||
|
||||
栈
|
||||
|
@ -57,7 +57,7 @@
|
||||
|
||||
## 二 运行时数据区域
|
||||
|
||||
Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。JDK. 1.8 和之前的版本略有不同,下面会介绍到。
|
||||
Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。JDK 1.8 和之前的版本略有不同,下面会介绍到。
|
||||
|
||||
**JDK 1.8 之前:**
|
||||
|
||||
@ -96,7 +96,7 @@ Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成
|
||||
|
||||
**与程序计数器一样,Java 虚拟机栈也是线程私有的,它的生命周期和线程相同,描述的是 Java 方法执行的内存模型,每次方法调用的数据都是通过栈传递的。**
|
||||
|
||||
**Java 内存可以粗糙的区分为堆内存(Heap)和栈内存 (Stack),其中栈就是现在说的虚拟机栈,或者说是虚拟机栈中局部变量表部分。** (实际上,Java 虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。)
|
||||
**Java 内存可以粗糙的区分为堆内存(Heap)和栈内存 (Stack),其中栈就是现在说的虚拟机栈,或者说是虚拟机栈中局部变量表部分。** (实际上,Java 虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。)
|
||||
|
||||
**局部变量表主要存放了编译期可知的各种数据类型**(boolean、byte、char、short、int、float、long、double)、**对象引用**(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。
|
||||
|
||||
@ -111,7 +111,7 @@ Java 虚拟机栈也是线程私有的,每个线程都有各自的 Java 虚拟
|
||||
|
||||
**扩展:那么方法/函数如何调用?**
|
||||
|
||||
Java 栈可用类比数据结构中栈,Java 栈中保存的主要内容是栈帧,每一次函数调用都会有一个对应的栈帧被压入 Java 栈,每一个函数调用结束后,都会有一个栈帧被弹出。
|
||||
Java 栈可以类比数据结构中栈,Java 栈中保存的主要内容是栈帧,每一次函数调用都会有一个对应的栈帧被压入 Java 栈,每一个函数调用结束后,都会有一个栈帧被弹出。
|
||||
|
||||
Java 方法有两种返回方式:
|
||||
|
||||
@ -132,11 +132,11 @@ Java 方法有两种返回方式:
|
||||
|
||||
Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。**此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
|
||||
|
||||
Java 世界中“几乎”所有的对象都在堆中分配,但是,随着 JIT 编译期的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。从 JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。
|
||||
Java 世界中“几乎”所有的对象都在堆中分配,但是,随着 JIT 编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。从 JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。
|
||||
|
||||
Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(Garbage Collected Heap)**.从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代:再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。**进一步划分的目的是更好地回收内存,或者更快地分配内存。**
|
||||
Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(Garbage Collected Heap)**。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代;再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。**进一步划分的目的是更好地回收内存,或者更快地分配内存。**
|
||||
|
||||
在 JDK 7 版本及 JDK 7 版本之前,堆内存被通常被分为下面三部分:
|
||||
在 JDK 7 版本及 JDK 7 版本之前,堆内存被通常分为下面三部分:
|
||||
|
||||
1. 新生代内存(Young Generation)
|
||||
2. 老生代(Old Generation)
|
||||
@ -170,7 +170,6 @@ JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7
|
||||
> uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
|
||||
> ...
|
||||
> }
|
||||
>
|
||||
> ```
|
||||
|
||||
堆这里最容易出现的就是 OutOfMemoryError 错误,并且出现这种错误之后的表现形式还会有几种,比如:
|
||||
@ -247,7 +246,7 @@ JDK 1.8 的时候,方法区(HotSpot 的永久代)被彻底移除了(JDK1
|
||||
|
||||
**直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 错误出现。**
|
||||
|
||||
JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**通道(Channel)** 与**缓存区(Buffer)** 的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样就能在一些场景中显著提高性能,因为**避免了在 Java 堆和 Native 堆之间来回复制数据**。
|
||||
JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**通道(Channel)**与**缓存区(Buffer)**的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样就能在一些场景中显著提高性能,因为**避免了在 Java 堆和 Native 堆之间来回复制数据**。
|
||||
|
||||
本机直接内存的分配不会受到 Java 堆的限制,但是,既然是内存就会受到本机总内存大小以及处理器寻址空间的限制。
|
||||
|
||||
@ -383,10 +382,10 @@ System.out.println(str4 == str5);//false
|
||||
**验证:**
|
||||
|
||||
```java
|
||||
String s1 = new String("abc");// 堆内存的地址值
|
||||
String s2 = "abc";
|
||||
System.out.println(s1 == s2);// 输出 false,因为一个是堆内存,一个是常量池的内存,故两者是不同的。
|
||||
System.out.println(s1.equals(s2));// 输出 true
|
||||
String s1 = new String("abc");// 堆内存的地址值
|
||||
String s2 = "abc";
|
||||
System.out.println(s1 == s2);// 输出 false,因为一个是堆内存,一个是常量池的内存,故两者是不同的。
|
||||
System.out.println(s1.equals(s2));// 输出 true
|
||||
```
|
||||
|
||||
**结果:**
|
||||
@ -421,15 +420,15 @@ private static class CharacterCache {
|
||||
两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。
|
||||
|
||||
```java
|
||||
Integer i1 = 33;
|
||||
Integer i2 = 33;
|
||||
System.out.println(i1 == i2);// 输出 true
|
||||
Integer i11 = 333;
|
||||
Integer i22 = 333;
|
||||
System.out.println(i11 == i22);// 输出 false
|
||||
Double i3 = 1.2;
|
||||
Double i4 = 1.2;
|
||||
System.out.println(i3 == i4);// 输出 false
|
||||
Integer i1 = 33;
|
||||
Integer i2 = 33;
|
||||
System.out.println(i1 == i2);// 输出 true
|
||||
Integer i11 = 333;
|
||||
Integer i22 = 333;
|
||||
System.out.println(i11 == i22);// 输出 false
|
||||
Double i3 = 1.2;
|
||||
Double i4 = 1.2;
|
||||
System.out.println(i3 == i4);// 输出 false
|
||||
```
|
||||
|
||||
**Integer 缓存源代码:**
|
||||
@ -438,12 +437,11 @@ private static class CharacterCache {
|
||||
/**
|
||||
*此方法将始终缓存-128 到 127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
|
||||
*/
|
||||
public static Integer valueOf(int i) {
|
||||
if (i >= IntegerCache.low && i <= IntegerCache.high)
|
||||
return IntegerCache.cache[i + (-IntegerCache.low)];
|
||||
return new Integer(i);
|
||||
}
|
||||
|
||||
public static Integer valueOf(int i) {
|
||||
if (i >= IntegerCache.low && i <= IntegerCache.high)
|
||||
return IntegerCache.cache[i + (-IntegerCache.low)];
|
||||
return new Integer(i);
|
||||
}
|
||||
```
|
||||
|
||||
**应用场景:**
|
||||
@ -452,38 +450,38 @@ private static class CharacterCache {
|
||||
2. Integer i1 = new Integer(40);这种情况下会创建新的对象。
|
||||
|
||||
```java
|
||||
Integer i1 = 40;
|
||||
Integer i2 = new Integer(40);
|
||||
System.out.println(i1==i2);//输出 false
|
||||
Integer i1 = 40;
|
||||
Integer i2 = new Integer(40);
|
||||
System.out.println(i1==i2);//输出 false
|
||||
```
|
||||
|
||||
**Integer 比较更丰富的一个例子:**
|
||||
|
||||
```java
|
||||
Integer i1 = 40;
|
||||
Integer i2 = 40;
|
||||
Integer i3 = 0;
|
||||
Integer i4 = new Integer(40);
|
||||
Integer i5 = new Integer(40);
|
||||
Integer i6 = new Integer(0);
|
||||
Integer i1 = 40;
|
||||
Integer i2 = 40;
|
||||
Integer i3 = 0;
|
||||
Integer i4 = new Integer(40);
|
||||
Integer i5 = new Integer(40);
|
||||
Integer i6 = new Integer(0);
|
||||
|
||||
System.out.println("i1=i2 " + (i1 == i2));
|
||||
System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
|
||||
System.out.println("i1=i4 " + (i1 == i4));
|
||||
System.out.println("i4=i5 " + (i4 == i5));
|
||||
System.out.println("i4=i5+i6 " + (i4 == i5 + i6));
|
||||
System.out.println("40=i5+i6 " + (40 == i5 + i6));
|
||||
System.out.println("i1=i2 " + (i1 == i2));
|
||||
System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
|
||||
System.out.println("i1=i4 " + (i1 == i4));
|
||||
System.out.println("i4=i5 " + (i4 == i5));
|
||||
System.out.println("i4=i5+i6 " + (i4 == i5 + i6));
|
||||
System.out.println("40=i5+i6 " + (40 == i5 + i6));
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
```
|
||||
i1=i2 true
|
||||
i1=i2+i3 true
|
||||
i1=i4 false
|
||||
i4=i5 false
|
||||
i4=i5+i6 true
|
||||
40=i5+i6 true
|
||||
i1=i2 true
|
||||
i1=i2+i3 true
|
||||
i1=i4 false
|
||||
i4=i5 false
|
||||
i4=i5+i6 true
|
||||
40=i5+i6 true
|
||||
```
|
||||
|
||||
解释:
|
||||
|
@ -1,4 +1,4 @@
|
||||
> 本文由 JavaGuide 翻译自 https://www.baeldung.com/jvm-parameters,并对文章进行了大量的完善补充。翻译不易,如需转载请注明出处为: 作者: 。
|
||||
> 本文由 JavaGuide 翻译自 [https://www.baeldung.com/jvm-parameters](https://www.baeldung.com/jvm-parameters),并对文章进行了大量的完善补充。翻译不易,如需转载请注明出处,作者:[baeldung](https://www.baeldung.com/author/baeldung/) 。
|
||||
|
||||
## 1.概述
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
## 2.堆内存相关
|
||||
|
||||
>Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。**此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
|
||||
>
|
||||
|
||||
### 2.1.显式指定堆内存`–Xms`和`-Xmx`
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
RBAC 即基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式。
|
||||
|
||||
简单地说:一个用户可以拥有若干角色,每一个角色有可以被分配若干权限这样,就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系,如下图
|
||||
简单地说:一个用户可以拥有若干角色,每一个角色又可以被分配若干权限,这样就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系,如下图
|
||||
|
||||

|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||

|
||||
|
||||
生产者(客户端)发送消息到消息队列中去,接受者(服务端)处理消息,需要消费的系统直接去消息队列取消息进行消费即可而不需要和其他系统有耦合, 这显然也提高了系统的扩展性。
|
||||
生产者(客户端)发送消息到消息队列中去,接受者(服务端)处理消息,需要消费的系统直接去消息队列取消息进行消费即可而不需要和其他系统有耦合,这显然也提高了系统的扩展性。
|
||||
|
||||
**消息队列使利用发布-订阅模式工作,消息发送者(生产者)发布消息,一个或多个消息接受者(消费者)订阅消息。** 从上图可以看到**消息发送者(生产者)和消息接受者(消费者)之间没有直接耦合**,消息发送者将消息发送至分布式消息队列即结束对消息的处理,消息接受者从分布式消息队列获取该消息后进行后续处理,并不需要知道该消息从何而来。**对新增业务,只要对该类消息感兴趣,即可订阅该消息,对原有系统和业务没有任何影响,从而实现网站业务的可扩展性设计**。
|
||||
|
||||
@ -98,19 +98,19 @@ JMS 定义了五种不同的消息正文格式,以及调用的消息类型,
|
||||
|
||||
### 4.2 AMQP
|
||||
|
||||
AMQP,即 Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准 **高级消息队列协议**(二进制应用层协议),是应用层协议的一个开放标准,为面向消息的中间件设计,兼容 JMS。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件同产品,不同的开发语言等条件的限制。
|
||||
AMQP,即 Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准 **高级消息队列协议**(二进制应用层协议),是应用层协议的一个开放标准,为面向消息的中间件设计,兼容 JMS。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件同产品,不同的开发语言等条件的限制。
|
||||
|
||||
**RabbitMQ 就是基于 AMQP 协议实现的。**
|
||||
|
||||
### 4.3 JMS vs AMQP
|
||||
|
||||
| 对比方向 | JMS | AMQP |
|
||||
| :----------- | --------------------------------------: | :----------------------------------------------------------: |
|
||||
| 定义 | Java API | 协议 |
|
||||
| 跨语言 | 否 | 是 |
|
||||
| 跨平台 | 否 | 是 |
|
||||
| 对比方向 | JMS | AMQP |
|
||||
| :----------- | :-------------------------------------- | :----------------------------------------------------------- |
|
||||
| 定义 | Java API | 协议 |
|
||||
| 跨语言 | 否 | 是 |
|
||||
| 跨平台 | 否 | 是 |
|
||||
| 支持消息类型 | 提供两种消息模型:①Peer-2-Peer;②Pub/sub | 提供了五种消息模型:①direct exchange;②fanout exchange;③topic change;④headers exchange;⑤system exchange。本质来讲,后四种和 JMS 的 pub/sub 模型没有太大差别,仅是在路由机制上做了更详细的划分; |
|
||||
| 支持消息类型 | 支持多种消息类型 ,我们在上面提到过 | byte[](二进制) |
|
||||
| 支持消息类型 | 支持多种消息类型 ,我们在上面提到过 | byte[](二进制) |
|
||||
|
||||
**总结:**
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
|
||||
- **容器镜像是轻量的、可执行的独立软件包** ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。
|
||||
- **容器化软件适用于基于 Linux 和 Windows 的应用,在任何环境中都能够始终如一地运行。**
|
||||
- **容器赋予了软件独立性** ,使其免受外在环境差异(例如,开发和预演环境的差异)的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。
|
||||
- **容器赋予了软件独立性**,使其免受外在环境差异(例如,开发和预演环境的差异)的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。
|
||||
|
||||
#### 再来看看容器较为通俗的解释
|
||||
|
||||
**如果需要通俗的描述容器的话,我觉得容器就是一个存放东西的地方,就像书包可以装各种文具、衣柜可以放各种衣服、鞋架可以放各种鞋子一样。我们现在所说的容器存放的东西可能更偏向于应用比如网站、程序甚至是系统环境。**
|
||||
**如果需要通俗地描述容器的话,我觉得容器就是一个存放东西的地方,就像书包可以装各种文具、衣柜可以放各种衣服、鞋架可以放各种鞋子一样。我们现在所说的容器存放的东西可能更偏向于应用比如网站、程序甚至是系统环境。**
|
||||
|
||||

|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
|
||||
关于虚拟机与容器的对比在后面会详细介绍到,这里只是通过网上的图片加深大家对于物理机、虚拟机与容器这三者的理解(下面的图片来源与网络)。
|
||||
|
||||
**物理机**
|
||||
**物理机:**
|
||||
|
||||

|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||

|
||||
|
||||
通过上面这三张抽象图,我们可以大概可以通过类比概括出: **容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。**
|
||||
通过上面这三张抽象图,我们可以大概通过类比概括出: **容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。**
|
||||
|
||||
---
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
|
||||
### 3.1 两者对比图
|
||||
|
||||
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便.
|
||||
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
|
||||
|
||||

|
||||
|
||||
@ -130,9 +130,9 @@
|
||||
|
||||
**Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。** 镜像不包含任何动态数据,其内容在构建之后也不会被改变。
|
||||
|
||||
Docker 设计时,就充分利用 **Union FS**的技术,将其设计为 **分层存储的架构** 。 镜像实际是由多层文件系统联合组成。
|
||||
Docker 设计时,就充分利用 **Union FS** 的技术,将其设计为**分层存储的架构** 。镜像实际是由多层文件系统联合组成。
|
||||
|
||||
**镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。** 比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
|
||||
**镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。**比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
|
||||
|
||||
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
|
||||
|
||||
@ -182,7 +182,7 @@ mariadb MariaDB is a community-developed fork of MyS
|
||||
mysql/mysql-server Optimized MySQL Server Docker images. Create… 650 [OK]
|
||||
```
|
||||
|
||||
在国内访问**Docker Hub** 可能会比较慢国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 [时速云镜像库](https://hub.tenxcloud.com/ "时速云镜像库")、[网易云镜像服务](https://www.163yun.com/product/repo "网易云镜像服务")、[DaoCloud 镜像市场](https://www.daocloud.io/ "DaoCloud 镜像市场")、[阿里云镜像库](https://www.aliyun.com/product/containerservice?utm_content=se_1292836 "阿里云镜像库")等。
|
||||
在国内访问**Docker Hub** 可能会比较慢国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 [时速云镜像库](https://www.tenxcloud.com/ "时速云镜像库")、[网易云镜像服务](https://www.163yun.com/product/repo "网易云镜像服务")、[DaoCloud 镜像市场](https://www.daocloud.io/ "DaoCloud 镜像市场")、[阿里云镜像库](https://www.aliyun.com/product/containerservice?utm_content=se_1292836 "阿里云镜像库")等。
|
||||
|
||||
除了使用公开服务外,用户还可以在 **本地搭建私有 Docker Registry** 。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。
|
||||
|
||||
|
@ -4,22 +4,20 @@
|
||||
|
||||
说实话关于 Docker 是什么并太好说,下面我通过四点向你说明 Docker 到底是个什么东西。
|
||||
|
||||
- Docker 是世界领先的软件容器平台,基于 **Go 语言** 进行开发实现。
|
||||
- Docker 是世界领先的软件容器平台,基于 **Go 语言** 进行开发实现。
|
||||
- Docker 能够自动执行重复性任务,例如搭建和配置开发环境,从而解放开发人员。
|
||||
- 用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
|
||||
- Docker可以**对进程进行封装隔离,属于操作系统层面的虚拟化技术。** 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
|
||||
- Docker 可以**对进程进行封装隔离,属于操作系统层面的虚拟化技术。** 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
|
||||
|
||||
官网地址:https://www.docker.com/ 。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 为什么要用 Docker?
|
||||
|
||||
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
|
||||
|
||||
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
|
||||
容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。
|
||||
|
||||
传统的开发流程中,我们的项目通常需要使用 MySQL、Redis、FastDFS 等等环境,这些环境都是需要我们手动去进行下载并配置的,安装配置流程极其复杂,而且不同系统下的操作也不一样。
|
||||
|
||||
|
@ -82,7 +82,7 @@ Linux 内核项目组当时使用分布式版本控制系统 BitKeeper 来管理
|
||||
|
||||
大部分版本控制系统(CVS、Subversion、Perforce、Bazaar 等等)都是以文件变更列表的方式存储信息,这类系统**将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。**
|
||||
|
||||
具体原理如下图所示,理解起来其实很简单,每个我们对提交更新一个文件之后,系统记录都会记录这个文件做了哪些更新,以增量符号Δ(Delta)表示。
|
||||
具体原理如下图所示,理解起来其实很简单,每个我们对提交更新一个文件之后,系统都会记录这个文件做了哪些更新,以增量符号Δ(Delta)表示。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-3deltas.png" width="500px"/>
|
||||
@ -154,7 +154,7 @@ Git 有三种状态,你的文件可能处于其中之一:
|
||||
主体部分当然也可以有几段,但是一定要注意换行和句子不要太长。因为这样在使用 "git log" 的时候会有缩进比较好看。
|
||||
|
||||
提交的标题行描述应该尽量的清晰和尽量的一句话概括。这样就方便相关的 Git 日志查看工具显示和其他人的阅读。
|
||||
|
||||
|
||||
### 推送改动到远程仓库
|
||||
|
||||
- 如果你还没有克隆现有仓库,并欲将你的仓库连接到某个远程服务器,你可以使用如下命令添加:·`git remote add origin <server>` ,比如我们要让本地的一个仓库和 Github 上创建的一个仓库关联可以这样`git remote add origin https://github.com/Snailclimb/test.git`
|
||||
@ -164,7 +164,7 @@ Git 有三种状态,你的文件可能处于其中之一:
|
||||
|
||||
### 远程仓库的移除与重命名
|
||||
|
||||
- 将 test 重命名位 test1:`git remote rename test test1`
|
||||
- 将 test 重命名为 test1:`git remote rename test test1`
|
||||
- 移除远程仓库 test1:`git remote rm test1`
|
||||
|
||||
### 查看提交历史
|
||||
@ -183,31 +183,30 @@ git log --author=bob
|
||||
|
||||
有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 `--amend` 选项的提交命令尝试重新提交:
|
||||
|
||||
```console
|
||||
```shell
|
||||
git commit --amend
|
||||
```
|
||||
|
||||
取消暂存的文件
|
||||
|
||||
```console
|
||||
```shell
|
||||
git reset filename
|
||||
```
|
||||
|
||||
撤消对文件的修改:
|
||||
|
||||
```
|
||||
```shell
|
||||
git checkout -- filename
|
||||
```
|
||||
|
||||
假如你想丢弃你在本地的所有改动与提交,可以到服务器上获取最新的版本历史,并将你本地主分支指向它:
|
||||
|
||||
```
|
||||
```shell
|
||||
git fetch origin
|
||||
git reset --hard origin/master
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 分支
|
||||
|
||||
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,*master* 是“默认的”分支。在其他分支上进行开发,完成后再将它们合并到主分支上。
|
||||
@ -216,13 +215,13 @@ git reset --hard origin/master
|
||||
|
||||
创建一个名字叫做 test 的分支
|
||||
|
||||
```console
|
||||
```shell
|
||||
git branch test
|
||||
```
|
||||
|
||||
切换当前分支到 test(当你切换分支的时候,Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。 Git 会自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样)
|
||||
|
||||
```console
|
||||
```shell
|
||||
git checkout test
|
||||
```
|
||||
|
||||
@ -232,39 +231,39 @@ git checkout test
|
||||
|
||||
你也可以直接这样创建分支并切换过去(上面两条命令的合写)
|
||||
|
||||
```console
|
||||
```shell
|
||||
git checkout -b feature_x
|
||||
```
|
||||
|
||||
切换到主分支
|
||||
|
||||
```
|
||||
```shell
|
||||
git checkout master
|
||||
```
|
||||
|
||||
合并分支(可能会有冲突)
|
||||
|
||||
```java
|
||||
```shell
|
||||
git merge test
|
||||
```
|
||||
|
||||
把新建的分支删掉
|
||||
|
||||
```
|
||||
```shell
|
||||
git branch -d feature_x
|
||||
```
|
||||
|
||||
将分支推送到远端仓库(推送成功后其他人可见):
|
||||
|
||||
```
|
||||
git push origin
|
||||
```shell
|
||||
git push origin
|
||||
```
|
||||
|
||||
## 推荐
|
||||
|
||||
**在线演示学习工具:**
|
||||
|
||||
「补充,来自[issue729](https://github.com/Snailclimb/JavaGuide/issues/729)」Learn Git Branching https://oschina.gitee.io/learn-git-branching/ 。该网站可以方便的演示基本的git操作,讲解得明明白白。每一个基本命令的作用和结果。
|
||||
「补充,来自[issue729](https://github.com/Snailclimb/JavaGuide/issues/729)」Learn Git Branching https://oschina.gitee.io/learn-git-branching/。该网站可以方便的演示基本的git操作,讲解得明明白白。每一个基本命令的作用和结果。
|
||||
|
||||
**推荐阅读:**
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user