1. 什么是顺序表?
顺序表是数据结构中, 耿广义的概念
数组是 Java 语法中, 更具体的概念
数组是实现顺序表的一种典型方式
Java 实现顺序表的时候, 有一个专门的类 ArrayList (针对普通的数组进行封装)
List: 线性表
ArrayList: 顺序表
Collection: 元素集合
一个线性表要提供的典型操作(增删改查), 就可以直接参考 List 接口里面的方法
2. Java 中的 List 和 ArrayList 类
方法 | 解释 |
---|---|
boolean add(元素类型 e) | 将 e 尾插到线性表中 |
void add(int index, 元素类型 e); | e 插入到线性表的 index 位置处 |
元素类型 remove(int index); | 删除 index 位置的元素,并返回该元素; |
boolean remove(元素类型 e); | 删除从前往后遍历时,遇到的第一个相等的(equals)元素 |
元素类型 get(int index); | 返回 index 位置的元素 |
元素类型 set(int index, 元素类型 e); | 用新的元素 e 替换 index 位置的元素,并返回 index 位置的原来的元素 |
boolean contains(元素类型 e); | 判断与元素 e 相等(equals)的元素是否存在于线性表中 |
int indexOf(元素类型 e); | 从前往后遍历的方式,找到第一个与元素 e 相等(equals)的元素的下标 |
int lastIndexOf(元素类型 e); | 从后往前遍历的方式,找到第一个与元素 e 相等(equals)的元素的下标 |
void clear(); | 清空线性表 |
int size(); | 返回线性表中已有元素的个数 |
boolean isEmpty(); | 返回线性表是不是一个空的容器 |
Iterator iterator(); | |
void sort(Comparator 比较器); | |
List subList(int fromIndex, int toIndex); |
3. 迭代器(Iterator)
每种容器(Collection)都是具备迭代能力(Iterable)的。所以,每种容器都自带一个方法,返回一个合适的迭代器(Iterator)以对容器进行无视实现差别的迭代。
ArrayList<String> list = new ArrayList<>();
list.add("你好");
list.add("中国");
Iterator<String> it = list.iterator();
// 只要还有下一个元素,循环就继续
while (it.hasNext()) {
// 获取下一个元素,并让迭代器走到之后的位置上
String e = it.next();
// 可以在合适的条件下,对当前迭代器正处于的元素进行删除
it.remove();
}
4. 实现 ArrayList
import java.util.Arrays;
public class MyArrayList {
// 属性
// 数组为空数组
private String[] date = null;
// 数组长度为 0
private int size = 0;
// 数组最大容量为 100,超出容量就需要扩容
private int capacity = 100;
public MyArrayList() {
date = new String[capacity];
}
public void realloc() {
// 准备一个更大容器
capacity = 2 * capacity;
String[] newDate = new String[capacity];
// 将 date 中数据拷贝到 newDate 中
for (int i = 0; i < size; i++){
newDate[i] = date[i];
}
date = newDate;
}
// 1.插入操作
// 尾插
public void add(String e) {
// 如果 size >= capacity 则需要扩容
if (size >= capacity) {
realloc();
}
date[size] = e;
size++;
}
// 任意位置插入
public void add(int index, String e) {
// 先判断是否小需要扩容
if (size >= capacity) {
realloc();
}
// 找到插入元素位置,将该位置和以后元素依次向后移位
for (int i = size - 1; i >= index; i--) {
date[i + 1] = date[i];
}
date[index] = e;
size++;
}
// 2.删除元素
// 按照下标元素删除,这个方法返回删除的元素
public String remove(int index) {
// 注意先判断边界条件
if (index < 0 || index >= size) {
return null;
}
// 找到下标元素返回,将之后元素依次向前移
String ret = date[index];
for (int i = index - 1; i < size; i++) {
date[i] = date[i + 1];
}
// 更新 size
size--;
return ret;
}
// 指定元素删除,返回是否删除成功
public boolean remove(String e) {
// 遍历寻找指定元素
int index = 0;
for ( ; index < size; index++) {
if (date[index].equals(e)) {
break;
}
}
// 若元素是最后一个,直接 -- 即可
if (index == size) {
size--;
}
// 将元素覆盖
for (; index < size; index++) {
date[index] = date[index + 1];
}
size--;
return true;
}
// 3.获取指定位置元素
public String get(int index) {
if (index < 0 || index >= size) {
// 可以返回 null 也可以抛出一个异常
// return null;
throw new MyArrayListIndexOutOfRangeException("下标越界了! index:" + index);
}
return date[index];
}
// 4.修改指定位置元素
public void set(int index, String e) {
if (index >= size || index < 0) {
// return null;
throw new MyArrayListIndexOutOfRangeException("下标越界了! + index");
}
date[index] = e;
}
// 5.判断元素是否存在
public boolean contains(String e) {
for (int i = 0; i < size; i++) {
if (date[i].equals(e)){
return true;
}
}
return false;
}
// 6.查找元素位置
public int indexOf(String e) {
for (int i = 0; i < size; i++) {
if (date[i].equals(e)) {
return i;
}
}
// 未找到元素,返回 -1
return -1;
}
// 7.查找指定元素(从后往前遍历)
public int lastIndexOf(String e) {
for (int i = size - 1; i >= 0; i--) {
if (date[i].equals(e)) {
return i;
}
}
return -1;
}
// 清空线性表
public void clear() {
size = 0;
}
// 返回线性表已有元素个数
public int size() {
return size;
}
// 返回线性表是否为空
public boolean isEmpty() {
// 判断线性表长度
// 长度为 0 返回 true
return size == 0;
}
@Override
public String toString() {
// 直接使用,缺点会输出 null
// return Arrays.toString(date);
// 自己重写方法
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("[");
for (int i = 0; i < size; i++) {
stringBuilder.append(date[i]);
if (i < size - 1) {
stringBuilder.append(",");
}
}
stringBuilder.append("]");
return stringBuilder.toString();
}
public static void main(String[] args) {
MyArrayList date = new MyArrayList();
date.add("c");
date.add(1,"c++");
date.add("java");
// date.remove("c++");
// date.remove(1);
System.out.println(date.get(2));
date.set(2,"c+");
System.out.println(date.contains("java"));
System.out.println(date.indexOf("c+"));
System.out.println(date.lastIndexOf("c"));
System.out.println(date.size);
System.out.println(date);
date.clear();
System.out.println(date.isEmpty());
}
class MyArrayListIndexOutOfRangeException extends RuntimeException {
public MyArrayListIndexOutOfRangeException(String message) {
super(message);
}
}
}