Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
79d7c74
[算法总结] 搞定 BAT 面试——几道常见的子符串算法题
Snailclimb Sep 10, 2018
8442291
Merge branch 'master' of https://github.com/Snailclimb/Java_Guide
Snailclimb Sep 10, 2018
1f1f3ad
字符串算法题
Snailclimb Sep 10, 2018
7b512e8
字符串算法
Snailclimb Sep 10, 2018
e1cb7a8
增加“字符串常见算法题”
Snailclimb Sep 10, 2018
fd5c975
增加 ZooKeeper 的内容
Snailclimb Sep 11, 2018
f3a6382
增加 “ZooKeeper” 的文章
Snailclimb Sep 11, 2018
1e5ea37
修改标题
Snailclimb Sep 11, 2018
788cf82
修改目录结构
Snailclimb Sep 12, 2018
69c53d0
修改错别字
Snailclimb Sep 13, 2018
2f61492
hashcode方法讲解的完善
Snailclimb Sep 13, 2018
564d7bd
补充内容
Snailclimb Sep 13, 2018
2099ea6
补充完善
Snailclimb Sep 14, 2018
cc5b7f3
修复图片无法显示问题
Snailclimb Sep 14, 2018
9d54496
final、static、this、super关键字总结
Snailclimb Sep 14, 2018
ab92540
增加 “static、final、this、super关键字总结”
Snailclimb Sep 14, 2018
8295879
增加 static 关键字总结
Snailclimb Sep 14, 2018
a15483f
增加“static关键字”详解
Snailclimb Sep 14, 2018
4d1f98e
修改页面排版
Snailclimb Sep 14, 2018
ea13483
修复图片无法显示问题
Snailclimb Sep 14, 2018
d7789b0
修改标点符号
Snailclimb Sep 14, 2018
7f922cb
修复bug:char在Java中应该占两个字节 (感谢issue提醒!)
Snailclimb Sep 15, 2018
d593ae7
补充:一个网页从请求到显示的整个过程
Snailclimb Sep 16, 2018
5f10117
修改部分格式!
Snailclimb Sep 16, 2018
8982879
修改错别字
Snailclimb Sep 16, 2018
4529ad9
get 和 post 的区别补充
Snailclimb Sep 16, 2018
2fd2106
Update final、static、this、super.md
zeason Sep 17, 2018
ad95c39
Merge pull request #23 from zeason/patch-1
Snailclimb Sep 17, 2018
183cb0a
Update Java基础知识.md
zeason Sep 17, 2018
45ba979
Merge pull request #24 from zeason/patch-2
Snailclimb Sep 17, 2018
bb4edcb
增加:” Spring中bean的作用域与生命周期“内容讲解
Snailclimb Sep 17, 2018
e0e5c04
增加:” Spring中bean的作用域与生命周期“内容讲解
Snailclimb Sep 17, 2018
9cc0e04
修改文件名字
Snailclimb Sep 17, 2018
46f51db
修复链接失效问题
Snailclimb Sep 17, 2018
ba35260
增加 ArrayList 扩容机制分析内容
Snailclimb Sep 18, 2018
03058e9
增加ArrayList-Grow一文链接
Snailclimb Sep 18, 2018
c1ce439
修复链接错误
Snailclimb Sep 18, 2018
cec7832
增加链表相关算法题
Snailclimb Sep 20, 2018
6d156a7
增加链表相关算法链接
Snailclimb Sep 20, 2018
3481546
修改和完善部分内容
Snailclimb Sep 20, 2018
2806b3e
增加关于redlock分布式锁相关内容,调整数据存储包结构
Sep 20, 2018
757470e
调整数据存储包结构
jiayangchen Sep 20, 2018
2278117
Update 如何做可靠的分布式锁,Redlock真的可行么.md
Sep 20, 2018
36196ce
增加目录
Snailclimb Sep 20, 2018
dc21529
增加目录
Snailclimb Sep 20, 2018
903efee
修改目录结构
Snailclimb Sep 20, 2018
04b4662
Update Redlock分布式锁.md
Sep 20, 2018
8b9b230
Update 如何做可靠的分布式锁,Redlock真的可行么.md
Sep 20, 2018
7e58ff4
Merge pull request #27 from DevRoom-3/feature/redis
Snailclimb Sep 20, 2018
6160404
补充增加Redis内容
Snailclimb Sep 20, 2018
1dcad6f
完善部分内容
Snailclimb Sep 21, 2018
a9a7bbe
完善内容
Snailclimb Sep 21, 2018
eeebf7d
完善
Snailclimb Sep 21, 2018
6b84b3e
修复失效链接
Snailclimb Sep 21, 2018
15f670b
修复失效链接
Snailclimb Sep 21, 2018
5046b32
修改部分内容样式
Snailclimb Sep 21, 2018
dd31d98
redis持久化
Snailclimb Sep 24, 2018
5eda80b
增加redis 4.0持久化改进
jiayangchen Sep 25, 2018
1e68e80
Merge pull request #30 from DevRoom-3/improve/redis-persistence
Snailclimb Sep 26, 2018
71a7068
对 redis 总结 这部分内容进行了一次改动较大的重构
Snailclimb Sep 26, 2018
a15058a
修改表述错误:Java中有值传递和引用传递->Java中只有值传递
Snailclimb Sep 27, 2018
d424e4f
Update README.md
Snailclimb Sep 27, 2018
66ed9fc
Update README.md
Snailclimb Sep 27, 2018
bcc0f41
什么是解释性语言
Snailclimb Sep 29, 2018
a9f0552
构造器Constructor补充
Snailclimb Sep 29, 2018
f893ac1
修改文章排版样式
Snailclimb Sep 29, 2018
421f84f
get和post请求实际上是没有区别?
Snailclimb Sep 29, 2018
38690a8
补充内容:RandomAccess接口
Snailclimb Sep 29, 2018
f94310a
String、StringBuffer、StringBuilder补充
Snailclimb Sep 29, 2018
ec28415
tableSizeFor()方法
Snailclimb Sep 29, 2018
ad8d433
修改错别字
Snailclimb Oct 1, 2018
e08f674
修复一个bug
Snailclimb Oct 2, 2018
b49eb03
增加“Java异常处理”知识点
Snailclimb Oct 2, 2018
715dd1e
Java序列话中如果有些字段不想进行序列化 怎么办
Snailclimb Oct 2, 2018
d059609
修改目录
Snailclimb Oct 2, 2018
c279173
修改文章排版
Snailclimb Oct 2, 2018
9ccc997
修改文章排版
Snailclimb Oct 2, 2018
33cf696
修改文章排版
Snailclimb Oct 2, 2018
4a987bb
阿里云产品推荐
Snailclimb Oct 6, 2018
820d49f
阿里云产品推荐
Snailclimb Oct 6, 2018
6b6eeb3
Fix typo of class name.
autumind Oct 8, 2018
52a1157
【思维导图-索引篇】
Snailclimb Oct 9, 2018
2227ffa
add:数据库索引
Snailclimb Oct 9, 2018
1b3d6af
singleton的延迟初始化方式
Snailclimb Oct 11, 2018
689098f
singleton的延迟初始化方式
Snailclimb Oct 11, 2018
ae5bb01
阿里云服务
Snailclimb Oct 11, 2018
ff88ca2
Update README.md
Snailclimb Oct 11, 2018
9fd08b3
阿里云活动添加
Snailclimb Oct 11, 2018
f0aa076
SpringMVC 工作原理详解
Snailclimb Oct 11, 2018
a6c6aaa
add SpringMVC 工作原理详解.md
Snailclimb Oct 11, 2018
41f5755
修复 SpringMVC 工作原理详解 链接失效
Snailclimb Oct 11, 2018
8c05e22
Update SpringMVC 工作原理详解.md
Snailclimb Oct 11, 2018
8583d26
Merge pull request #34 from autumind/patch-1
Snailclimb Oct 12, 2018
386bac0
Update: 接口和抽象类的区别是什么
jun1st Oct 13, 2018
0b39a21
Update Java基础知识.md
jun1st Oct 13, 2018
e70aa7d
fix : 修复拼写错误
lewisbyte Oct 14, 2018
fa64796
Gitchat推荐:Java 程序员必备:并发知识系统总结
Snailclimb Oct 14, 2018
186af9e
Merge pull request #38 from qq1367212627/master
Snailclimb Oct 17, 2018
0df64ea
Merge pull request #37 from jun1st/patch-2
Snailclimb Oct 17, 2018
2d17ede
Merge pull request #36 from jun1st/patch-1
Snailclimb Oct 17, 2018
139350b
Update LinkedList.md
Nightingale07 Oct 18, 2018
651df42
Merge pull request #40 from Nightingale07/patch-1
Snailclimb Oct 19, 2018
29d2e7c
阿里云
Snailclimb Oct 20, 2018
ecce9b3
增加“秋招总结”
Snailclimb Oct 24, 2018
ab2c176
增加:“秋招总结”
Snailclimb Oct 24, 2018
fd50808
补充部分书籍
Snailclimb Oct 24, 2018
d3b8cb3
更新文章内容
Snailclimb Oct 26, 2018
d366ee5
欢迎订阅我的Java并发总结的 Gitchat
Snailclimb Oct 26, 2018
6a5f7d6
Update README.md
Snailclimb Oct 26, 2018
87ee3a1
增加思维导图
Snailclimb Oct 26, 2018
d200823
阿里云服务
Snailclimb Oct 28, 2018
3575fa2
阿里云
Snailclimb Oct 28, 2018
b28487e
阿里云双11最新活动
Snailclimb Oct 29, 2018
53feb9a
阿里云双11活动
Snailclimb Oct 29, 2018
ae1f5d1
阿里云双11活动
Snailclimb Oct 29, 2018
ae872d0
阿里云活动
Snailclimb Oct 29, 2018
8c5243b
Update README.md
Snailclimb Oct 29, 2018
32985c5
阿里云新人专属!
Snailclimb Oct 29, 2018
473a7a3
阿里云活动
Snailclimb Oct 29, 2018
f160d8e
Update README.md
Snailclimb Oct 29, 2018
db05139
Update README.md
Snailclimb Oct 29, 2018
f78642e
Update README.md
Snailclimb Oct 29, 2018
dd913a2
阿里云活动
Snailclimb Oct 30, 2018
3cbec50
Update README.md
Snailclimb Oct 30, 2018
ef86d09
Update README.md
Snailclimb Oct 30, 2018
bf6917c
Update README.md
Snailclimb Oct 30, 2018
97a468c
Update README.md
Snailclimb Oct 30, 2018
d7817fc
Update README.md
Snailclimb Oct 30, 2018
84889fc
Update README.md
Snailclimb Oct 30, 2018
80e4eb7
【强烈推荐】阿里云活动
Snailclimb Oct 30, 2018
aa9880a
Update README.md
Snailclimb Oct 30, 2018
f469735
Update README.md
Snailclimb Oct 30, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
347 changes: 347 additions & 0 deletions Java相关/ArrayList-Grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@

