前言
前面我们讲了很多关于Java数据结构的基础知识,现在我们开始正式进入Java数据结构的第一章开始学习,List、ArrayList以及顺序表
1.List的介绍
1.1.什么是List
在集合框架中,List是一个接口,继承自Collection。
I表示是接口
Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示
Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下:
站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作
1.2. 常见接口介绍
List中提供了好的方法,具体如下:
虽然方法比较多,但是常用方法如下
1.3. List的使用
注意:List是个接口,并不能直接用来实例化。
如果要使用,必须去实例化List的实现类。在集合框架中,ArrayList和LinkedList都实现了List接口
下面在进行讲解
2.ArrayList以及顺序表
2.1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
2.2.顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改
2.3.ArrayList的模拟实现
2.3.1.创建接口
首先我们把一些常用的方法放到一个接口里,这样以后模拟实现任何一个顺序表,只需要重写一下里面的内容即可。
/**
* @Author: Lenovo
* @Date: 2024/6/9 10:05
* @description:
*/
public interface IList {
void add(int data);
boolean isFull();
//在pos位置新增元素
void add(int pos,int data);
//判定是否包含某个元素
boolean contains(int toFind);
//获取 pos 位置的元素
int get(int pos);
//给 pos 位置的元素设置为 value
void set(int pos,int value);
//删除第一次出现的关键字key
void remove(int toRemove);
//获取顺序表的长度
int size();
//清空顺序表
void clear();
public int indexOf(int toFind);
//打印顺序表 注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
void display();
}
下面我们就要对上面的方法进行重写。
2.3.2.准备工作
import java.util.Arrays;
/**
* @Author: Lenovo
* @Date: 2024/6/9 10:02
* @description:
*/
public class MyArrayList implements IList{
public int[]array;
public int useSize;
public final int DEFAULT_CAPACITY=10;
public MyArrayList(){
this.array=new int[DEFAULT_CAPACITY];
}
@Override
public void add(int data) {
}
//扩容操作
private void grow(){
}
@Override
public boolean isFull() {
}
@Override
public void add(int pos, int data) {
}
@Override
public boolean contains(int toFind) {
return false;
}
@Override
public int get(int pos) {
return 0;
}
@Override
public void set(int pos, int value) {
}
@Override
public void remove(int toRemove) {
}
@Override
public int size() {
return 0;
}
@Override
public void clear() {
}
@Override
public int indexOf(int toFind) {
return 0;
}
@Override
public void display() {
}
}
2.3.3.添加数据和打印数据
首先就要看数组是否满了,是否需要扩容。
//扩容操作
private void grow(){
this.array= Arrays.copyOf(this.array,2*this.array.length);
}
@Override
public boolean isFull() {
return this.array.length==this.useSize;
}
第二步才是进行添加数据。
2.3.3.1.在数组末尾进行插入
@Override
public void add(int data) {
if(isFull()){
grow();
}
this.array[this.useSize]=data;
this.useSize++;
}
2.3.3.2.在指定位置之后插入
首先我们要对pos进行一个判断,使用异常。
PosIllegal异常
public class PosIllegal extends RuntimeException{
public PosIllegal(){
}
public PosIllegal(String s){
super(s);
}
}
private void CheckPos(int pos) throws PosIllegal{
if(pos<0||pos>useSize){
throw new PosIllegal("pos位置不合法!!!");
}
}
@Override
public void add(int pos, int data) {
try {
CheckPos(pos);
if(isFull()){
grow();
}
for (int i = this.useSize; i >pos ; i--) {
array[i]=array[i-1];
}
this.array[pos]=data;
this.useSize++;
}catch (PosIllegal e){
e.printStackTrace();
}
}
2.3.3.3.打印数据
public void display() {
for(int i=0;i<this.useSize;i++){
System.out.print(this.array[i]+" ");
}
System.out.println();
}
2.3.4.获得数据和在指定位置修改数据
首先我们要对pos进行一个判断,使用异常。
我们会发现,那个pos的范围发生了变化,所以又要创建一个新方法,来进行判断。
2.3.4.1.获得数据
首先要进行判空以及pos是否分问题,需要使用两个异常
EmptyExpection异常
public class EmptyExpection extends RuntimeException{
public EmptyExpection(){
super();
}
public EmptyExpection(String s){
super(s);
}
}
其中判断pos的区间也发生了变化,又重新再写一个方法
private void CheckPos2(int pos) throws PosIllegal{
if(pos<0||pos>=useSize){
throw new PosIllegal("Pos位置不合法");
}
}
判空操作
private void CheckEmpty()throws EmptyExpection{
if(isEmpty()){
throw new EmptyExpection("数组为空");
}
}
public int get(int pos) {
try {
CheckPos2(pos);
CheckEmpty();
return array[pos];
}catch (PosIllegal e){
e.printStackTrace();
}catch (EmptyExpection e){
e.printStackTrace();
}
return -1;
}
2.3.4.2.在指定位置修改数据
主要流程都一样,都是要判空,要判断pos的合法性
public void set(int pos, int value) {
try {
CheckPos2(pos);
CheckEmpty();
array[pos]=value;
}catch (PosIllegal e){
e.printStackTrace();
}catch (EmptyExpection e){
e.printStackTrace();
}
}
2.3.5.删除元素、查找元素、包含元素以及清空元素
2.3.5.1.查找元素
public int indexOf(int toFind) {
for (int i=0;i<this.useSize;i++){
if(array[i]==toFind){
return i;
}
}
return -1;
}
2.3.5.2.是否包含某个元素
public boolean contains(int toFind) {
for (int i = 0; i < this.useSize; i++) {
if(array[i]==toFind){
return true;
}
}
return false;
}
2.3.5.3.清空元素
public void clear() {
/*
如果是数组里面是引用数据类型,就需要这样子做了
for(int i=0;i<useSize;i++){
array[i]=null;
}
*/
this.useSize=0;
}
2.3.5.4.删除元素
public void remove(int toRemove) {
try{
CheckEmpty();
int pos=indexOf(toRemove);
if(pos==-1){
return;
}
for (int i = pos; i <this.useSize-1 ; i++) {
array[i]=array[i+1];
}
this.useSize--;
}catch (EmptyExpection e){
e.printStackTrace();
}
}
2.3.6.所有代码
MyArrayList类
import java.util.Arrays;
/**
* @Author: Lenovo
* @Date: 2024/6/9 10:02
* @description:
*/
public class MyArrayList implements IList{
public int[]array;
public int useSize;
public final int DEFAULT_CAPACITY=10;
public MyArrayList(){
this.array=new int[DEFAULT_CAPACITY];
}
@Override
public void add(int data) {
if(isFull()){
grow();
}
this.array[this.useSize]=data;
this.useSize++;
}
//扩容操作
private void grow(){
this.array= Arrays.copyOf(this.array,2*this.array.length);
}
@Override
public boolean isFull() {
return this.array.length==this.useSize;
}
private boolean isEmpty(){
return this.array.length==0;
}
private void CheckPos(int pos) throws PosIllegal{
if(pos<0||pos>useSize){
throw new PosIllegal("pos位置不合法!!!");
}
}
@Override
public void add(int pos, int data) {
try {
CheckPos(pos);
if(isFull()){
grow();
}
for (int i = this.useSize; i >pos ; i--) {
array[i]=array[i-1];
}
this.array[pos]=data;
this.useSize++;
}catch (PosIllegal e){
e.printStackTrace();
}
}
@Override
public boolean contains(int toFind) {
for (int i = 0; i < this.useSize; i++) {
if(array[i]==toFind){
return true;
}
}
return false;
}
private void CheckPos2(int pos) throws PosIllegal{
if(pos<0||pos>=useSize){
throw new PosIllegal("Pos位置不合法");
}
}
private void CheckEmpty()throws EmptyExpection{
if(isEmpty()){
throw new EmptyExpection("数组为空");
}
}
@Override
public int get(int pos) {
try {
CheckPos2(pos);
CheckEmpty();
return array[pos];
}catch (PosIllegal e){
e.printStackTrace();
}catch (EmptyExpection e){
e.printStackTrace();
}
return -1;
}
@Override
public void set(int pos, int value) {
try {
CheckPos2(pos);
CheckEmpty();
array[pos]=value;
}catch (PosIllegal e){
e.printStackTrace();
}catch (EmptyExpection e){
e.printStackTrace();
}
}
@Override
public void remove(int toRemove) {
try{
CheckEmpty();
int pos=indexOf(toRemove);
if(pos==-1){
return;
}
for (int i = pos; i <this.useSize-1 ; i++) {
array[i]=array[i+1];
}
this.useSize--;
}catch (EmptyExpection e){
e.printStackTrace();
}
}
@Override
public int size() {
return this.useSize;
}
@Override
public void clear() {
/*
如果是数组里面是引用数据类型,就需要这样子做了
for(int i=0;i<useSize;i++){
array[i]=null;
}
*/
this.useSize=0;
}
@Override
public int indexOf(int toFind) {
for (int i=0;i<this.useSize;i++){
if(array[i]==toFind){
return i;
}
}
return -1;
}
@Override
public void display() {
for(int i=0;i<this.useSize;i++){
System.out.print(this.array[i]+" ");
}
System.out.println();
}
}
IList接口
/**
* @Author: Lenovo
* @Date: 2024/6/9 10:05
* @description:
*/
public interface IList {
void add(int data);
boolean isFull();
//在pos位置新增元素
void add(int pos,int data);
//判定是否包含某个元素
boolean contains(int toFind);
//获取 pos 位置的元素
int get(int pos);
//给 pos 位置的元素设置为 value
void set(int pos,int value);
//删除第一次出现的关键字key
void remove(int toRemove);
//获取顺序表的长度
int size();
//清空顺序表
void clear();
public int indexOf(int toFind);
//打印顺序表 注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
void display();
}
EmptyExpection异常类
/**
* @Author: Lenovo
* @Date: 2024/6/9 11:50
* @description:
*/
public class EmptyExpection extends RuntimeException{
public EmptyExpection(){
super();
}
public EmptyExpection(String s){
super(s);
}
}
PosIllegal异常类
/**
* @Author: Lenovo
* @Date: 2024/6/9 11:50
* @description:
*/
public class PosIllegal extends RuntimeException{
public PosIllegal(){
}
public PosIllegal(String s){
super(s);
}
}
下一篇我们在讲关于Java自带ArrayList的使用。
完