1、标识符的命名规则和命名规范
命名规则:1、不能使用关键字、标识符;2、不能使用空格; 如果不遵守编译不通过
命名规范:1、包名 xxxyyyzzz; 2、类名(接口名)XxxYyyZzz; 3、变量名(方法名)xxxYyyZzz; 4、常量名: XXX_YYY_ZZZ
2、Java基础类型
按照数据类型分为:
Java数据类型分为两类: 非引用和引用类型: 非引用:byte(1字节)、char(2字节)、short(2字节)、int(4字节)、long(8字节)、float(4字节)、double(8字节)、boolean(1位) 8种类型。 引用数据类型: 类、接口、数组。
long类型需要带上L(l)结尾
float类型需要以F(f)结尾
在Java当中, ‘’为字符; “”为字符串。 ‘好’也是一个字符。
按照在类型声明的位置:
2、整型提升
byte、short、char ->int ->long ->float ->double, char类型和int相加会将char提升为int类型进行运算。
概念: 容量小的类型与容量大的类型进行运算时会自动提升为容量大的类型。
Java当中byte、char、short之间运算时会提升为int类型,最后再降为对应的类型。由于Java类型严格,所以就会报错。必须用int接受。

无符号右移; 无符号右移补0。
2.1 强制类型转化
强制类型转化会存在数据的丢失和精度问题。容量大的转化容量小的。
3、Java关键字的使用
凡是自己的起的变量的名字都是标识符。(包名、类型名、接口名、方法名、 常量名)
4、switch() 里面可以是哪些类型?
byte、short、char、int, 枚举类型、String。
5、数组的初始化方式?
数组是引用类型。
int[] arr = new int[5]; //动态初始化
int[] arr = new int[]{1,2,3,4,5}; //静态初始化
上面的长度一创建就确定啦, 就是不可以修改。
二维数组创建方式:
二维数组类型其实也是一维数组类型。
int[][] arr = new int[5][4];
int[][] arr = new int[5][];
int[][] arr = new int[][] {{1,2,3}, {4,5}, {6,7,8}}; 大小为3行3列
数组初始化会创建默认值: 整形:0; 浮点型:0.0; char:0; boolean: false, 引用类型: null
数组常见的异常为: 1、角标越界问题; 2、空指针问题。
6、所有排序算法以查找算法
冒泡排序: o(n)~o(n^2) 
7、面向对象
7.1 类及类的成员: 属性、方法、构造器、代码块、内部类。
7.2 特点: 封装、继承、多态。
封装: 对代码内部的保护,该隐藏的隐藏起来,不该隐藏的暴露出来。
体现1:对于内部的私有属性可以通过提供共有的接口对外提供。
体现2:不对外暴露的私有方法
体现3:单例模式
体现4:不希望类在包外访问,可以将类设置为缺省的。
继承(extends): 1、提高代码复用性; 2、扩展功能;3、为多态做准备
子类继承父类就会获取父类所有的属性和方法,可能后续会因为父类的私有属性导致子类无法访问而已。
1)Java类只有单继承,所以一个父类可以被很多子类继承,一个子类只能有一个父类
2)子类继承父类,就可以获取父类的属性和方法。
3)子类实例化的时候,会先调用父类的构造器,后调用自己的构造器。
4)没有声明一个类的父类的话,这个类继承于java.lang.Object类。也就是所有的类都继承或间接继承Object
多态: 父类的引用指向子类的对象。多态的实现其实就是虚拟方法的调用, 在编译阶段我们只能调用父类中声明的方法, 在运行期调用子类重写的方法。 编译看左边, 运行看右边。由于这个判断无法在编译阶段确定,只能在运行阶段确定,所以也叫运行时绑定(动态绑定)。
多态分为: 编译时多态 和 运行时多态
this和super调用构造器: 本类重载其他的构造器; 调用父类的构造器。
Java这块每个函数都具有虚函数的特征,区别C++好需要virtual关键字修饰。正是因为这个特征,Java的多态很容易实现。如果使用fianl关键字修饰,就不会存在多态了,编译阶段就会确定是调用哪个方法。
子类实例化过程: 首先调用父类的构造器,然后再调用子类的构造器。先完成父类的初始化,然后在完成子类的初始化。
7.3 类和对象的区别: 类像一个模板, 对象是实例化、实实在在的。
7.4 类和对象创建和执行分为几步: 1、类创建;2、类实例化;3、调用。
7.5 this是本类的引用, super是父类的引用。
7.6 属性和局部变量的区别?
1、局部变量在栈中, 属性在堆中(非static)
2、局部变量不初始化, 属性会自动初始化。
8、函数重载&函数重写
函数重载: 同一作用域相同的函数名、参数类型和个数,参数排布顺序不同就是函数重载,它是在编译阶段就确定好的,也被称为静态绑定。
函数重写:函数体相同(函数名,参数类型和参数排布顺序相同),子类的返回值是父类的返回值的子类即为函数重写。权限修饰符也要一样。
由于在编译阶段无法确定具体行为,也就是调用父类的方法, 在运行阶段就会调用子类重写的方法。因此也被称为动态绑定。
Java这块我们可以通过@Override校验重写是否成功, 如果重写失败会报错。
找到操作数栈的实际类型C, 然后去invokevirtual去在常量区找相符方法, 如果不通过就会按照继承关系依次对C执行查找相符方法,最终找到了则返回这个方法的直接引用执行方法内容,如果没找到则抛出异常 IllegalAccessError 非法访问异常。
但是这样存在一个问题,就是每次遇到一个多态就会网上找几次才能找到? 
因此诞生虚方法表(存放虚方法)
最终多态的底层实现为: 找到操作数栈实际类型C,然后在虚方法表中查找执行。
虚方法表在类加载的链接阶段进行创建。