## 一 先从 ArrayList 的构造函数说起

**ArrayList有三种方式来初始化,构造方法源码如下:**

```java
/**
* 默认初始容量大小
*/
private static final int DEFAULT_CAPACITY = 10;


private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
*默认构造函数,使用初始容量10构造一个空列表(无参数构造)
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

/**
* 带初始容量参数的构造函数。(用户自己指定容量)
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {//初始容量大于0
//创建initialCapacity大小的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {//初始容量等于0
//创建空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {//初始容量小于0,抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}


/**
*构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回
*如果指定的集合为null,throws NullPointerException。
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}

```

细心的同学一定会发现 :**以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为10。** 下面在我们分析 ArrayList 扩容时会降到这一点内容!

## 二 一步一步分析 ArrayList 扩容机制

这里以无参构造函数创建的 ArrayList 为例分析

### 1. 先来看 `add` 方法

```java
/**
* 将指定的元素追加到此列表的末尾。
*/
public boolean add(E e) {
//添加元素之前,先调用ensureCapacityInternal方法
ensureCapacityInternal(size + 1); // Increments modCount!!
//这里看到ArrayList添加元素的实质就相当于为数组赋值
elementData[size++] = e;
return true;
}
```
### 2. 再来看看 `ensureCapacityInternal()` 方法

