- idea和eclipse
- eclipse的快速生成
- main函数:main
- 输出语句:syso
- idea的快速生成
- main函数:psvm
- 输出语句:sout
- 在idea中一个project相当于eclipse当中的一个workspace,在空的工程下新建Module(模块),IDEA中模块类似于eclipse当中的project
- eclipse的组织方式:workspace->project
- idea的组织方式:project->module
- idea的字体设置:
- file->settings->输入font->设置字体样式以及字号大小
- idea是自动保存,不需要ctrl+s
- idea添加构造方法/setXxx/getXxx:alt+insert
- eclipse的快速生成
- 抽象类
- 什么是抽象类?
- 类和类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类,类本身是不存在的,所以抽象类无法创建对象,无法实例化。
- 抽象类属于什么数据类型?
- 抽象类也属于引用数据类型,编译之后也是一个class字节码文件
- 抽象类怎么定义?
- [修饰符列表] abstract class 类名{
- 类体;
- }
- [修饰符列表] abstract class 类名{
- 抽象类是无法实例化的,无法创建对象,所以抽象类都是用来被子类继承的,所以final和abstract不能联合使用,这两个关键字是对立的
- 抽象类的子类可以是抽象类
- 抽象类虽然无法实例化,但抽象类有构造方法,这个构造方法供子类使用
- 抽象类关联到一个概念,抽象方法,什么是抽象方法呢?
- 抽象方法只有方法的声明,没有方法体,以分号结尾
- public abstract void doSome();
- 抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
- 重要结论:
- 一个非抽象的类继承抽象类,必须将抽象类中的抽象方法重写
- 一个抽象的类继承抽象类,可以不去将抽象类中的抽象方法重写
- 抽象类和非抽象之间可以使用多态,面向OCP原则
- 面试题:Java语言中凡是没有方法体的方法都是抽象方法
- 不对,错误的
- Object类中就有很多方法没有方法体,都是以;结尾的,但他们都不是抽象方法,例如:
- public native int hashCode();
- 这个方法底层调用了C++写的动态链接库程序
- 前面修饰符列表中没有abstract,有一个native,表示调用JVM本地程序
- 什么是抽象类?
- 接口
- 接口也是一种引用数据类型,编译之后也是一个class字节码文件
- 接口是完全抽象的,(抽象类是半抽象的),或者也可以说接口是特殊的抽象类,特殊在他是完全抽象的
- 接口怎么定义,语法是什么?
- [修饰符列表] interface 接口名{}
- 接口支持多继承,一个接口可以继承多个接口
- 接口中只包含两部分内容,一部分是常量,一部分是抽象方法,接口中的所有元素都是public修饰的
- 接口中的抽象方法定义时,public abstract修饰符可以省略
- 接口中的常量,public static final可以省略
- 类和类是继承(单继承),接口和接口是继承(多继承),类和接口之间是实现implements(多实现)
- 当一个非抽象类实现接口,必须将接口中的所有抽象方法全部实现
- 接口和非抽象之间可以使用多态,面向OCP原则
- 继承和实现都存在的话,extends关键字在前,implements关键字在后,如果没写继承,则默认继承Object类
- 接口在开发中的作用:
- 注意:接口在开发中的作用类似于多态在开发中的作用:
- 多态:面向抽象编程(将Dog/Cat写成Animal),不要面向具体编程,降低程序的耦合度,提高程序的扩展力、
- 总结:面向接口编程,可以降低程序的耦合度,提高程序的扩展力
- 接口离不开多态,接口+多态才可以达到降低程序的耦合度,提高程序的扩展力
- 类型和类型之间的关系:
- is a
- Cat is a Animal(猫是一个动物)
- 凡是能够满足is a的表示“继承关系”
- A extends B
- has a
- I has a Pen(我有一只笔)
- 凡是能够满足has a关系的表示“关联关系”
- 关联关系通常以“属性的形式存在”
- A{
- B b;
- }
- like a:
- Cooker like a FoodMenu(厨师像一个菜单一样)
- 凡是能够满足like a关系的表示“实现关系”
- 实现关系通常是:类实现接口
- A implements B
- is a
- 抽象类和接口的区别:
- 抽象类是半抽象的
- 接口时完全抽象的
- 抽象类中有构造方法
- 接口中没有构造方法
- 类之间是单继承
- 接口之间可以多继承
- 类可以实现多个接口
- 接口中只允许出现常量和抽象方法
- Object类中的方法在哪找?
- 第一:去源代码当中(但是这种方式比较麻烦,因为源代码也比较难)
- 第二: 去查阅java的类库的帮助文档
- 什么是API(Application Program Interface)?
- 应用程序编程接口
- 整个JDK类库就是一个javase的API
- 每一个API都会配置一套API帮助文档
- Object类需要了解的方法:
- Object的toString方法
- public String toString() {
- return getClass().getName() + "@" + Integer.toHexString(hashCode());
- }
- 返回的是:类名@对象的内存地址通过哈希算法转换为十六进制的形式
- SUN公司设计toString方法的目的?
- toString方法的设计目的是:通过调用这个方法可以将一个“Java对象”转换成字符串形式
- SUN公司开发Java语言的时候,建议所有的子类都去重写toString方法
- 输出引用的时候。默认会调用引用的toString方法
- public String toString() {
- Object的equals方法
- public boolean equals(Object obj){
- return (this == obj);
- }
- 以后编程的过程当中,都要通过equals方法来判断两个对象是否相等
- 判断基本数据类型是否相等直接使用“=”就可以,=判断的是值的大小,所以引用数据类型不能用“=”判断
- 在Object类的equals方法中,默认采用的是“==”判断两个Java对象是否相等,而“==”判断的是两个对象的内存地址是否相等,所以老祖宗的equals方法不够用,需要重写equals方法
-

-
改良之后的代码
-

-
再次改良之后的代码
-

- public boolean equals(Object obj){
-
String类
- String类已经重写了equals方法,比较两个字符串相等不能使用==,必须使用equals
- String类已经重写了toString方法
- Object的finalize方法
- protected void finalize() throws Throwable { }
- finalize()方法有一个没有代码的方法体,而且这个方法是protected修饰的
- 这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法,不像equals,toString方法是需要写代码调用的,finalize方法只需要重写,重写完将来自动会有程序来调用
- 当一个Java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法
- finalize()方法实际上是SUN公司为Java程序员准备的一个时机,垃圾销毁时机,如果希望在对象销毁时机执行一段代码的话,这段代码要写到finalize()方法当中
- java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到,种种条件下,又可能启动,也有可能不启动
- 有一段代码可以建议垃圾回收器启动:System.gc();,只是建议,可能启动,也可能不启动,只是启动的概率高了一些
- Object的hashCode方法
- public native int hashCode();
- 这个方法不是抽象方法,带有native关键字,底层调用C++程序
- hashCode方法返回的是哈希码
- 实际上就是一个Java对象的内存地址,经过哈希算法,得出的一个值
- 所以hashCode方法的执行结果可以等同看做一个Java对象的内存地址
- 内部类:
- 在类的内部又定义了一个新的类。被称为内部类
- 分类:
- 实例内部类:类似于实例变量
- 静态内部类:类似于静态变量
- 局部内部类:类似于局部变量
- 不能使用访问权限修饰符和static修饰
- 匿名内部类:
- 匿名内部类是一种特殊的局部内部类,它是通过匿名类实现接口
- 学习匿名内部类主要是以后阅读别人的代码时,可以理解,并不代表以后都要这样写,因为匿名内部类有两个缺点:
- 缺点一:太复杂、太乱、可读性差
- 缺点二:类没有名字,以后想重复使用,不能用
-

- 内部类的修饰符:private、protected、public及默认修饰符
- dosome方法中的局部内部类,在其他方法内不能使用
- 使用内部类编写的代码可读性很差,能不用尽量不用
- 数组
- 一维数组:
- 数组是一种引用数据类型,不属于基本数据类型,父类也是Object
- 数组实际上是一个容器,可以同时容纳多个元素
- 数组当中可以存储“基本数据”类型的数据,也可以存储“引用数据类型”的数据
- 数组因为是引用数据类型,所以数组对象在堆内存当中
-

-
数组当中如果存储的是java对象的话,实际存储的是对象的“引用(内存地址)”
- 数组一旦创建,长度不可变
- 数组的分类:一维数组、二位数组、三维数组、多维数组...........
- 所有的数组对象都有length属性,用来获取数组中元素的个数
- Java中的数组要求数组中元素的类型统一,比如int类型数组只能存储int类型,Person类型数组只能存储Person类型
- 数组在内存方面存储的时候,数组中的元素内存地址是连续的,这是数组存储元素的特色,数组实际上是一种简单的数据结构
- 所有数组都是拿第一个小方框的内存地址作为整个数组的内存地址,因为这样就可以算出后面数组的内存地址
- 数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个数组的下标是length-1
- 数组数据结构的优点和缺点?
- 优点:
- 查询/查找/检索某个下标上的元素时效率极高,可以说查询效率最高的一个数据结构
- 为什么检索效率高?
- 第一:数组中元素的内存地址在空间存储上是连续的
- 第二:每一个元素类型相同,所以占用空间大小一样
- 第三:知道第一个元素的内存地址,有知道下标,所以通过一个数学表达式就可以某个下标上元素的内存地址,然后直接通过内存地址定位元素,所以数组的检索效率最高
- 数组中存储100个元素,或者100万个元素,在元素检索方面,效率是一样的,因为数组中的元素查找的时候,不会一个一个找,是通过数学表达式计算出来的(算出一个内存地址,直接定位)
- 查询/查找/检索某个下标上的元素时效率极高,可以说查询效率最高的一个数据结构
- 缺点:
- 第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为随机增删元素会涉及到后面元素统一向前或向后移的操作
- 第二:数组不能存储大数据量,因为很难在内存空间上找到一快特别大的内存空间
- 注意:对于数组中最后一个元素的增删,是没有效率影响的
- 优点:
- 怎么声明/定义一个一维数组?
- int[] array1;或int ayyar1[];//不建议这种,这是C++风格
- double[] array2;
- String[] array3;
- Object[] array4;
- 怎么初始化一个一维数组?
- 包括两种方式:静态初始化一维数组、动态初始化一维数组
- 静态初始化一维数组(定义的同时初始化):
- int[] array={1,2,,3,4,5};
- int[] array=new int[]{1,2,3,4,5};
- 动态初始化一维数组(先定义,后初始化):
- int[] array=new int[5];//5表示数组元素的个数,每个元素默认值0
- 什么时候采用静态初始化方式,什么时候采用动态初始化方式?
- 当创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式
- 当创建数组的时候,不确定数组中存储哪些元素时,采用动态初始化方式来预先分配内存空间、
-

-
public static void main(String[] args){}
-
System.out.println(args.length);//值是0,代表数组创建了只是没有任何数据
- 其实这个数组是留给用户的,用户可以在控制台输入参数
- 例如这样运行程序:java ArrayTest abc def xyz
- 那么这个时候JVM自动将”abc def xyz“通过空格的方式进行分离,分离完成之后,自动放到“String[] args”数组中
- 把abc def xyz 转换成字符串数组{“abc”,“def”,“xyz”}
-


-
-
数组的扩容:
- 在Java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
- 数组满了,需要扩容
- Java中对数组的扩容:先建一个大容量的数组,然后将小容量的数组中的数据一个一个拷贝到大数组当中
- 结论:数组扩容效率较低,因为涉及到拷贝的问题,所以在以后的开发中请注意,尽可能少的进行数组的拷贝,可以在创建对象的时候预估计多少合适,最好预估准确,这样可以减少数组的扩容次数,提高效率
-


-

-
二维数组:
- 二维数组其实是一个一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组
- 三维数组其实是一个二维数组,特殊在这个二维数组当中的每一个元素是一个一维数组
- 二维数组的静态初始化:
- int[][] a={{1,2,3,},{4},{5,6,7}};
- int[][] array=new int[][]{{1,2,3,},{4},{5,6,7}};
-


-
二维数组的动态初始化:
- int array[][]=new int[3][4];
- 二维数组其实是一个一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组
- 常见的算法:
- 排序算法:冒泡排序、选择排序.......
- 查找算法:二分法查找
- 以上的算法其实在Java中已经封装好了,直接调用就可以,只不过面试可能会碰上
- 算法在Java中不需要精通,Java已经封装好,要排序调用方法就行,例如:Java中提供了一个数组工具类:
- java.util.Arrays;//Arrays是一个工具类,其中sort()方法可以排序,是静态方法,直接使用类名调用就行
-


- 冒泡排序:
-
-
选择排序:
- 选择排序比冒泡排序的效率高,高在交换位置的次数上,选择排序的交换位置是有意义的
- 循环一次,然后找出参加比较的这对数据中最小的,拿着这个最小的值和最前面的数据交换位置
-


-
选择排序和冒泡排序的比较次数没变,但是交换次数明显减少了
-
二分法查找:二分法查找要建立在排序的基础之上
-

-

-
二分法查找效率要高于“一个挨着一个”的这种查找方式
-
二分法查找算法的终止条件:一直折半,直到中间的那个元素恰好是被查找的元素
-

-

-
-
Arrays工具类:
- Arrays是SUN公司为程序员已经写好的一个工具类
- java.util.Arrays
- int[] arr={10,21,30,5,3,8,19,22};
- Arrays.binarySearch(arr,22);//用来对数组进行二分法查找
- Arrays.sort(arr);//用来对数组进行排序
- 一维数组:
- String类
-

-

-
无论String a=“abc”;还是String a=new String("abc");a中都保存的是内存地址
-


-
所以字符串比较的时候不能用双等号,双等号不保险 ,String类已经重写了equals方法,所以应该调用String类的equals方法
-
String a="abc", a.equals("abc"); 和 "abc".equals(a) 建议使用 "abc".equals(a),可以避免空指针异常
- 关于String类的常用构造方法:
-
-
String类的常用方法:
- charAt方法:
-
-
compareTo方法:
-
-
contains方法
-
-
endsWith方法
-
- startWith方法
-
-
equals方法
-
-
-
-
equalsIgnoreCase方法
- getBytes方法
-
- indexOf方法
-
-
lastIndexOf方法
-
-
isEmpty方法:length长度为0,则为空,
-

- 判断数组长度和字符串长度不一样:
- 判断数组长度是length属性
- 判断字符串长度是length方法
-
- replace方法
-
-
split方法
-
-
substring方法
-
-
toCharArray方法
-
-
toLowerCase方法
-
-
toUpperCase方法
-
-
trim方法
-
-
valueOf方法
-
-
-
-
StringBuffer类
- 思考:我们在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题?
- 因为java中的字符串是不可变的,每一次拼接都会产生新的字符串
- 这样会占用大量的方法区内存,造成内存空间的浪费
- String s="abc";
- s+="hello"; 就以上两行代码,就导致在方法区字符串常量池中创建了3个对象:
- "abc"
- "hello"
- "abchello"
- 如果以后需要进行大量的字符串拼接操作,建议使用JDK中自带的:
- java.lang.StringBuffer
- java.lang.StringBuilder
- 如何优化StringBuffer的性能?
- 在创建StringBuffer的时候尽可能给定一个初始化容量
- 最好减少底层数组的扩容次数(因为每扩容一次底层就会调用System.arraycopy方法),预估计一下,给一个大一点些的初始化容量
- String不可变:
-
- StringBuffer可变:
-
-

-

-
StringBuffer和StringBuilder区别:
- StringBuffer中的方法都有:synchronizaed关键字进行修饰,表示StringBuffer在多线程环境下是安全的
- StringBuilder中的方法都没有:synchronizaed关键字进行修饰,表示StringBuilder在多线程环境下运行是不安全的
- 思考:我们在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题?
- 包装类:
- 装箱和拆箱:
- 装箱:自动将基本数据类型转换为包装器类型;
- 拆箱:自动将包装器类型转换为基本数据类型
-


-

-

- 构造方法
-
- 访问最大值和最小值
-
-
自动装箱和拆箱
-
- 数字格式化异常:
-
-
字符串转换为int类型
-
-


-

-

- 装箱和拆箱:
-
java对日期的处理
-

-

- 注意:字符串的格式的日期格式和SimpleDateFormat对象指定的日期格式要一样,不然会出现异常
-
获取自1970年1月1日 00:00:00 000到当前系统的总毫秒数
-
-
-
简单总结一下System类相关属性和方法:
-
- System.out【out是System类的静态变量】
- System.out.println()【println()方法不是System类的,是PrintStream类的方法】
- System.gc()【建议启动垃圾回收器】System.currentTimeMillis【获取自1970年1月1日 00:00:00 000到当前系统的总毫秒数】
- System.exit(0)【退出JVM】
-
- 数字格式化:
-
-
BigDecimal
-
-
Random
-
-
枚举
-

-
思考:以上的这个方法设计没毛病,挺好,返回true和false两种情况,但是在以后的开发中,有可能遇到一个方法的执行结果可能包括三种情况,四种情况,五种情况等等,但是每一种情况都是可以数清楚的,一枚一枚列举出来的,这个布尔类型就无法满足了,此时需要使用Java中的枚举类型
-
枚举:一枚一枚列举出来的,才建议使用枚举类型
- 枚举编译之后也是生成class文件
- 枚举也是一种引用数据类型
- 枚举怎么定义:
- enum 枚举类型名{
- 枚举值1,枚举值2;
- }
- enum 枚举类型名{
- 结果只有两种情况的建议使用布尔类型,结果超过2种并且还是可以一枚一枚列举出来的,建议使用枚举
- 例如:颜色、四季、星期
-

-
-
异常:

-


- UML(统一建模语言):
- 画UML图的工具有很多,例如Rational Rose(收费的)、starUML等...
- 什么是UML?有什么用?
- UML是一种统一建模语言
- 一种图标式语言(画图的)
- UML不是只有java中使用,只要是面向对象的编程语言,都有UML
- 一般画UML图的都是软件架构师/系统分析师,这些级别的人员使用的
- 在UML图中可以描述类和类之间的关系,程序执行的流程,对象的状态等
- 在Java软件开发当中,java软件开发人员必须能看懂
-
java异常的结构图:
-

-
编译时异常又被称为受检异常/受控异常,运行时异常又被称为未受检异常/未受控异常
编译时异常和运行时异常,都是在运行阶段发生的,因为程序只有在运行阶段才可以new对象,异常的发生就是new异常对象,编译阶段异常是不会发生的,
-
编译时异常为什么而得名?
- 因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,而得名
- 编译时异常和运行时异常区别:
- 运行时异常一般发生的概率比较低
- 举个例子:
- 你看到外面下雨,倾盆大雨
- 你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)
- 而且这种异常的概率很高,所以我们出门之前要拿一把伞
- 拿一把伞就是对生病异常的发生之前的一种处理方式
- 小明走在街上,可能会被天上的飞机轮子砸到
- 被飞机轮子砸到也算一种异常,
- 但是这种异常发生概率低
- 在出门之前你没必要对这种发生概率较低的异常进行预处理
- 如果你预处理这种异常,你将活得很累
- 举个例子:
- 假设Java中没有对一场进行划分,没有分为,编译时异常和运行时异常,所有的异常都需要在编写程序阶段进行预处理,将是怎样的效果呢?
- 首先,这样的话,程序的绝对安全的,但是程序员编写代码太累,到处都是处理异常的代码
- 运行时异常一般发生的概率比较低
-
- Java语言对异常的处理方式包括两种:
- 第一种方式:在方法的声明位置使用throws关键字
- 异常发生之后,如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生了,只有一个结果,终止java程序
- 第二种方式:使用try...catch方式进行异常的捕捉
- 第一种方式:在方法的声明位置使用throws关键字
-

-
异常处理方式代码:
- 向上抛:
-
-
try...catch
-
- 向上抛:
-
注意:
-
只要异常没有捕捉,采用上报的方式,后续的代码就不会执行
-
另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行
- try..catch捕捉异常之后,后续的代码可以执行
-
- try..catch深入
- catch小括号中的类型,可以是具体的异常类型,也可以是异常类型的父类型
- catch可以写多个,建议catch的时候,精确的一个一个处理,这样有利于程序的调试
-
-
catch写多个的时候,从上到下,必须从小到大
- JDK8的新特性:
-
-
异常对象有两个非常重要的方法:
- 获取异常简单的描述信息
- String msg=exception.getMessage();
- 打印异常追踪信息
- exception.printStackTrace();
-


- 获取异常简单的描述信息
- 发生异常和打印堆栈信息
- 发生异常
-
- 打印堆栈信息
-
- 发生异常
-
我们以后查看异常追踪信息,应该怎么看,可以快速调试程序?
- 异常追踪信息,从上往下一行一行看
- 但需要注意,SUN公司写的代码就不用看了(看包名就知道是自己的还是SUN的),主要问题是出现在自己编写的代码上
- finally
- 补充:如果初始化的语句用在try块中或if块中,也必须要让它在第一次使用前一定能够得到赋值。也就是说,把初始化语句放在只有if块的条件判断语句中编译器也会抗议,因为执行的时候可能不符合if后面的判断条件,如此一来初始化语句就不会被执行了,这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句,就可以通过编译,因为无论如何,总有至少一条初始化语句会被执行,不会发生使用前未被初始化的事情。对于try-catch也是一样,如果只有在try块里才有初始化语句,编译不通过。如果在catch或finally里也有,则可以通过编译。
-

-

-

-

- 自定义异常类:
-
- finalize()是什么?
- 垃圾回收机器(Garbage Collection),也叫GG,垃圾回收器主要有以下特点:
-
1. 当对象不再被程序所使用的时候,垃圾回收器将会将其回收
-
2. 垃圾回收是在后台运行的,我们无法命令垃圾回收器GC马上回收资源,但是我们可以告诉他可以尽快回收资源(System.gc()和Runtime.getRuntime().gc())
-
3. 垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize()方法
-
4. GC主要针对堆内存
-


-
final、finalize、finally的区别?
- final是一个关键字,表示最终的,不可变的
- finally也是一个关键字,和try联合使用,使用在异常处理机制中,finally语句块中的代码是一定会执行的
- finalize()是Object类中的一个方法,作为方法名出现,所以finalize是标识符,这个方法是由垃圾回收器GC负责调用的
- throws和throw区别
- throws在方法的声明位置上使用,表示上报异常给声明者
- throw手动抛出异常
- 集合
- 什么是集合?有什么用?
- 数组其实就是一个集合,集合实际上就是一个容器,可以来容纳其他类型的数据,但数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型
- 集合为什么说在开发中使用较多?
- 集合是一个容器,是一个载体,可以一次容纳多个对象,在实际开发中,假设连接数据库,数据库当中有10条数据,那么假设把这10条记录查询出来,在Java程序中会将10条数据封装成10个Java对象,然后将10个Java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将数据一个个展现出来
- 集合不能直接存储基本数据类型的数据,另外集合也不能直接存储java对象,集合当中存储的是java对象的内存地址(或者说,集合存储的是引用)
- list.add(100);//自动装箱Integer
- 注意:
- 集合在java中本身是一个容器,是一个对象
- 集合中任何时候存储的都是引用
- 数组和集合的区别:
- 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型
- 当我们需要保存一组类型相同的数据的时候,我们应该是用一个容器来保存,这个容器就是数组,但是,使用数组存储对象具有一定的弊端, 因为我们在实际开发中,存储的数据的类型是多种多样的,于是,就出现了“集合”,集合同样也是用来存储多个数据的。
- 集合的内存空间可以连续也可以不连续,元素类型可以相同也可以不同
-

-
在java中每一个不同的集合,底层会对应不同的数据结构,往不同的集合中存储元素,等于将数据放到了不同的数据结构当中,什么是数据结构? 数据存储的结构就是数据结构,不同的数据结构,存储方式不同,例如:数组、二叉树、链表、哈希表等等
- 在Java集合这一章,需要掌握的不是精通数据结合,Java中已经将数据结构实现了,已经写好了常用的集合类,你只需要掌握怎么用?在什么情况下选择哪一种集合去使用即可
- 集合在java.util.*;下,所有的集合类和集合接口都在java.util包下
- java集合分为两大类:
- 一类是单个方式存储元素:
- 单个方式存储元素,这一类集合中的超级父接口:java.util.Collection
- 另一类是键值对儿的方式存储元素:
- 以键值对的方式存储元素,这一类集合中的超级父接口:java.util.Map
- 一类是单个方式存储元素:
- 集合的继承结构图
-

-

- 类之间的关系
- 依赖:一个类作为另一个类的返回值类型,形参类型,局部变量类型(虚线箭头)
- 关联:一个类作为另一个类的成员变量类型 (实线箭头)
- 继承:子类和父类之间,子接口和父接口之间(实线空心三角)
- 实现:子类和接口之间(虚线空心三角)
-
总结:
- ArrayList:底层是数组
- LinkedList:底层是双向链表
- Vector:底层是数组,线程安全的,效率低,使用较少
- HashSet:底层是HahMap,放到HashSet集合中的元素,等同于放到HashMap集合的key部分了
- TreeSet:底层是TreeMap,放到TreeMap集合中的元素,等同于放到TreeMap集合key部分了
- HashMap:底层是哈希表
- Hashtable:底层是哈希表,只不过是线程安全的,效率较低,很少使用
- Properties:是线程安全的,并且key和value只能存储字符串String
- TreeMap:底层是二叉树,TreeMap集合的key可以自动按照大小顺序排序
-
- 关于java.util.Collection接口中的常用方法
-
-
迭代器:
-






















