虚方法和非虚方法?
非虚方法: 如果在编译阶段就确定调用方法版本,在运行期间不会发生变化的。
例如: static修饰的静态方法,final修饰的方法,构造器,私有方法,父类的方法。
除此以外,Java默认每个方法都是虚方法,在运行阶段实际调用可能会发生改变。
9、值传递机制
实参:方法调用时,实际传递给形参的数据
形参:方法定义时,声明的小括号内的参数
如果参数是基础数据类型,此时形参接受的实参的存储的数据值, 如果参数是引用类型,此时形参传递的是地址值。
10、何为JavaBean
JavaBean使用Java写的一个可重复使用的组件。需要满足以下三个条件:
1、类是公共的;2、有一个无参构造函数;3、有属性,并且有set、get方法。
11、MVC设计模式
MVC分为三层: model层、 views层、 controller层, 将web开发流程分层,层次分明。

12、构造器(构造方法)有什么用?
- 创建对象
- 一个类初始化的时候会调用构造器初始化属性。
- 一个类可以创建多个构造器。
- 一个类一定会有一个默认的构造器(无参),如果手写构造器就会覆盖默认的构造器。
- 一个类至少含有一个构造器。
关于类的属性赋值,有几种赋值方式?
默认初始化、显式初始化、构造器初始化
this关键字可以调用哪些结构?
非static属性、 非static方法、 构造器。
Java类中权限修饰符有哪些? 说明各自的权限范围?
权限由高到底: public > protected > 默认 > private
13、可变参数
public static void main(String[] args) {
show(“asd”, “xcx”, “dsd”);
}
public static void show(String … strs) {
for (String str : strs) {
System.out.println(str);
}
}
14、何为向下转型?
将父类引用指向的对象交给子类引用指向。如果说父类指向的是子类,那就是把权限交给子类而已。不会存在安全问题。
使用强转符就可以。
instanceOf关键字
a instanceOf A 检查a对象是否为A的对象,是返回true,否则编译错误。
15、Object对象
所有的类对象都直接或者间接继承了Object类。
16、三者类型转换-基础数据类型、包装类、String 
基本数据类型<—->包装类 自动装箱和拆箱
基本数据类型、包装类—->String, String.valueOf()
String —-> 基本数据类型, 调用包装类的IparseXxx(String s)
可能会出现异常,NumberFormatException
17、main方法
- main方法作为程序的入口
- main是一个普通的静态方法
- main也是我们与控制台交互的方式。 args读取的是控制台输入的信息。
代码块的作用:用于初始化类、对象信息。也只能使用static修饰符。
类的成员: 属性、方法、构造器、代码块。
static修饰的代码块: 随着类的加载而执行, 只执行一次。执行顺序按照先后顺序。
非static修饰的代码块:

17、抽象类以及abstract关键字
随着继承重写越来越深,导致后面都是创建子类,使用父类引用使用。 导致父类基本上不会实例化,不再使用。这样针对这种类型,父类只是定义,不是声明。 就提升为抽象类。
抽象类不能实例化,但是可以有构造器,方便子类继承时调用。
包含抽象方法的类一定是抽象类,反之不成立。
抽象方法只能定义,由子类完成实现。
如果子类继承抽象类,但是没有实现所有的抽象方法,则子类也不能实例化(编译阶段就会报错)(当然普通的方法也可以重写。)
若子类没有重写父类的所有方法, 则子类也是一个抽象类。
- abstract修饰一个类,这个类也是抽象类。
- 包含抽象方法的类是抽象类,但抽象类不一定包含抽象方法
- 抽象类可以有构造器和自定方法
- 子类继承抽象类需要实现所有抽象方法,否则无法实例化,除非也是抽象类。
- abstract只能修饰类、方法;其他的属性都不可以修饰,也不能修饰静态方法,尤其是final。
匿名类使用:
Person person = new Person() {@Overridepublic void eat() {System.out.println("haha");}};
抽象类和接口有哪些共同点和区别?
- 相同点: 不能实例化、都可以被继承
- 不同点: 抽象类有构造器,接口不能声明构造器,抽象类只能单继承,接口能够被多继承。
如果一个类既有继承类又有实现接口,则先写extends后写implements。
模板方法设计模式:
18、interface接口
接口的出现是为了弥补C++多继承。
- 使用interface关键字修饰
- 接口中定义的变量默认为全局常量(则为public static final)
- 接口中是不能定义构造器
- 接口中定义的方法都是抽象方法,子类继承需要全部重写(省略了public abstract)
接口与接口之间可以继承,多继承。
接口也可以实现匿名内部类。
工厂模式:创建对象的实现。实际上最好的实现方式是通过反射的模式进行创建。
如果接口和继承父类中都含有相同的属性,则编译错误。
Java8接口新特性:让接口越来越像类,接口能够提供一定的方法供子类使用。
可以定义静态方法、默认方法。
接口中定义的静态方法只能接口本身调用,子类无法调用。
但是子类可以调用接口的默认方法, 也可以重写。
如果子类继承的父类和实现的接口中声明同名同参数的方法, 默认调用父类的方法,但是对于属性不行。这也是类优先原则。
- 接口定义的静态方法,只能通过接口调用
- 通过实现类的对象,可以调用接口中的默认方法
- 如果子类重写了默认方法, 则调用为重写的默认的。
- 如果继承多个接口中有同名同参数的默认方法, 如果不重写则报错。但是如果有继承类存在该方法,则根据类优先原则使用父类的。可以不重写。
如果想要在子类调用抽象类的默认方法-> 接口名.super.方法名。
19、内部类
内部类分为局部内部类(静态和非静态)和成员内部类(方法类、代码块类、构造器类)。
class Person1 {// 成员内部类class CC {}// 局部内部类public void method() {class AA {}}// 局部内部类{class BB {}}}
- 内部类作为外部类的属性,可以访问外部类的一些信息。
- 可以被static修饰
- 可以被4种不同的权限修饰
- 作为一个类,也可以final、abstract关键字修饰
对于静态内部类实例化对象:Person1.CC cc = new Person1.CC();
非静态内部类实例化对象: Person1 p = new Person1(); Person1.CC cc = p.new CC();
在内部类中无法更改方法中的局部变量。一般安卓开发会使用。
public class InnerClass {public void method() {int num = 10;class AA {public void show() {// 对于num来说, num就是常量,不能更改num = 20;System.out.println(num);}}}}
20、 异常
Java异常分为两类:1、Error; 2、Exception(语法错误和逻辑错误不属于异常)
Error:Java虚拟机无法解决的严重问题。比如StackOverFlowError和OOM。(我们无法通过代码解决)
Exception:空指针、角标越界等等。
- 异常分为编译型异常和运行时异常。
- 编译型异常源文件在被类加载器加载阶段, 而运行时异常则是加载好之后的问题。
- 编译型异常也被称为受查异常,而运行时异常则被称为非受查异常。
- 除了RuntimeException异常,其他的都是编译型异常,受查异常。
- 一般需要异常处理的都是受查异常, 编译时异常。
对于异常处理有两种:1、try-catch; 2、throw
- 即使catch中抛出异常处理return,finally中也会执行。
- 需要注意的是:对于物理方面的资源,连接池,等等需要手动释放,不会自动回收
- 还可以通过throw自定义抛出异常。
- 通过继承Exception类实现自定义异常。
- throw为手动抛出异常,throws表示该方法会抛出什么异常
final和finally和finalize三者的区别?
- final修饰类、属性、方法,无法继承,无法修改,无法重写
- finally无论异常是否发生都会执行
- finalize是类被销毁时所执行的方法。
比较throw和throws的区别?
- throw抛出异常对象,可以手动抛出一个异常。
- throws标记一个方法会抛出什么样的异常,调用该方法需要做异常处理。try-catch-finally
21、String、StringBuilder和StringBuffer区别
1)String是不可变的类,里面的内容不能修改
2)String类无法被继承
String是不可变的类,StringBuilder和StringBuffer是可变的。
- StringBuilder线程不安全,效率高;
- StringBuffer是线程安全的。效率低,它保证线程安全是通过所有方法加synchronzied监视器。
22、日期和时间
- System.currentTimeUnit() : System提供的静态方法,单位毫秒级。
- Date类分为uti提供的,和sql提供的。
- sql下Date继承于util下的Date。
SimpleDateFormat: 时间格式化和解析
:.format(java.util.Date) 格式化
:.prase(“19-12-18 上午11:34”)
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");System.out.println(simpleDateFormat.format(date));// 2022-04-06 07:53:18// 转化为DateString birth = "2020-09-08";SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");System.out.println(simpleDateFormat.parse(birth));// util.Date 转化为 sql.Datejava.sql.Date date1 = new java.sql.Date(date.getTime());
// 日期转化为天数Date date = new Date();System.out.println(date);System.out.println(date.getTime()); //获取毫秒数int days = data.getTime() / (1000*60*60*24) + 1; // 对应的天数
1、calender抽象类(日历类) JDK1.7以前提供的。
2、Java提供了时间管理API(java-Time)1.7之前抛弃了
LocalDate localDate = LocalDate.now(); 2022-04-06LocalTime localTime = LocalTime.now(); 20:36:55.221LocalDateTime localDateTime = LocalDateTime.now(); 2022-04-06T20:36:55.221LocalDateTime localDateTime1 = LocalDateTime.of(2022, 11, 23, 12,23,46); 2022-11-23T12:23:46System.out.println(localDateTime1.getDayOfMonth()); //这个第几天System.out.println(localDateTime1.getDayOfWeek()); //周几System.out.println(localDateTime1.getMonth()); //几月System.out.println(localDateTime1.getMonthValue()); //几月数字System.out.println(localDateTime1.getMinute());//分钟
JDK8提供的DateTimeFormat为新的格式化时间类。
编码和解码:
1、编码:字符串->字节
2、解码:字节->字符串
日期格式化和解析:
1、格式化: 日期->字符串, format
2、解析:字符串->日期,parse
JDK8前后的时间函数对比:
23、比较器Compare
针对对象的排序, 使用java.long.Comparable和 java.util.Comparator两个接口。
Comparable需要继承该接口,并且完成重写。
如果不想继承接口而排序,则使用下面的接口。
java.util.Comparator 定制排序:
TestCompare[] arr1 = new TestCompare[5];arr1[0] = new TestCompare("A", 1);arr1[1] = new TestCompare("B", 2);arr1[2] = new TestCompare("C", 3);arr1[3] = new TestCompare("D", 4);arr1[4] = new TestCompare("E", 5);Arrays.sort(arr1, new Comparator<TestCompare>() {@Overridepublic int compare(TestCompare o1, TestCompare o2) {if (o1.getName().compareTo(o2.getName()) < 0) {return 1;} else if (o1.getName().compareTo(o2.getName()) > 0) {return -1;} else {return o1.getAge() - o2.getAge() > 0 ? -1 : 1;}}});
- Comparable排序,需要继承Comparable接口,并实现CompareTo方法。
- Comparator则不需要继承实现,对于一个对象可以直接定义比较规则。
24、常见类对象
1、System类
- System.exit() 退出
- System.gc() 请求系统垃圾回收,具体回收取决于系统的GC情况和算法和执行情况。

2、Math类
3、BigInteger(可以构建大于Long范围任何精度的整数,大数问题)
4、BigDecimal (对应浮点型)可以支持任意精度的浮点数。
25、枚举类和注解
- 枚举类,当需要定义一组常量,强烈建议使用枚举类。
- 类的对象有限的,确定的,我们称此类为枚举类。
- 如果枚举类只有一个, 使用单例模式。
JDK5之前通过public私有化构造器实现枚举类
5以后用过enmu关键字创建枚举类。
class Season {private final String seasonName;private final String seasonDesc;private Season(String seasonName, String seasonDesc) {this.seasonName = seasonName;this.seasonDesc = seasonDesc;}public static final Season SPRING = new Season("春天", "万物复苏");public static final Season SUMMER = new Season("夏天", "知声了了");public static final Season AUTUMN = new Season("秋天", "枫红落叶");public static final Season MINTER = new Season("冬天", "鹅毛大雪");public String getSeasonName() {return seasonName;}public String getSeasonDesc() {return seasonDesc;}}public enum TestEnmu {SPRING("春天", "万物复苏"),SUMMER("夏天", "酷酷烈日"),AUTUMN("秋天", "秋高气爽"),WINTER("冬天", "冬去春来");private final String name;private final String desc;private TestEnmu(String name, String desc) {this.name = name;this.desc = desc;}public String getName() {return name;}public String getDesc() {return desc;}}// 通过如下方式来使用Season s = Season.SPRING;s.getSeasonName()s.getSeasonDesc()
- 什么是枚举类:类中的对象是有限个,构造器私有化,如果只有一个为单例模式
- 对于枚举使用 public static final
- 对于属性 public final
26、注解
Annotation是代码中里的特殊标记,这些标记在编译、类加载、运行时读取,并执行相应的操作。
可以在不改变原有逻辑的情况下,在源文件中嵌入一些信息。
可以用于修饰包、类、构造器、方法、成员变量、参数、局部变量。
1、自定义注解:
- 自定义注解继承了java.lang.annotation.Anntation接口
- 注解的参数类型只能是String、Class、enum、Annotation类型
- 可以设置默认值default
- 只有一个参数,建议使用value
- 如果一个注解没有成员,则表明这是一个标识作用。

2、元注解
修饰注解的注解则称为元注解。
- Retention:修饰Annotation的证明周期,有SOURCE、CLASS、RUNTIME三种,其中CLASS为默认。如果想要在运行阶段通过反射获取注解,只能声明为RUNTIME中,其他两者更偏向于编译时和运行时校验。
- Target:表示注解能够修饰哪些元素。TYPE(类,接口,枚举类),FIELD(属性),PARAMETER(形参),LOCAL_VARIABLE(修饰局部变量),不选默认全部属性都可以。
- Doucumented:表示修饰的注解被javadoc解析时,保留下来。默认不保留。生成API文档时会有这个标识。
- Inherited:被它修饰的Annotation具有继承性,如果某个子类使用了被Inherited修饰的注解,其子类会自动继承这个注解。子类也能够继承使用父类的注解。
3、通过反射获取注解信息
public static void main(String[] args) {Class<Main01> aClass = Main01.class;Annotation[] annotations = aClass.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation);}}
4、JDK8提供的注解:可重复注解和类型注解
可重复注解:
老的重写方式@MyAnnotations({@TestAnnotation, @TestAnnotation})public @interface MyAnnotations {TestAnnotation[] value();}新的写法通过@Repeatable(MyAnnotations.class)完成重复写绑定// 这个MyAnnotations里面必须和TestAnnotation一定的生命周期和修饰范围和一定的继承性@Repeatable(MyAnnotations.class)@Retention(RetentionPolicy.RUNTIME)@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})public @interface TestAnnotation {String value() default "你好";}@TestAnnotation@TestAnnotationpublic static void main(String[] args) {
类型注解:针对一些特殊的参数进行修饰
能够在类的形参接受这块使用class Generic<@TestAnnotation T> {}这个是不能被使用的,需要添加新的修饰范围TYPE_PARAMETER才可以。ArrayList<@TestAnnotation String> list = new ArrayList<>();这个则是需要修饰范围TYPE_USE修饰即可。
- 何为元注解:对注解进行修饰的注解就是元注解
- Retention修饰生命周期(SOURCE、CLASS、RUNTIME);SOURCE编译检验,但是生成的.class不会包含;CLASS会在.class保留,但是不会在运行时空间保留,默认行为;RUNTIME会运行时内存中。一般通过反射获取注解进行相关操作。
- TARHET修饰范围类型
- 还有JDK8提供可重复直接REPEATED和USETYPE
什么叫注解?
- JDK5新增的功能,在不改变原有代码逻辑的情况下,添加一些标记,这些标记可以在编译,类加载,运行阶段读取。并执行的处理,也就是再不改变原有的逻辑下新增一些判断和处理
- 在EE中,可以代替xml配置进行处理。
JDK内置的注解?
- Override, 编译阶段判断是否重写
- Deprecated, 编译阶段判断该内容过时
- SuppressWarinings,抑制编译器警告
27、集合
Java集合可以分为两个体系: Collection接口和Map接口
- Collection接口: 一组集合的数据(List,Set)
- Map: key-value通过key值获取value
Collection接口:
Map接口:

集合和数组的区别?
- 数组和集合都是对多个数据进行存储和管理的结构,简称Java容器
- 两者都是存储,但是不能持久化,都是在内存中存储
- 数组的存储数据是固定大小的,而集合可以自动扩容。
数组的缺点?
- 一旦初始化,长度不会改变。
- 提供的方法有限,对于增加和删除效率不高。
- 集合的诞生就是为了解决数组的缺点,代替数组。
ArrayList、LinkedList、Vector三者的区别?
- 三者都是实现了List接口,都是对数据进行存储。
- ArrayList和Vector底层都是通过动态的数组的实现的,内存资源连续,空间利用率好,对于数据的增加和删除性能差。便于数据的查询。
- LinkedList底层通过链表实现,空间利用率不高,可能会存在内存碎片,对于数据的增加和删除效率高,但是不能快速查询任意位置的数据。
- ArrayList和Vector,ArrayList线程不安全,效率高,Vector线程安全,效率低。
1、contain()会调用存储对象的equals()方法进行判断是否匹配。
2、ArrayList默认长度为10,新增元素时扩容为原来容量的1.5倍。
Set集合介绍:
HashSet: 存储无序、不可重复的数据。读取效率高, 线程不安全的。
LinkedHashSet: 继承HashSet,遍历其内部数据时,可以按照添加的顺序遍历
TreeSet: 底层通过红黑树实现, 前序遍历得到有序的。
对于HastSet对象比较来说:通过hashCode方法获取哈希值判断是否相等。
所以对于存放在Set中的对象,对应的类一定要重写equals()和hashCode方法。
HashSet实际上就是调用HashMap实现的。
LinkedHashSet继承HashSet, 它能够保证遍历出来的元素按照插入的元素。底层还是和HashSet一样的性能。
底层实现:插入元素有三个,一个前驱引用和后驱引用,按照插入的顺序将元素链接起来形成双向链表。
起始头节点为null。
而对于TreeSet来说底层通过红黑树实现,会进行比较,因此需要存放的元素具有比较的能力。
对于对象来说需要实现comparable方法。
对于HashSet来说,比较两个对象是否相同通过HashCode()判断,而对于TreeSet则是通过对象的比较器来判断的。
集合Collection中存储自定义类的对象,需要自定义对象重写哪些方法?
- equals()方法, 虽然List不会排序,但是remove,contains方法需要判断对象是否相同需要。
- Set中HashSet需要重写HashCode和equals方法, 因为Set要去重,需要判断对象之间是否相同,依据就是HashCode值。而TreeSet需要排序,则需要对象之间重写比较器来进行排序。
可以试试,List不重写equals,remove和contains方法能否使用。
Set提供的remove方法和add方法,会调用equals和hashCode方法匹配。
Map集合介绍
HashMap: 线程不安全,效率高,能够存储null的key和value。
LinkedHashMap: HashMap的子类,他能保证遍历出来的元素是插入的顺序。底层通过链表拼接。
HashTable:老的哈希表。被HashMap替换。 线程安全的,效率低。和Vector一样。不能存储null的key和value。
TreeMap:底层通过红黑树实现的Map。遍历出来按照key排序。
properties: 继承了TreeMap,常用来配置文件。
LinkedHashMap底层维护了一个链表,如果我们Map需要边插入边遍历,我们就可以使用这个容器。提升性能。
JDK7和JDK8哈希表之间的区别?
- jdk7底层是通过数组+链表的形式实现, jdk8通过数组+链表+红黑树实现。
- new HashMap,底层是不会创建长度为16的数组的,只有第一次插入put元素才会创建长度。
- 默认的长度为16。加载因子(长度阈值):0.75。
- jdk7使用Entry, jdk8使用Node。
而LinkedHashMap继承了HashMap, 对于存储的元素来说是链表,而不是元素本身。
Map常用方法:
元视图方法:
- 通过 keySet 可以获取所有key值
- 通过 values 获取所有的value值
- 通过 entrySet 获取所有的key-value值。
Set