可以看到 `add` 方法 首先调用了`ensureCapacityInternal(size + 1)`

```java
//得到最小扩容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 获取默认的容量和传入参数的较大值
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}

ensureExplicitCapacity(minCapacity);
}
```
**当 要 add 进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity 为10。**

### 3. `ensureExplicitCapacity()` 方法

如果调用 `ensureCapacityInternal()` 方法就一定会进过(执行)这个方法,下面我们来研究一下这个方法的源码!

```java
//判断是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;

// overflow-conscious code
if (minCapacity - elementData.length > 0)
//调用grow方法进行扩容,调用此方法代表已经开始扩容了
grow(minCapacity);
}

```

我们来仔细分析一下:

- 当我们要 add 进第1个元素到 ArrayList 时,elementData.length 为0 (因为还是一个空的 list),因为执行了 `ensureCapacityInternal()` 方法 ,所以 minCapacity 此时为10。此时,`minCapacity - elementData.length > 0 `成立,所以会进入 `grow(minCapacity)` 方法。
- 当add第2个元素时,minCapacity 为2,此时e lementData.length(容量)在添加第一个元素后扩容成 10 了。此时,`minCapacity - elementData.length > 0 ` 不成立,所以不会进入 (执行)`grow(minCapacity)` 方法。
- 添加第3、4···到第10个元素时,依然不会执行grow方法,数组容量都为10。

