1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列等。
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
2.顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。可以在数组上完成数据的增删查改(CRUI)。
接口的实现:
public class SeqList {
private int[] array;
private int size;
// 默认构造方法
SeqList(){ }
// 将顺序表的底层容量设置为initcapacity
SeqList(int initcapacity){ }
// 新增元素,默认在数组最后新增
public void add(int data) { }
// 在 pos 位置新增元素
public void add(int pos, int data) { }
// 判定是否包含某个元素
public boolean contains(int toFind) { return true; }
// 查找某个元素对应的位置
public int indexOf(int toFind) { return -1; }
// 获取 pos 位置的元素
public int get(int pos) { return -1; }
// 给 pos 位置的元素设为 value
public void set(int pos, int value) { }
//删除第一次出现的关键字key
public void remove(int toRemove) { }
// 获取顺序表长度
public int size() { return 0; }
// 清空顺序表
public void clear() { }
// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
public void display() { }
}
3. ArrayList简介
在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:
【说明】
1. ArrayList是以泛型方式实现的,使用时必须要先实例化;
2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问;
3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的;
4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的;
5. 和Vector不同,Vector的底层数据结构是数组,查询快,增删慢,但与ArrayList不同,它是同步的,所以线程安全,效率较低。可以存储重复元素,并且支持同步操作,而ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList;
6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表。
4. ArrayList使用
ArrayList的构造:优先去看构造方法,因为构造方法会帮助成员进行初始化,而且构造方法的调用是在实例化对象。
有三个构造方法:
1.无参构造;
2.可以传一个集合;
3.可以传容量,指定顺序表初始容量。
一.不带参数的构造方法ArrayList()
A.通过ArrayList的源码可知,如图:
此为不带参数的构造方法ArrayList()
已知数组elementData在创建时为null,在不带参数的构造方法中也没有初始化,那么由下图引用add方法时,为什么数组可以存放数据?为什么不报错?
下图是Dubugger,可以清晰地看到编译时地具体过程!
那就去查看add方法是如何的:
此为通过list.add() 查看到的,但这个是在List接口下的方法,没有具体的实现过程,那么就要去查看ArrayList类里的add方法(ArrayList类实现List接口,重写了add()方法),如下图:
此图为底层代码的逻辑和原理讲解:
总结:当调用不带参数的构造方法时,底层的数组elementData长度为0,但是在第一次add()时,就会为我们分配内存,第一次分配的内存为10。
B.如何扩容的原理,如图:
这就是不带参数的构造方法ArrayList()为何数组elementData在创建时为null,还能继续进行存储数据,以及是如何扩容的原理。
二.带参数的构造方法ArrayList(int initialCapacity)
initialCapacity指定顺序表初始容量。
解读如图:
三.带参数的构造方法ArrayList(Collection<? extends E> c)
即传一个集合。
?属于通配符。
通配符
通配符是一种特殊语句,主要用于模糊搜索文件或进行模式匹配。
通配符在计算机科学和编程中广泛应用,它的主要作用是代替一个或多个字符,以便于在不确定完整字符串的情况下进行搜索或匹配操作。以下是关于通配符的详细解析:
1. 通配符的种类
星号(*):星号是最常用的通配符之一,它可以用来代替零个、单个或多个字符。例如,当查找以"AEW"开头的文件时,如果不记得文件名的其余部分,可以输入"AEW*",这样可以找到所有以"AEW"开头的文件。
问号(?):与星号不同,问号只能代替一个字符。例如,输入"love?"可以查找以"love"开头、后跟一个字符的文件,如"lovey"、"lovei"等。
其他通配符:在某些特定场景下,还使用方括号("[]")、花括号("{}")和圆括号("()")等作为通配符,它们分别表示指定范围内的任意单一字符、重复次数和分组。
2. 通配符的应用
文件查找:在使用操作系统或编程环境进行文件管理时,通配符大大简化了查找文件的过程。比如,可以使用"*.txt"来查找所有扩展名为"txt"的文件。
编程语言:在许多编程语言中,如SQL,通配符常用于数据库查询。例如,使用"LIKE"运算符配合"%"和"_"作为通配符来替代多个或一个字符,从而实现模糊搜索。
文本编辑器:在诸如Word等文本编辑器中,通配符也广泛应用于高级查找和替换功能。通过勾选“使用通配符”选项,可以执行更复杂的搜索操作,如"cho@se"可以查找到"chose"、"choose"等词。
3. 通配符的特殊用法
优先级规则:在使用多种通配符模式时,有一套特定的优先级规则来决定匹配的先后顺序。例如,更具体的模式(如精确路径)会被优先匹配。
路由配置:在网络路由器的配置中,通配符用于匹配IP地址,类似于子网掩码,但用途不同。例如,"10.0.0.0 0.0.0.255"表示匹配所有以"10"开头的IP地址。
4. 通配符的注意事项
转义字符:如果在搜索中需要用到通配符本身,通常需要使用反斜杠(\)进行转义。例如,要查找问号本身,需要输入"\?"。
性能影响:在使用通配符进行大规模数据搜索时,可能会对性能产生影响,因为需要遍历更多的可能性。因此,合理使用通配符能提高效率。
综上所述,通配符是一种强大的工具,能够极大地简化各种搜索和匹配任务。了解并灵活运用通配符,不仅能提高工作效率,还能在编程和数据处理中起到事半功倍的效果。在实际操作中,注意使用方法和具体语法,结合实际需求合理应用通配符,将能更好地服务于不同的使用场景和需求。
完整的示例代码演示说明:
class Person{
}
class Student extends Person{
}
public class Test {
public static void main(String[] args) {
ArrayList<Student> arrayList = new ArrayList<>();
List<Person> list = new ArrayList<>(arrayList);//E是Person,c是arrayList。虽然传入的参数是arrayList,但arrayList的类型是Student,是Person的子类,所以可以创建对象。
}
public static void main1(String[] args) {
// ArrayList创建,推荐写法
// 构造一个空的列表
List<String> list1 = new ArrayList<>();//子类ArrayList继承了父类List的成员和方法,还能实现动态继承,属于向上转型,实际就是创建一个子类对象,将其当成父类对象来使用。
list1.add("hello");
System.out.println("===========");
// 构造一个具有10个容量的列表
List<Integer> list2 = new ArrayList<>(15);
list2.add(1);
list2.add(2);
list2.add(3);
}
public static void main2(String[] args){
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("abc");
arrayList.add("def");
ArrayList<Integer> arrayList1 = new ArrayList<>();
List<String> list = new ArrayList<>(arrayList);//E是String,c是arrayList。可以将arrayList作为参数,因为其类型跟List<String> list实例化对象时的类型相同,都是String类型(String没有子类,不能被继承,是单独存在的)。
//List<String> list = new ArrayList<>(arrayList1);//E是String,c是arrayList1。arrayList1的类型是Integer,与List<String> list类型不符。因此会报错。
list.add("hello");
System.out.println("==============");
}
}
下一篇就继续记录ArrayList的知识点,包括ArrayList常见操作,ArrayList的遍历等。