1、Array类
package zhh.chapter13.array;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @author longbownice
* @version 1.0
*
* 自定义sort原理
*/
public class Array_ {
public static void main(String[] args) {
//1、toString
//以字符串形式打印数组,用[]包起来
Integer[] integers = {1, 20, 90};
//遍历数组
//1 20 90
for(int i = 0; i < integers.length; i++) {
System.out.print(integers[i]+" ");
}
//直接使用 Arrays.toString 方法,显示数组
//[1, 20, 90]
System.out.println(Arrays.toString(integers));
//2、演示 sort 方法的使用
//因为数组是引用类型,所以通过 sort 排序后,会直接影响到 实参 arr
//sort 重载的,也可以通过传入一个接口 Comparator 实现定制排序
//调用 定制排序 时,传入两个参数
// (1) 排序的数组 arr
// (2) 实现了 Comparator 接口的匿名内部类 , 要求实现 compare 方法
// 这里体现了接口编程的方式 , 看看源码,就明白
// 源码分析
//(1) Arrays.sort(arr, new Comparator())
//(2) 最终到 TimSort 类的 private static <T> void binarySort
// (T[] a, int lo, int hi, int start,Comparator<? super T> c)
//(3) 执行到 binarySort 方法的代码, 会根据动态绑定机制 c.compare()执行我们传入的
// 匿名内部类的 compare (),这里用到了一点二叉排序(折半插入排序)
// while (left < right) {
// int mid = (left + right) >>> 1;
(待插入的数,有序序列的中间值)
// if (c.compare(pivot, a[mid]) < 0)
//当return(pivot-a[mid])时,即待插入的数小于中间点时
//right左移,最后找着的插入位置一定在左边,即较小的数最后插入到左边
//类似于冒泡排序(从右边开始)中if([j]<[j-1]) {[j]左移}
//即实现了从小到大排序
//总之,前-后升序,后-前降序(且不改变原来顺序,不是left <= right)
//反之,从大到小
// right = mid;
// else
// left = mid + 1;
// }
//(4) new Comparator() {
// @Override
// public int compare(Object o1, Object o2) {
// Integer i1 = (Integer) o1;
// Integer i2 = (Integer) o2;
// return i2 - i1;
// }
// }
//(5) public int compare(Object o1, Object o2) 返回的值>0 还是 <0
// 会影响整个排序结果, 这就充分体现了 接口编程+动态绑定+匿名内部类的综合使用
// 将来的底层框架和源码的使用方式,会非常常见
// 默认排序方法
//Arrays.sort(arr);
//定制排序
Integer arr[] = {1, -1, 7, 0, 89};
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i2 - i1;
}
});
System.out.println("===排序后===");
System.out.println(Arrays.toString(arr));
//3、binarySearch二分查找(数组有序,返回下标)
//如果数组中不存在该元素,就返回 return -(low + 1),low是这个数如果存在所在的位置
Integer[] arr1 = {1, 2, 90, 123, 567};
int index = Arrays.binarySearch(arr1, 567);
System.out.println("index=" + index);//4
System.out.println(Arrays.binarySearch(arr1,999));//-(5+1)=-6
//4、copyOf 数组元素的复制
// 老韩解读
//1. 从 arr 数组中,拷贝 前n 个元素到 newArr 数组中
//2. 如果拷贝的长度 > arr.length 就在新数组的后面 增加 null
//3. 如果拷贝长度 < 0 就抛出异常 NegativeArraySizeException
//4. 该方法的底层使用的是 System.arraycopy()
Integer[] newArr = Arrays.copyOf(arr1, 3);//[1, 2, 90]
System.out.println(Arrays.toString(newArr));//[1, 2, 90]
newArr = Arrays.copyOf(arr1, 7);
System.out.println(Arrays.toString(newArr));//[1, 2, 90, 123, 567, null, null]
//ill 数组元素的填充
//1. 使用 val 去填充 num 数组,可以理解成是替换原理的元素
Integer[] num = new Integer[]{9,3,2};
System.out.println(Arrays.toString(num));//[9, 3, 2]
Arrays.fill(num, 99);
System.out.println("==num 数组填充后==");
System.out.println(Arrays.toString(num));//[99, 99, 99]
//equals
// 比较两个数组元素内容是否完全一致
//1. 如果 arr 和 arr2 数组的元素一样,则返回 true;
//2. 如果不是完全一样,就返回false
Integer[] arr2 = {1, 2, 90, 123};
boolean equals = Arrays.equals(arr, arr2);
System.out.println("equals=" + equals);//false
//asList 将一组值
// 转换成list
//老韩解读
//1. asList 方法,会将 (2,3,4,5,6,1)数据转成一个 List 集合
//2. 返回的 asList 编译类型 List(接口)
//3. asList 运行类型 java.util.Arrays#ArrayList, 是 Arrays 类的
// 静态内部类 private static class ArrayList<E> extends AbstractList<E>
// implements RandomAccess, java.io.Serializable
List asList = Arrays.asList(2,3,4,5,6,1);
System.out.println("asList=" + asList);
System.out.println("asList 的运行类型" + asList.getClass());
}
}
自定义sort应用
package zhh.chapter13.array;
import java.util.Arrays;
import java.util.Comparator;
/**
* @author longbownice
* @version 1.0
*
* 自定义sort应用
*
*/
public class ArraySort {
public static void main(String[] args) {
Book[] book=new Book[4];
book[0]=new Book("红楼梦",100);
book[1]=new Book("金瓶梅新",90);
book[2]=new Book("青年文摘20年",5);
book[3]=new Book("java从入门到放弃",300);
//price从小到大
Arrays.sort(book, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
//如果价格是double
//也可以用double接受,根据相减结果用ifelse返回1或-1;
int d1=o1.getPrice();
int d2=o2.getPrice();
return d1-d2;
}
});
for(Book b:book){
System.out.println(b);
}
System.out.println();
Arrays.sort(book, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
int d1=o1.getPrice();
int d2=o2.getPrice();
return d2-d1;
}
});
for(Book b:book){
System.out.println(b);
}
System.out.println();
Arrays.sort(book, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
int d1=o1.getName().length();
int d2=o2.getName().length();
return d2-d1;
}
});
for(Book b:book){
System.out.println(b);
}
// print
// Book{name='青年文摘20年', price=5}
// Book{name='金瓶梅新', price=90}
// Book{name='红楼梦', price=100}
// Book{name='java从入门到放弃', price=300}
//
// Book{name='java从入门到放弃', price=300}
// Book{name='红楼梦', price=100}
// Book{name='金瓶梅新', price=90}
// Book{name='青年文摘20年', price=5}
//
// Book{name='java从入门到放弃', price=300}
// Book{name='青年文摘20年', price=5}
// Book{name='金瓶梅新', price=90}
// Book{name='红楼梦', price=100}
}
}
class Book{
private String name;
private int price;
public Book(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
2、System类
package zhh.chapter13.system;
import java.util.Arrays;
/**
* @author longbownice
* @version 1.0
*
* System 类常见方法和案例
*/
public class System_ {
public static void main(String[] args) {
//1、exit 退出当前程序
// exit(0) 表示程序退出
// 0 表示一个状态 , 正常的状态
System.out.println("ok1");
// System.exit(0);//执行的话就结束进程了,下面不再执行
System.out.println("ok2");
//2、arraycopy :复制数组元素,比较适合底层调用,
// 一般使用 Arrays.copyOf 完成复制数组
// System.arraycopy(src, 0, dest, 0, src.length);
// src 源数组
// * @param src the source array.
// srcPos: 从源数组的哪个索引位置开始拷贝
// * @param srcPos starting position in the source array.
// dest : 目标数组,即把源数组的数据拷贝到哪个数组
// * @param dest the destination array.
// destPos: 把源数组的数据拷贝到 目标数组的哪个索引
// * @param destPos starting position in the destination data.
// length: 从源数组拷贝多少个数据到目标数组
// * @param length the number of array elements to be copied.
int[] src={1,2,3};
int[] dest = new int[3];// dest 当前是 {0,0,0}
System.arraycopy(src, 0, dest, 0, src.length);
System.out.println("dest=" + Arrays.toString(dest));//[1, 2, 3]
System.arraycopy(src, 1, dest, 0, 2);
System.out.println("dest=" + Arrays.toString(dest));//[2, 3, 3]
//3、currentTimeMillens:返回当前时间距离 1970-1-1 的毫秒数
System.out.println(System.currentTimeMillis());//1700745243726
//4、垃圾回收,以后再详细了解
System.gc();
}
}
3、BigInteger 和 BigDecimal 类
应用场景:
1)Biglnteger适合保存比较大的整型
2) BigDecimal适合保存精度更高的浮点型(小数)
- add 加
- subtract减
- multiply乘
- divide除
package zhh.chapter13.bigdate;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author longbownice
* @version 1.0
*/
public class BigDate {
public static void main(String[] args) {
BigInteger bigInteger = new BigInteger("99999999999955555555558888888");
BigInteger bigInteger1 = new BigInteger("2");
BigInteger add = bigInteger.add(bigInteger1);
System.out.println("add: "+add);
BigInteger subtract = bigInteger.subtract(bigInteger1);
System.out.println("subtract: "+subtract);
BigInteger multiply = bigInteger.multiply(bigInteger1);
System.out.println("multiply: "+multiply);
BigInteger divide = bigInteger.divide(bigInteger1);
System.out.println("divide: "+divide);
// print
// add: 99999999999955555555558888890
// subtract: 99999999999955555555558888886
// multiply: 199999999999911111111117777776
// divide: 49999999999977777777779444444
BigDecimal bigDecimal = new BigDecimal("9.9999999999999999999999999999");
BigDecimal bigDecimal1 = new BigDecimal("1.22");
BigDecimal add1 = bigDecimal.add(bigDecimal1);
System.out.println("add1: "+add1);
BigDecimal subtract1 = bigDecimal.subtract(bigDecimal1);
System.out.println("subtract1: "+subtract1);
BigDecimal multiply1 = bigDecimal.multiply(bigDecimal1);
System.out.println("multiply1: "+multiply1);
//这里不指定BigDecimal.ROUND_CEILING(保留分子精度),会抛出异常ArithmeticException
// BigDecimal divide1 = bigDecimal.divide(bigDecimal1);
// System.out.println("divide1: "+divide1);
BigDecimal divide2 = bigDecimal.divide(bigDecimal1,BigDecimal.ROUND_CEILING);
System.out.println("divide2: "+divide2);
// print
// add1: 11.2199999999999999999999999999
// subtract1: 8.7799999999999999999999999999
// multiply1: 12.199999999999999999999999999878
// divide2: 8.1967213114754098360655737705
}
}
4、日期类
package zhh.chapter13.date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
/**
* @author longbownice
* @version 1.0
*
* 第一代日期
* Date类使用
*/
public class Date_ {
public static void main(String[] args) throws ParseException {
Date date = new Date();
System.out.println(date);//Fri Nov 24 10:01:15 CST 2023
//从1970-01-01 00:00:00经过3600000毫秒(1小时)的时间,在加上8(相差八个时区)
Date date1 = new Date(3600000);
System.out.println(date1);//Thu Jan 01 09:00:00 CST 1970
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
System.out.println(sdf.format(date));//2023-11-24 10-04-32
//符合格式日期的字符串可以转换成date型日期
String s="2030-10-22 18-20-10";
//有可能抛出异常ParseException
Date parse = sdf.parse(s);
System.out.println(sdf.format(parse));//2023-11-24T02:42:38.338Z 默认时区
//时间戳和日期转换
Instant now = Instant.now();
System.out.println(now);
Date from = Date.from(now);
System.out.println(now.getNano());//324000000
System.out.println(sdf.format(date));//2023-11-24 10-42-38
Instant instant = from.toInstant();
System.out.println(instant);//2023-11-24T02:42:38.338Z
//可以通过Instance实现LocalDateTime和Date的转换
// 使用ZoneId定义时区(可以根据需要选择不同的时区)
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
LocalDateTime localDateTime = now.atZone(zoneId).toLocalDateTime();
System.out.println(localDateTime);//2023-11-24T11:09:24.854
}
}
package zhh.chapter13.date;
import java.util.Calendar;
/**
* @author longbownice
* @version 1.0
*
* 第二代日期
* Calendar类使用
*/
public class Calendar_ {
public static void main(String[] args) {
//构造器protected
//可以通过 getInstance() 来获取实例
Calendar instance = Calendar.getInstance();
System.out.println(instance);//打印很多相关字段
//如果我们需要按照 24 小时进制来获取时间, Calendar.HOUR ==改成=> Calendar.HOUR_OF_DAY
// 这里为什么要 + 1, 因为 Calendar 返回月时候,是按照 0 开始编号
//Calender 没有专门的格式化方法,所以需要程序员自己来组合显示
System.out.println(instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1) + "-"
+ instance.get(Calendar.DATE) + " " + instance.get(Calendar.HOUR_OF_DAY) + "-"
+ instance.get(Calendar.MINUTE) + "-" + instance.get(Calendar.SECOND));
//2023-11-24 10-25-24
}
}
package zhh.chapter13.date;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author longbownice
* @version 1.0
*
* 第三代日期
*
* 前面两代日期类的不足分析
* JDK 1.0中包含了一个java.util.Date类,
* 但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar也存在问题是:
*
* 1)可变性:像曰期和时间这样的类应该是不可变的。
* 2)偏移性:Date中的年份是从1900开始的,而月份都从0开始。
* 3)格式化:格式化只对Date有用,Calendar则不行。
* 4)此外,它们也不是线程安全的;不能处理闰秒等(每隔2天,多出1s)。
*/
public class LocalDateTime_ {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2023-11-24T10:35:19.793
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dtf.format(ldt));//2023-11-24 10:35:19
System.out.println(ldt.getMonth());//英文月份 NOVEMBER
System.out.println(ldt.getYear()+"-"+ldt.getMonthValue()+"-"+ldt.getDayOfMonth()+" "
+ldt.getHour()+":"+ldt.getMinute()+":"+ldt.getSecond());
//2023-11-24 10:35:19
//提供 plus 和 minus 方法可以对当前时间进行加或者减
LocalDateTime localDateTime = ldt.plusDays(900);
LocalDateTime localDateTime1 = ldt.plusHours(900);
LocalDateTime localDateTime2 = ldt.minusDays(900);
LocalDateTime localDateTime3 = ldt.minusMonths(900);
System.out.println(dtf.format(localDateTime));//2026-05-12 10:38:51
System.out.println(dtf.format(localDateTime1));//2023-12-31 22:38:51
System.out.println(dtf.format(localDateTime2));//2021-06-07 10:38:51
System.out.println(dtf.format(localDateTime3));//1948-11-24 10:38:51
LocalDate localDate =LocalDate.now();//获取年月日
System.out.println(localDate);//2023-11-24
LocalTime now = LocalTime.now();//获取时分秒
System.out.println(now);//11:52:09.879
}
}
4、集合
.集合主要是两组(单列集合 , 双列集合)
Collection 接口有两个重要的子接口 List、Set , 他们的实现子类都是单列集合
Map 接口的实现子类 是双列集合,存放的 K-V
4.1Collection 接口和常用方法
- collection实现子类可以存放多个元素,每个元素可以是Object
- 有些Collection的实现类,可以存放重复的元素,有些不可以
- 有些Collection的实现类,有些是有序的(List),有些不是有序(Set)
- Collection接口没有直接的实现子类,是通过它的子接口Set 和 List来实现的
package zhh.chapter14.collection_;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @author longbownice
* @version 1.0
*
* Collection接口常用方法
* 以ArrayList为例
*/
public class Collection_ {
@SuppressWarnings("all")
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
ArrayList arrayList1 = new ArrayList();
arrayList1.add("zhansan");
arrayList1.add("zhansan");
arrayList1.add("lisi");
arrayList1.add("wangsan");
arrayList1.add("hzaosan");
//增
arrayList.add(10);//相当于new Integer(10)
arrayList.add("jack");
arrayList.add(true);
arrayList.add(5.99);
arrayList.add(arrayList1);
//增多个
arrayList.addAll(arrayList1);
System.out.println(arrayList);
//[10, jack, true, 5.99, [zhansan, zhansan, lisi, wangsan, hzaosan], zhansan, zhansan, lisi, wangsan, hzaosan]
//删
arrayList.remove((Integer)10);//或者(0)
arrayList.remove("jack");
arrayList.remove(1);
arrayList.removeAll(arrayList1);
System.out.println(arrayList);
//[true, [zhansan, zhansan, lisi, wangsan, hzaosan]]
//改
arrayList.set(0,5.10);
System.out.println(arrayList);
//[5.1, [zhansan, zhansan, lisi, wangsan, hzaosan]]
//查
System.out.println(arrayList.contains(true));//T
System.out.println(arrayList.containsAll(arrayList1));//F
System.out.println(arrayList.size());//2
arrayList.clear();
System.out.println(arrayList.isEmpty());//T
ArrayList arrayList2 = new ArrayList();
arrayList2.add(new Dog("阿拉斯加",6));
arrayList2.add(new Dog("拉布拉多",3));
arrayList2.add(new Dog("哈士奇",7));
arrayList2.add(new Dog("中华田园犬",5));
//迭代器遍历(实现自Iterable)
//快捷键itit
//Ctrl+j显示快捷键的快捷键
Iterator iterator = arrayList2.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();//执行过next()后,指向下一个
System.out.println(next);
}
//Dog{name='阿拉斯加', age=6}
//Dog{name='拉布拉多', age=3}
//Dog{name='哈士奇', age=7}
//Dog{name='中华田园犬', age=5}
//遍历一次后,iterator指向最后一个元素
//如果希望再次遍历,重置
Iterator iterator1 = arrayList2.iterator();
while (iterator1.hasNext()) {
Object next = iterator1.next();
System.out.println(next);
}
//增强for循环遍历
//底层还是iterator,相当于简化版iterator
//只能遍历数组和集合
for (Object o :arrayList2) {
System.out.println(o);
}
//Dog{name='阿拉斯加', age=6}
//Dog{name='拉布拉多', age=3}
//Dog{name='哈士奇', age=7}
//Dog{name='中华田园犬', age=5}
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4.2、ArrayList底层源码
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
注意事项
- permits all elements, including null ,ArrayList 可以加入nul,并且多个
- ArrayList是由数组来实现数据存储的
- ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高,无synchronized)。在多线程情况下,不建议使用ArrayList
源码分析
- ArrayList中维护了一个Object类型的数组elementData.
- transient Objectl] elementData; //transient表示瞬间,短暂的,表示该属性不会被序列号
- 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
- 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
4.3 Vector
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
和ArrayList几乎一样,只不过Vector是线程安全(synchronize)的。
底层也是对象数组,protected Object element[]
4.4 LinkedList 底层结构
- LinkedList底层实现了双向链表和双端队列特点
- 可以添加任意元素(元素可以重复),包括null
- 线程不安全,没有实现同步
- LinkedList底层维护了一个双向链表.
- LinkedList中维护了两个属性first和last分别指向首节点和尾节点
- 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表.
- 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
CRUD
package zhh.chapter14.list;
import java.util.LinkedList;
/**
* @author longbownice
* @version 1.0
*/
public class LinkListCRUD {
@SuppressWarnings("all")
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
//create
/* 1. LinkedList linkedList = new LinkedList();
public LinkedList() {}
2. 这时 linkeList 的属性 first = null last = null
3. 执行 添加
public boolean add(E e) {
linkLast(e);
return true;
}
4.将新的结点,加入到双向链表的最后
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
*/
linkedList.add(11);
linkedList.add(22);
linkedList.add(11);
linkedList.add(44);
linkedList.add(55);
linkedList.add(66);
System.out.println(linkedList);
//delete
/*
源码 linkedList.remove(); // 这里默认删除的是第一个结点
1. 执行 removeFirst
public E remove() {
return removeFirst();
}
2. 执行removeFirst()
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
*/
/* remove(Object o)
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
//从这里可以看出按对象删除遇到重名时,先删除前面的
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
*/
linkedList.remove((Object)11);
linkedList.remove((Object)11);
linkedList.remove(2);
linkedList.remove();//删除第一个
System.out.println(linkedList);
//update
linkedList.set(1,999);
System.out.println(linkedList);
//retrieve
System.out.println(linkedList.get(0));
System.out.println(linkedList);
System.out.println(linkedList.contains(999));
// print
// [11, 22, 11, 44, 55, 66]
// [44, 66]
// [44, 999]
// 44
// [44, 999]
// true
}
}
ArrayList 和 LinkedList 的比较
如何选择ArrayList和LinkedList:
- 如果我们改查的操作多,选择ArrayList
- 如果我们增删的操作多,选择LinkedList
- 一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
- 在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList,也就是说,要根据业务来进行选择