直到添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。进入grow方法进行扩容。

### 4. `grow()` 方法

```java
/**
* 要分配的最大数组大小
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

/**
* ArrayList扩容的核心方法。
*/
private void grow(int minCapacity) {
// oldCapacity为旧容量,newCapacity为新容量
int oldCapacity = elementData.length;
//将oldCapacity 右移一位,其效果相当于oldCapacity /2,
//我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
int newCapacity = oldCapacity + (oldCapacity >> 1);
//然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,
//如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
```

**int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍!** 记清楚了!不是网上很多人说的 1.5 倍+1!

> ">>"(移位运算符):>>1 右移一位相当于除2,右移n位相当于除以 2 的 n 次方。这里 oldCapacity 明显右移了1位所以相当于oldCapacity /2。对于大数据的2进制运算,位移运算符比那些普通运算符的运算要快很多,因为程序仅仅移动一下而已,不去计算,这样提高了效率,节省了资源  

**我们再来通过例子探究一下`grow()` 方法 :**

- 当add第1个元素时,oldCapacity 为0,经比较后第一个if判断成立,newCapacity = minCapacity(为10)。但是第二个if判断不会成立,即newCapacity 不比 MAX_ARRAY_SIZE大,则不会进入 `hugeCapacity` 方法。数组容量为10,add方法中 return true,size增为1。
- 当add第11个元素进入grow方法时,newCapacity为15,比minCapacity(为11)大,第一个if判断不成立。新容量没有大于数组最大size,不会进入hugeCapacity方法。数组容量扩为15,add方法中return true,size增为11。
- 以此类推······

**这里补充一点比较重要,但是容易被忽视掉的知识点:**

- java 中的 `length `属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了 length 这个属性.
- java 中的 `length()` 方法是针对字符串说的,如果想看这个字符串的长度则用到 `length()` 这个方法.
- java 中的 `size()` 方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看!

### 5. `hugeCapacity()` 方法。

从上面 `grow()` 方法源码我们知道: 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。


```java
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//对minCapacity和MAX_ARRAY_SIZE进行比较
//若minCapacity大,将Integer.MAX_VALUE作为新数组的大小
//若MAX_ARRAY_SIZE大,将MAX_ARRAY_SIZE作为新数组的大小
//MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
```



## 三 `System.arraycopy()` 和 `Arrays.copyOf()`方法


阅读源码的话,我们就会发现 ArrayList 中大量调用了这两个方法。比如:我们上面讲的扩容操作以及`add(int index, E element)`、`toArray()` 等方法中都用到了该方法!


### 3.1 `System.arraycopy()` 方法

```java
/**
* 在此列表中的指定位置插入指定的元素。
*先调用 rangeCheckForAdd 对index进行界限检查;然后调用 ensureCapacityInternal 方法保证capacity足够大;
*再将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。
*/
public void add(int index, E element) {
rangeCheckForAdd(index);

ensureCapacityInternal(size + 1); // Increments modCount!!
//arraycopy()方法实现数组自己复制自己
//elementData:源数组;index:源数组中的起始位置;elementData:目标数组;index + 1:目标数组中的起始位置; size - index:要复制的数组元素的数量;
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
```

我们写一个简单的方法测试以下:

```java
public class ArraycopyTest {

public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = new int[10];
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
System.arraycopy(a, 2, a, 3, 3);
a[2]=99;
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
}

}
```

结果:

```
0 1 99 2 3 0 0 0 0 0
```

### 3.2 `Arrays.copyOf()`方法

```java
/**
以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。
*/
public Object[] toArray() {
//elementData:要复制的数组;size:要复制的长度
return Arrays.copyOf(elementData, size);
}
```

个人觉得使用 `Arrays.copyOf()`方法主要是为了给原有数组扩容,测试代码如下:

```java
public class ArrayscopyOfTest {

public static void main(String[] args) {
int[] a = new int[3];
a[0] = 0;
a[1] = 1;
a[2] = 2;
int[] b = Arrays.copyOf(a, 10);
System.out.println("b.length"+b.length);
}
}
```

结果:

```
10
```


### 3.3 两者联系和区别

**联系:**

看两者源代码可以发现 copyOf() 内部实际调用了 `System.arraycopy()` 方法

**区别:**

`arraycopy()` 需要目标数组,将原数组拷贝到你自己定义的数组里或者原数组,而且可以选择拷贝的起点和长度以及放入新数组中的位置 `copyOf()` 是系统自动在内部新建一个数组,并返回该数组。



## 四 `ensureCapacity`方法

ArrayList 源码中有一个 `ensureCapacity` 方法不知道大家注意到没有,这个方法 ArrayList 内部没有被调用过,所以很显然是提供给用户调用的,那么这个方法有什么作用呢?

```java
/**
如有必要,增加此 ArrayList 实例的容量,以确保它至少可以容纳由minimum capacity参数指定的元素数。
*
* @param minCapacity 所需的最小容量
*/
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;

if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}

```

**最好在 add 大量元素之前用 `ensureCapacity` 方法,以减少增量从新分配的次数**

我们通过下面的代码实际测试以下这个方法的效果:

```java
public class EnsureCapacityTest {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
final int N = 10000000;
long startTime = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
list.add(i);
}
long endTime = System.currentTimeMillis();
System.out.println("使用ensureCapacity方法前:"+(endTime - startTime));

list = new ArrayList<Object>();
long startTime1 = System.currentTimeMillis();
list.ensureCapacity(N);
for (int i = 0; i < N; i++) {
list.add(i);
}
long endTime1 = System.currentTimeMillis();
System.out.println("使用ensureCapacity方法后:"+(endTime1 - startTime1));
}
}
```

运行结果:

```
使用ensureCapacity方法前:4637
使用ensureCapacity方法后:241

```

通过运行结果,我们可以很明显的看出向 ArrayList 添加大量元素之前最好先使用`ensureCapacity` 方法,以减少增量从新分配的次数
2 changes: 1 addition & 1 deletion Java相关/ArrayList.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

  ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

  ArrayList 实现了**RandmoAccess 接口**,即提供了随机访问功能。RandmoAccess 是 Java 中用来被 List 实现,为 List 提供**快速访问功能**的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。
  ArrayList 实现了**RandomAccess 接口**,即提供了随机访问功能。RandomAccess 是 Java 中用来被 List 实现,为 List 提供**快速访问功能**的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。

  ArrayList 实现了**Cloneable 接口**,即覆盖了函数 clone(),**能被克隆**

Expand Down
7 changes: 7 additions & 0 deletions Java相关/J2EE基础知识.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ Servlet接口定义了5个方法,其中**前三个方法与Servlet生命周期
参考:《javaweb整合开发王者归来》P81

## get和post请求的区别

> 网上也有文章说:get和post请求实际上是没有区别,大家可以自行查询相关文章!我下面给出的只是一种常见的答案。

①get请求用来从服务器上获得资源,而post是用来向服务器提交数据;

②get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?"连接,而各个变量之间使用"&"连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;
Expand All @@ -78,6 +81,10 @@ Servlet接口定义了5个方法,其中**前三个方法与Servlet生命周期

补充:GET方式提交表单的典型应用是搜索引擎。GET方式就是被设计为查询用的。

还有另外一种回答。推荐大家看一下:

- https://www.zhihu.com/question/28586791
- https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4#rd

## 什么情况下调用doGet()和doPost()
Form标签里的method的属性为get时调用doGet(),为post时调用doPost()。
Expand Down
Loading