Skip to content

Commit f25a32d

Browse files
committed
[refractor]移除集合部分内容,单独整理
1 parent e69859b commit f25a32d

File tree

1 file changed

+9
-268
lines changed

1 file changed

+9
-268
lines changed
Lines changed: 9 additions & 268 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,4 @@
1-
<!-- TOC -->
2-
3-
- [1. 基础](#1-基础)
4-
- [1.1. 正确使用 equals 方法](#11-正确使用-equals-方法)
5-
- [1.2. 整型包装类值的比较](#12-整型包装类值的比较)
6-
- [1.3. BigDecimal](#13-bigdecimal)
7-
- [1.3.1. BigDecimal 的用处](#131-bigdecimal-的用处)
8-
- [1.3.2. BigDecimal 的大小比较](#132-bigdecimal-的大小比较)
9-
- [1.3.3. BigDecimal 保留几位小数](#133-bigdecimal-保留几位小数)
10-
- [1.3.4. BigDecimal 的使用注意事项](#134-bigdecimal-的使用注意事项)
11-
- [1.3.5. 总结](#135-总结)
12-
- [1.4. 基本数据类型与包装数据类型的使用标准](#14-基本数据类型与包装数据类型的使用标准)
13-
- [2. 集合](#_2-集合)
14-
- [2.1. Arrays.asList()使用指南](#21-arraysaslist使用指南)
15-
- [2.1.1. 简介](#211-简介)
16-
- [2.1.2. 《阿里巴巴Java 开发手册》对其的描述](#212-阿里巴巴java-开发手册对其的描述)
17-
- [2.1.3. 使用时的注意事项总结](#213-使用时的注意事项总结)
18-
- [2.1.4. 如何正确的将数组转换为ArrayList?](#214-如何正确的将数组转换为arraylist)
19-
- [2.2. Collection.toArray()方法使用的坑&如何反转数组](#22-collectiontoarray方法使用的坑如何反转数组)
20-
- [2.3. 不要在 foreach 循环里进行元素的 remove/add 操作](#23-不要在-foreach-循环里进行元素的-removeadd-操作)
21-
22-
<!-- /TOC -->
23-
24-
# 1. 基础
25-
26-
## 1.1. 正确使用 equals 方法
1+
## 正确使用 equals 方法
272

283
Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
294

@@ -65,7 +40,7 @@ Reference:[Java中equals方法造成空指针异常的原因及解决方案](htt
6540
- 可以使用 == 或者 != 操作来比较null值,但是不能使用其他算法或者逻辑操作。在Java中`null == null`将返回true。
6641
- 不能使用一个值为null的引用类型变量来调用非静态方法,否则会抛出异常
6742

68-
## 1.2. 整型包装类值的比较
43+
## 整型包装类值的比较
6944

7045
所有整型包装类对象值的比较必须使用equals方法。
7146

@@ -85,9 +60,9 @@ System.out.println(i1==i2);//false
8560

8661
**注意:** 如果你的IDE(IDEA/Eclipse)上安装了阿里巴巴的p3c插件,这个插件如果检测到你用 ==的话会报错提示,推荐安装一个这个插件,很不错。
8762

88-
## 1.3. BigDecimal
63+
## BigDecimal
8964

90-
### 1.3.1. BigDecimal 的用处
65+
### BigDecimal 的用处
9166

9267
《阿里巴巴Java开发手册》中提到:**浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。** 具体原理和浮点数的编码方式有关,这里就不多提了,我们下面直接上实例:
9368

@@ -113,7 +88,7 @@ System.out.println(y); /* 0.1 */
11388
System.out.println(Objects.equals(x, y)); /* true */
11489
```
11590

116-
### 1.3.2. BigDecimal 的大小比较
91+
### BigDecimal 的大小比较
11792

11893
`a.compareTo(b)` : 返回 -1 表示 `a` 小于 `b`,0 表示 `a` 等于 `b` , 1表示 `a` 大于 `b`
11994

@@ -122,7 +97,7 @@ BigDecimal a = new BigDecimal("1.0");
12297
BigDecimal b = new BigDecimal("0.9");
12398
System.out.println(a.compareTo(b));// 1
12499
```
125-
### 1.3.3. BigDecimal 保留几位小数
100+
### BigDecimal 保留几位小数
126101

127102
通过 `setScale`方法设置保留几位小数以及保留规则。保留规则有挺多种,不需要记,IDEA会提示。
128103

@@ -132,19 +107,19 @@ BigDecimal n = m.setScale(3,BigDecimal.ROUND_HALF_DOWN);
132107
System.out.println(n);// 1.255
133108
```
134109

135-
### 1.3.4. BigDecimal 的使用注意事项
110+
### BigDecimal 的使用注意事项
136111

137112
注意:我们在使用BigDecimal时,为了防止精度丢失,推荐使用它的 **BigDecimal(String)** 构造方法来创建对象。《阿里巴巴Java开发手册》对这部分内容也有提到如下图所示。
138113

139114
![《阿里巴巴Java开发手册》对这部分BigDecimal的描述](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/BigDecimal.png)
140115

141-
### 1.3.5. 总结
116+
### 总结
142117

143118
BigDecimal 主要用来操作(大)浮点数,BigInteger 主要用来操作大整数(超过 long 类型)。
144119

145120
BigDecimal 的实现利用到了 BigInteger, 所不同的是 BigDecimal 加入了小数位的概念
146121

147-
## 1.4. 基本数据类型与包装数据类型的使用标准
122+
## 基本数据类型与包装数据类型的使用标准
148123

149124
Reference:《阿里巴巴Java开发手册》
150125

@@ -160,237 +135,3 @@ Reference:《阿里巴巴Java开发手册》
160135

161136
**反例** : 比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。
162137

163-
# 2. 集合
164-
165-
## 2.1. Arrays.asList()使用指南
166-
167-
最近使用`Arrays.asList()`遇到了一些坑,然后在网上看到这篇文章:[Java Array to List Examples](http://javadevnotes.com/java-array-to-list-examples) 感觉挺不错的,但是还不是特别全面。所以,自己对于这块小知识点进行了简单的总结。
168-
169-
### 2.1.1. 简介
170-
171-
`Arrays.asList()`在平时开发中还是比较常见的,我们可以使用它将一个数组转换为一个List集合。
172-
173-
```java
174-
String[] myArray = {"Apple", "Banana", "Orange"};
175-
List<String> myList = Arrays.asList(myArray);
176-
//上面两个语句等价于下面一条语句
177-
List<String> myList = Arrays.asList("Apple","Banana", "Orange");
178-
```
179-
180-
JDK 源码对于这个方法的说明:
181-
182-
```java
183-
/**
184-
*返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁,
185-
* 与 Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。
186-
*/
187-
public static <T> List<T> asList(T... a) {
188-
return new ArrayList<>(a);
189-
}
190-
```
191-
192-
### 2.1.2. 《阿里巴巴Java 开发手册》对其的描述
193-
194-
`Arrays.asList()`将数组转换为集合后,底层其实还是数组,《阿里巴巴Java 开发手册》对于这个方法有如下描述:
195-
196-
![阿里巴巴Java开发手-Arrays.asList()方法](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/阿里巴巴Java开发手-Arrays.asList()方法.png)
197-
198-
### 2.1.3. 使用时的注意事项总结
199-
200-
**传递的数组必须是对象数组,而不是基本类型。**
201-
202-
`Arrays.asList()`是泛型方法,传入的对象必须是对象数组。
203-
204-
```java
205-
int[] myArray = {1, 2, 3};
206-
List myList = Arrays.asList(myArray);
207-
System.out.println(myList.size());//1
208-
System.out.println(myList.get(0));//数组地址值
209-
System.out.println(myList.get(1));//报错:ArrayIndexOutOfBoundsException
210-
int[] array = (int[]) myList.get(0);
211-
System.out.println(array[0]);//1
212-
```
213-
当传入一个原生数据类型数组时,`Arrays.asList()` 的真正得到的参数就不是数组中的元素,而是数组对象本身!此时List 的唯一元素就是这个数组,这也就解释了上面的代码。
214-
215-
我们使用包装类型数组就可以解决这个问题。
216-
217-
```java
218-
Integer[] myArray = {1, 2, 3};
219-
```
220-
221-
**使用集合的修改方法:`add()``remove()``clear()`会抛出异常。**
222-
223-
```java
224-
List myList = Arrays.asList(1, 2, 3);
225-
myList.add(4);//运行时报错:UnsupportedOperationException
226-
myList.remove(1);//运行时报错:UnsupportedOperationException
227-
myList.clear();//运行时报错:UnsupportedOperationException
228-
```
229-
230-
`Arrays.asList()` 方法返回的并不是 `java.util.ArrayList` ,而是 `java.util.Arrays` 的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。
231-
232-
```java
233-
List myList = Arrays.asList(1, 2, 3);
234-
System.out.println(myList.getClass());//class java.util.Arrays$ArrayList
235-
```
236-
237-
下图是`java.util.Arrays$ArrayList`的简易源码,我们可以看到这个类重写的方法有哪些。
238-
239-
```java
240-
private static class ArrayList<E> extends AbstractList<E>
241-
implements RandomAccess, java.io.Serializable
242-
{
243-
...
244-
245-
@Override
246-
public E get(int index) {
247-
...
248-
}
249-
250-
@Override
251-
public E set(int index, E element) {
252-
...
253-
}
254-
255-
@Override
256-
public int indexOf(Object o) {
257-
...
258-
}
259-
260-
@Override
261-
public boolean contains(Object o) {
262-
...
263-
}
264-
265-
@Override
266-
public void forEach(Consumer<? super E> action) {
267-
...
268-
}
269-
270-
@Override
271-
public void replaceAll(UnaryOperator<E> operator) {
272-
...
273-
}
274-
275-
@Override
276-
public void sort(Comparator<? super E> c) {
277-
...
278-
}
279-
}
280-
```
281-
282-
我们再看一下`java.util.AbstractList``remove()`方法,这样我们就明白为啥会抛出`UnsupportedOperationException`
283-
284-
```java
285-
public E remove(int index) {
286-
throw new UnsupportedOperationException();
287-
}
288-
```
289-
290-
### 2.1.4. 如何正确的将数组转换为ArrayList?
291-
292-
stackoverflow:https://dwz.cn/vcBkTiTW
293-
294-
**1. 自己动手实现(教育目的)**
295-
296-
```java
297-
//JDK1.5+
298-
static <T> List<T> arrayToList(final T[] array) {
299-
final List<T> l = new ArrayList<T>(array.length);
300-
301-
for (final T s : array) {
302-
l.add(s);
303-
}
304-
return l;
305-
}
306-
```
307-
308-
```java
309-
Integer [] myArray = { 1, 2, 3 };
310-
System.out.println(arrayToList(myArray).getClass());//class java.util.ArrayList
311-
```
312-
313-
**2. 最简便的方法(推荐)**
314-
315-
```java
316-
List list = new ArrayList<>(Arrays.asList("a", "b", "c"))
317-
```
318-
319-
**3. 使用 Java8 的Stream(推荐)**
320-
321-
```java
322-
Integer [] myArray = { 1, 2, 3 };
323-
List myList = Arrays.stream(myArray).collect(Collectors.toList());
324-
//基本类型也可以实现转换(依赖boxed的装箱操作)
325-
int [] myArray2 = { 1, 2, 3 };
326-
List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList());
327-
```
328-
329-
**4. 使用 Guava(推荐)**
330-
331-
对于不可变集合,你可以使用[`ImmutableList`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java)类及其[`of()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java#L101)[`copyOf()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/ImmutableList.java#L225)工厂方法:(参数不能为空)
332-
333-
```java
334-
List<String> il = ImmutableList.of("string", "elements"); // from varargs
335-
List<String> il = ImmutableList.copyOf(aStringArray); // from array
336-
```
337-
对于可变集合,你可以使用[`Lists`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java)类及其[`newArrayList()`](https://github.com/google/guava/blob/master/guava/src/com/google/common/collect/Lists.java#L87)工厂方法:
338-
339-
```java
340-
List<String> l1 = Lists.newArrayList(anotherListOrCollection); // from collection
341-
List<String> l2 = Lists.newArrayList(aStringArray); // from array
342-
List<String> l3 = Lists.newArrayList("or", "string", "elements"); // from varargs
343-
```
344-
345-
**5. 使用 Apache Commons Collections**
346-
347-
```java
348-
List<String> list = new ArrayList<String>();
349-
CollectionUtils.addAll(list, str);
350-
```
351-
352-
**6. 使用 Java9 的 `List.of()`方法**
353-
``` java
354-
Integer[] array = {1, 2, 3};
355-
List<Integer> list = List.of(array);
356-
System.out.println(list); /* [1, 2, 3] */
357-
/* 不支持基本数据类型 */
358-
```
359-
360-
## 2.2. Collection.toArray()方法使用的坑&如何反转数组
361-
362-
该方法是一个泛型方法:`<T> T[] toArray(T[] a);` 如果`toArray`方法中没有传递任何参数的话返回的是`Object`类型数组。
363-
364-
```java
365-
String [] s= new String[]{
366-
"dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A"
367-
};
368-
List<String> list = Arrays.asList(s);
369-
Collections.reverse(list);
370-
s=list.toArray(new String[0]);//没有指定类型的话会报错
371-
```
372-
373-
由于JVM优化,`new String[0]`作为`Collection.toArray()`方法的参数现在使用更好,`new String[0]`就是起一个模板的作用,指定了返回数组的类型,0是为了节省空间,因为它只是为了说明返回的类型。详见:<https://shipilev.net/blog/2016/arrays-wisdom-ancients/>
374-
375-
## 2.3. 不要在 foreach 循环里进行元素的 remove/add 操作
376-
377-
如果要进行`remove`操作,可以调用迭代器的 `remove `方法而不是集合类的 remove 方法。因为如果列表在任何时间从结构上修改创建迭代器之后,以任何方式除非通过迭代器自身`remove/add`方法,迭代器都将抛出一个`ConcurrentModificationException`,这就是单线程状态下产生的 **fail-fast 机制**
378-
379-
> **fail-fast 机制** :多个线程对 fail-fast 集合进行修改的时候,可能会抛出ConcurrentModificationException,单线程下也会出现这种情况,上面已经提到过。
380-
381-
Java8开始,可以使用`Collection#removeIf()`方法删除满足特定条件的元素,如
382-
``` java
383-
List<Integer> list = new ArrayList<>();
384-
for (int i = 1; i <= 10; ++i) {
385-
list.add(i);
386-
}
387-
list.removeIf(filter -> filter % 2 == 0); /* 删除list中的所有偶数 */
388-
System.out.println(list); /* [1, 3, 5, 7, 9] */
389-
```
390-
391-
`java.util`包下面的所有的集合类都是fail-fast的,而`java.util.concurrent`包下面的所有的类都是fail-safe的。
392-
393-
![不要在 foreach 循环里进行元素的 remove/add 操作](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019/7/foreach-remove:add.png)
394-
395-
396-

0 commit comments

Comments
 (0)