学习目标:
java中的数组操作
学习内容:
1. ArrayList
概述
ArrayList可以创建包含单一类型元素的数组,也可以创建包含不同类型元素的数组。
示例
import java.util.ArrayList;
public class Lianxi1 {
public static void main(String[] args) {
// 创建一个只包含String类型的ArrayList对象
ArrayList<String> list = new ArrayList<String>();
// 添加元素到ArrayList中
list.add("李四");
list.add("小明");
list.add("小红");
// 打印ArrayList中的元素 [李四, 小明, 小红]
System.out.println(list);
// 修改ArrayList中的元素
list.set(0, "小刚");
list.remove(1);
// 打印修改后的ArrayList中的元素 [小刚, 小红]
System.out.println(list);
// 遍历ArrayList中的元素
for (String str : list) {
System.out.println(str);
}
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/**
* ArrayList的常用操作
*/
public class Lianxi1 {
public static void main(String[] args) {
// 创建一个可包含多种类型元素的ArrayList
ArrayList<Object> list = new ArrayList<Object>();
// 添加元素到ArrayList中
list.add("李四");
list.add("小明");
// 添加Integer类型的元素到ArrayList中
list.add(123);
// 在ArrayList的指定位置添加元素,不指定位置则添加到末尾
list.add(1, "王五");
// 创建另一个集合
ArrayList<Object> anotherList = new ArrayList<Object>(Arrays.asList(1, 2, 456));
list.addAll(anotherList); // 使用addAll将anotherList中的所有元素添加到list的末尾
list.addAll(1, anotherList); //将 anotherList 中的所有元素插入到 list 的索引 1 处
// clone()方法创建ArrayList的浅拷贝
ArrayList<Object> clonedList = (ArrayList<Object>) list.clone();
System.out.println("clonedList: " + clonedList); // 输出[李四, 1, 2, 456, 王五, 小明, 123, 1, 2, 456]
// 深拷贝ArrayList 当list中元素改变后,deepClonedList中的元素不会改变
ArrayList<Object> deepClonedList = new ArrayList<Object>(list);
System.out.println("deepClonedList: " + deepClonedList); // 输出 [李四, 1, 2, 456, 王五, 小明, 123, 1, 2, 456]
list.add(2, "张三"); // 在ArrayList的指定位置添加元素
// 排序操作
anotherList.sort(null); // 使用默认的排序方式对ArrayList进行排序
System.out.println("clonedList: " + clonedList);; // 输出 [李四, 1, 2, 456, 王五, 小明, 123, 1, 2, 456]
System.out.println("deepClonedList: " + deepClonedList); // 输出 [李四, 1, 2, 456, 王五, 小明, 123, 1, 2, 456]
System.out.println("list: " + list); // 输出 [李四, 1, 张三, 2, 456, 王五, 小明, 123, 1, 2, 456]
// 切片操作
list.subList(1, 4); // 截取ArrayList的子列表, 包含索引1到索引3的元素, 并返回一个新的ArrayList
// 判断ArrayList中是否包含元素
boolean isHas = list.contains("小明"); // 判断ArrayList中是否包含元素"小明"
System.out.println(isHas); // 输出true
int index = list.indexOf("小明"); // 返回元素"小明"的索引,如果不存在,返回-1
System.out.println(index); // 输出0
list.set(0, "张三"); // 修改ArrayList中的元素
Object obj = list.get(0); // 获取ArrayList中的元素
System.out.println(obj); // 输出张三
int size = list.size(); // 获取ArrayList的大小
System.out.println(size); // 输出6
// 反转操作
Collections.reverse(list); // 反转ArrayList中的元素
System.out.println(list); // 输出[新元素2, 新元素1, 王五, 张三, 456, 123]
//hashCode()和equals()方法
int hash = list.hashCode(); // 获取ArrayList的哈希码
System.out.println(hash); // 输出-123456789
boolean isEqual = list.equals(anotherList); // 判断两个ArrayList是否相等
System.out.println(isEqual); // 输出false
// 获取并删除ArrayList中的最后一个元素
int lastIndex = list.size() - 1;
Object lastElement = list.remove(lastIndex); // 获取并删除ArrayList中的最后一个元素
System.out.println(lastElement); // 输出123
System.out.println(list); // 输出[新元素2, 新元素1, 王五, 张三, 456]
// 删除操作
list.remove("小明"); // 从ArrayList中删除元素
list.remove("test"); // 从ArrayList中删除不存在的元素, 不会报异常
list.remove(0); // 从ArrayList中删除元素
// list.remove(10); // 从ArrayList中删除不存在的元素, 会报IndexOutOfBoundsException异常
// 打印ArrayList中的元素
System.out.println(list);
// 遍历ArrayList中的元素
for (Object ob : list) {
System.out.println(ob);
}
//使用forEach方法遍历ArrayList中的元素
list.forEach(System.out::println);
list.clear(); // 清空ArrayList中的元素
System.out.println(list); // 打印ArrayList中的元素,此时ArrayList为空
}
}
2、Arrays
概述
Arrays可创建固定长度列表,只可修改,不可添加也不可删除
import java.util.Arrays;
import java.util.List;
public class Lianxi1 {
// 定义一个固定长度的列表
public static void main(String[] args) {
// 使用Arrays.asList()创建一个固定长度的列表
List<String> fixedSizeList = Arrays.asList("李四", "小明", "小红");
System.out.println("固定长度列表: " + fixedSizeList);
// 尝试添加元素(会抛出UnsupportedOperationException)
try {
fixedSizeList.add("新元素");
} catch (UnsupportedOperationException e) {
System.out.println("无法添加元素到固定长度列表");
}
// 尝试删除元素(会抛出UnsupportedOperationException)
try {
fixedSizeList.remove(0);
} catch (UnsupportedOperationException e) {
System.out.println("无法删除元素从固定长度列表");
}
// 修改元素
fixedSizeList.set(0, "小刚");
System.out.println("修改后的固定长度列表: " + fixedSizeList);
}
}
import java.util.Arrays;
import java.util.List;
public class Lianxi1 {
public static void main(String[] args) {
// 创建一个包含3个整数的数组
int[] array = new int[3];
array[0] = 1;
array[1] = 3;
array[2] = 2;
// 打印数组 [1, 3, 2]
System.out.println(Arrays.toString(array));
// 排序数组 [1, 2, 3]
Arrays.sort(array);
System.out.println(Arrays.toString(array));
// 查找元素
int index = Arrays.binarySearch(array, 2);
System.out.println("元素2的索引位置: " + index);
// 复制数组
int[] copyArray = Arrays.copyOf(array, array.length);
System.out.println("复制后的数组: " + Arrays.toString(copyArray));
// 填充数组
Arrays.fill(copyArray, 0);
System.out.println("填充后的数组: " + Arrays.toString(copyArray));
// 比较数组
boolean isEqual = Arrays.equals(array, copyArray);
System.out.println("两个数组是否相等: " + isEqual);
// 转换为列表
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println("转换为列表: " + list);
// 多维数组操作
int[][] multiArray = {{1, 2, 3}, {4, 5, 6}};
System.out.println("多维数组: " + Arrays.deepToString(multiArray));
}
}
3.不可变列表
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Lianxi1 {
public static void main(String[] args) {
// 使用Collections.unmodifiableList将数组转换为不可变列表
List<Integer> immutableList = Collections.unmodifiableList(Arrays.asList(1, 3, 2));
// 尝试修改不可变列表(会抛出UnsupportedOperationException)
// immutableList.set(0, 10);
// 打印不可变数组和不可变列表
System.out.println("不可变列表: " + immutableList);
}
}
4. 基础概念
Array和List
在Java中,数组(Array)和列表(List)是两种常用的数据结构,它们用于存储一系列的元素。尽管它们看起来功能相似,但在使用方式、性能和功能上存在一些关键的区别。ArrayList或LinkedList是List的实现类。
- 类型安全性
数组:在创建时指定了其可以持有的元素类型,比如int[]、String[]等。一旦创建,数组的类型就固定了,不能改变。
列表:是一个接口,可以通过泛型来指定其可以持有的元素类型,如List。列表的类型也是在创建时指定的,但比数组更灵活,因为可以使用泛型。 - 大小固定性
数组:一旦创建,其大小就固定了,不能动态增长或缩减。
列表:大小是动态的,可以根据需要增加或减少元素。 - 性能
数组:在性能上通常优于列表,尤其是在遍历和访问元素时。数组是连续的内存空间,这使得访问速度非常快。
列表:由于提供了更多的功能和灵活性,所以在性能上可能稍逊于数组,尤其是在大量元素的情况下。 - 功能
数组:功能相对简单,主要用于存储和访问固定数量的元素。
列表:提供了丰富的操作,如添加、删除、查找、排序等。列表是一个接口,Java集合框架提供了多种实现,如ArrayList、LinkedList等,每种实现都有其特定的用途和性能特点。
总结
选择数组还是列表,主要取决于具体的应用场景。如果元素数量固定,且对性能有较高要求,可以选择数组。如果需要频繁地添加、删除元素,或者不确定元素的数量,列表是更好的选择。
ArrayList和List
在Java中,ArrayList和List之间的区别主要体现在它们的本质、实现方式、功能特性以及使用场景上。以下是对这些区别的详细分析:
- 本质区别
List:List是Java集合框架(Java Collections Framework)中的一个接口,它继承自Collection接口。List接口定义了一系列操作有序集合的方法,如添加、删除、检索和遍历等。由于List是一个接口,它不能被直接实例化。
ArrayList:ArrayList是List接口的一个具体实现类,它实现了可变大小的数组。ArrayList底层基于动态数组实现,可以根据需要自动调整大小,以存储任意数量的元素。 - 实现方式
List:作为一个接口,List定义了操作有序集合的规范,但具体实现由它的实现类(如ArrayList、LinkedList等)来完成。
ArrayList:ArrayList通过动态数组实现,内部维护一个Object类型的数组来存储元素。当元素数量超过当前数组容量时,ArrayList会自动进行扩容,以容纳更多的元素。 - 功能特性
List:提供了有序集合的一系列操作方法,如add(E e)、remove(int index)、get(int index)等,但由于它是接口,这些方法的具体实现依赖于实现类。
ArrayList:除了继承List接口的所有方法外,ArrayList还提供了基于动态数组实现的特定功能,如自动扩容、通过索引直接访问元素等。ArrayList的随机访问效率较高,但在插入和删除元素时可能需要移动其他元素,效率相对较低。 - 使用场景
List:由于List是一个接口,它通常用于需要有序集合操作的场合,但具体实现类可以根据需求选择。例如,如果需要频繁地插入和删除元素,可以考虑使用LinkedList;如果需要快速随机访问元素,可以考虑使用ArrayList。
ArrayList:ArrayList适用于需要动态数组功能的场合,如需要频繁地添加或删除元素,但又希望保持元素的顺序时。ArrayList还适用于需要快速随机访问元素的场合,因为基于数组的实现使得通过索引访问元素变得非常高效。
总结
ArrayList和List之间的主要区别在于它们的本质、实现方式、功能特性以及使用场景。List是一个接口,定义了有序集合的操作规范;而ArrayList是List接口的一个具体实现类,通过动态数组实现了有序集合的功能。在选择使用ArrayList还是其他List实现类时,需要根据具体需求来决定。
ArrayList和LinkedList
ArrayList和LinkedList是Java集合框架中两种常用的List实现类,它们在内部实现、性能特点、使用场景等方面存在显著差异。以下是它们之间的主要区别:
- 内部实现
ArrayList:基于动态数组实现。ArrayList在内存中使用连续的空间来存储元素,当元素数量超过当前数组容量时,会自动扩容,通常是将数组大小增加到原来的1.5倍(但具体实现可能有所不同)。
LinkedList:基于双向链表实现。每个节点(Node)包含数据部分和指向前一个节点及后一个节点的指针(引用),这使得LinkedList的元素在内存中可以是分散存储的,每个节点可以有自己的大小。 - 性能特点
随机访问效率:
ArrayList:由于是基于数组实现的,因此支持快速的随机访问。通过索引直接访问元素的时间复杂度为O(1)。
LinkedList:不支持高效的随机访问。访问第N个元素需要从头部或尾部开始遍历链表,时间复杂度为O(N)。
插入和删除效率:
ArrayList:在列表的中间插入或删除元素时,需要将插入或删除位置后面的元素都向后或向前移动,时间复杂度为O(N)。但在列表的末尾添加或删除元素是高效的,时间复杂度为O(1)。
LinkedList:在列表的中间插入或删除元素时,只需要改变相邻节点的指针,时间复杂度为O(1)。但在列表的中间位置访问元素时,需要从头或尾开始遍历链表,时间复杂度为O(N)。
空间占用:
ArrayList:需要连续的内存空间来存储元素,当元素数量较大时,可能会占用更多的内存空间。但ArrayList的空间浪费主要体现在在列表的结尾预留一定的容量空间。
LinkedList:不需要连续的内存空间,可以根据需要动态分配内存。但每个节点除了存储数据之外,还需要额外的空间来存储对前一个节点和后一个节点的引用,因此可能会占用更多的内存空间(尽管通常这种空间占用在整体应用中的影响较小)。
迭代器性能:
ArrayList:由于数据在内存中是连续存储的,迭代时不会产生额外的指针跳转操作,因此迭代器性能通常较好。
LinkedList:数据在内存中是分散存储的,迭代时可能会频繁地进行指针跳转,因此迭代器性能可能较差。 - 使用场景
ArrayList:适用于需要频繁进行随机访问操作的场景,如需要根据索引获取元素或更新元素的值。它也适用于那些对列表进行遍历、迭代和转换的情况。
LinkedList:适用于频繁执行插入和删除操作的场景,尤其是当这些操作发生在列表的开头或中间位置时。此外,当用作队列或栈的基础数据结构时,LinkedList是一个很好的选择。
综上所述,ArrayList和LinkedList各有优缺点,在选择时应根据具体的使用场景和需求来决定。