文章目录
ArrayList 与顺序表
顺序表
顺序表是用一段 物理地址连续的存储单元依次存储的线性结构 , 一般情况下采用数组存储 . 在数组上完成数据的增删查改
假设有一组数据:
public int[] elem;
public int usedSize;//存储了多少个有效的数据
public static final int DEFAULT_SIZE = 5;
public MyArrayList() {
this.elem = new int[DEFAULT_SIZE];
}
打印顺序表
public void display() {
for (int i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i] + " ");
}
System.out.println(" ");
}
新增元素
默认在数组最后新增
-
先检查数组是否为满
public boolean isFull() { /*if(this.usedSize == this.elem.length) { return true; } return false;*/ return this.usedSize == this.elem.length; }
-
如果数组满了 , 进行数组扩容
private void resize() { this.elem = Arrays.copyOf(this.elem,2*this.elem.length);//扩容 }
// 新增元素,默认在数组最后新增
public void add(int data) {
if(this.isFull()) {
resize();
}
this.elem[this.usedSize] = data;
this.usedSize++;
}
在pos 位置新增元素
-
先检查pos 位置的合法性
private void checkIndex(int pos) { if (pos < 0 || pos > usedSize) { throw new IndexOutOfException("位置不合法,请检查位置的合法性"); } }
-
再判断数组是否为满
//判断是否为满 public boolean isFull() { /*if(this.usedSize == this.elem.length) { return true; } return false;*/ return this.usedSize == this.elem.length; }
-
如果数组满了 , 进行扩容
private void resize() { this.elem = Arrays.copyOf(this.elem,2*this.elem.length);//扩容 }
public void add(int pos, int data) {
checkIndex(pos);//检查pos的合法性
if (isFull()) {
resize();
}
for (int i = usedSize - 1; i >= pos; i--) {
elem[i+1] = elem[i];
}
elem[pos] = data;
usedSize++;
}
判断是否包含某个元素
public boolean contains(int toFind) {
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == toFind) {
return true;
}
}
return false;
}
查找某个元素对应的位置
// 查找某个元素对应的位置
public int indexOf(int toFind) {
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == toFind) {
return i;
}
}
return -1; //因为数组没有负数下标
}
获取 pos 位置的元素
public int get(int pos) {
checkGetIndex(pos);
return elem[pos];
}
private void checkGetIndex(int pos) {
if (pos < 0 || pos >= usedSize) {
throw new IndexOutOfException("get元素的时候,位置不合法,请检查位置的合法性");
}
}
抛异常
public class IndexOutOfException extends RuntimeException{
public IndexOutOfException() {
}
public IndexOutOfException(String msg) {
super(msg);
}
}
给pos位置元素设为 value
-
检查 pos 位置是否合法
private void checkIndex(int pos) { if (pos < 0 || pos > usedSize) { throw new IndexOutOfException("位置不合法,请检查位置的合法性"); } }
public void set(int pos, int value) {
checkIndex(pos);
elem[pos] = value;
}
删除第一次出现的关键字 key
public boolean remove(int toRemove) {
int index = indexOf(toRemove);
if(index == -1) {
System.out.println("没有这个数据");
return false;
}
for (int i = index;i < usedSize;i++) {
elem[i] = elem[i + 1];
}
usedSize--;
elem[usedSize] = 0;
return true;
}
获取顺序表长度
public int size() {
return usedSize;
}
清空顺序表
public void clear() {
usedSize = 0;
}
ArrayList
在集合框架中 , ArrayList 是一个普通的类 , 实现了 List接口
- ArrayList 是以泛型方式实现的 , 使用时必须先要实例化
- ArrayList 实现了 RandomAccess 接口 , 表名 ArrayList 支持随机访问
- ArrayList 实现了 Clonable 接口 , 表名ArrayList 是可以 clone的
- ArrayList 实现了Serializable 接口 , 表名ArrayList 是支持序列化的
- 和 Vector 不同 , ArrayList不是线程安全的 , 在单线程下可以使用 , 在多线程中可以选择 Vector 或者 CopyOnWriteList
- ArrayList 底层是一段连续的空间 , 并且可以动态扩容 , 是一个动态类的顺序表
创建ArrayList
public static void main(String[] args) {
//构造一个空的列表
ArrayList<Integer> arraylist1 = new ArrayList<>();
//构造一个容量为十的列表
ArrayList<Integer> arraylist2 = new ArrayList<>(10);
}
遍历ArrayList
三种方式进行遍历 :
-
for 循环
for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i) + " "); }
-
foreach
for (Integer x : list) { System.out.print(x + " "); } System.out.println();
-
迭代器
ListIterator<Integer> it = list.listIterator(); while(it.hasNext()) { System.out.print(it.next()+" "); //打印的同时 让 it 往前走一步 }
ArrayList 操作
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("张三");
arrayList.add("王五");
arrayList.add("李四");
System.out.println(arrayList);
//获取 arrayList 中的有效元素个数
System.out.println(arrayList.size());
//获取和设置 index 位置上的元素 , index必须介于 [0,size)之间
System.out.println(arrayList.get(0));
arrayList.set(0,"赵六");
System.out.println(arrayList.get(0));
//在arrayList 的index 位置插入指定元素 , index及后续的元素同一往后挪一个位置
arrayList.add(1,"刘七");
System.out.println(arrayList);
//删除指定元素 , 找到了就删除 , 该元素之后的元素同一往前挪一个位置
arrayList.remove("赵六");
System.out.println(arrayList);
//删除arrayList中index位置上的元素 , 注意 index不要超过list中有效元素个数 , 否则会抛出下标越界异常
arrayList.remove(arrayList.size()-1);
System.out.println(arrayList);
}
例题
杨辉三角
public List<List<Integer>> gengrate(int numRows) {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> row = new ArrayList<>();
row.add(1);
ret.add(row);
for (int i = 0; i < numRows; i++) {
List<Integer> prevRom = ret.get(i - 1);
List<Integer> curRom = new ArrayList<>();
curRom.add(1);//第一个1
//中间 curRow list 的值
for (int j = 0; j < i; j++) {
int x = prevRom.get(j) + prevRom.get(j - 1);
curRom.add(x);
}
curRom.add(1);//最后一个1
ret.add(curRom);
}
return ret;
}
删除多余字符
/**
* s1 = welcome to home
* s2 = come
* 要求删除 s1 中的字符 , 这些字符都是 s2 出现的 s1 = wl t h
* @param args
*/
public static void main(String[] args) {
ArrayList<Character> list = new ArrayList<>();
String s1 = "welcome to home";
String s2 = "come";
for (int i = 0; i < s1.length(); i++) {
char ch = s1.charAt(i);
if (!s2.contains(ch + "")) {
list.add(ch);
}
}
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
}
总结
优点 : 当给定下标时 , 查找速度非常快 . 适合给定下标的查找
缺点 :
1. 插入 : 必须挪动元素 , 才能插入元素
2. 删除 : 必须挪动元素 , 才能删除
3. 每次扩容 , 非常浪费资源
);
if (!s2.contains(ch + “”)) {
list.add(ch);
}
}
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
}
#### 总结
优点 : 当给定下标时 , 查找速度非常快 . 适合给定下标的查找
缺点 : 1. 插入 : 必须挪动元素 , 才能插入元素
2. 删除 : 必须挪动元素 , 才能删除
3. 每次扩容 , 非常浪费资源