java 高级特性
package characteristic; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 封装三大好处 良好的封装减少耦合 类内部的结构可以自由修改(无须修改客户代码) 可以对成员进行精确控制(年龄范围,性别控制等) 隐藏信息,实现细节(对象的属性私有化) protected关键字 尽可能隐藏,但是允许子类的成员访问。 指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。 public 公有的 * */ class Person { protected String name; protected int age = 5; protected String sex; public Person() { // TODO Auto-generated constructor stub System.out.println("父类------" + name); } public Person(int age) { System.out.println(this.age); this.age = age; System.out.println("父类------" + age); } @Override public String toString() { // TODO Auto-generated method stub return "父类-----" + name; } public String getName(){ return name; } public void setName(String name){ this.name = name; } public static void main(String[] args) throws ParseException { } } /** 通过继承(is-a)实现代码的复用。 继承特点 子类拥有父类非private的属性和方法 子类可以拥有自己的属性和方法 子类可以用自己的方式实现父类的方法(重写) */ /** * 构造器 只能被调用,不能被继承,super()调用父类的构造器。 子类会默认调用父类的构造器。 如果没有默认的父类构造器,子类必须显示调用指定父类的构造器,而且必须在子类构造器中的第一行代码实现调用。 * */ class Husband extends Person { private String name; private int age; public Husband() { // TODO Auto-generated constructor stub // 调用父类 super(4); System.out.println("Husband Constrctor....."); } public String toString(){ setName("123"); //调用父类的setName(); return super.toString(); //调用父类的toString方法 } public static void main(String[] args) { Husband husband = new Husband(); System.out.println(husband.getClass().getName()); System.out.println(husband.toString()); } } /** * 向上转型 专用类型向较通用类型转换,所以总是安全的。 可能带来属性和方法的丢失。 * */ class PersonDisplay{ public void display(){ System.out.println("Play Person"); } /** * 重载 * */ static void display(PersonDisplay personDisplay){ personDisplay.display(); } } /** 多态的实现 条件(继承、重写、 向上转型) 实现形式(继承、接口)当子类重写父类的方法被调用时,只有对象继承链中的最末端的方法才会被调用 1.方法多态 2.引用多态 * */ class HusbandDisplay extends PersonDisplay{ public void display(){ System.out.println("Play Husband"); } public static void main(String[] args) { //HusbandDisplay husbandDisplay = (HusbandDisplay) new PersonDisplay(); //husbandDisplay.display(); PersonDisplay display = new HusbandDisplay(); //向下转型 当子类重写父类的方法 display.display(); //指向子类的父类引用调用 display() 方法时,必调用子类display()方法 //Person.display(husbandDisplay); 向上转型 } } class A { public String show(D obj) { return ("A and D"); } public String show(A obj) { return ("A and A"); } } class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } class C extends B{ } class D extends B{ } /** * 其实在继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O) */ class Test { public static void main(String[] args) { //B 是继承 A A a1 = new A(); A a2 = new B(); B b = new B(); //C 与 D 继承 B C c = new C(); D d = new D(); System.out.println(b.getClass()); System.out.println("1--" + a1.show(b));//"A and A" System.out.println("2--" + a1.show(c));//"A and A" System.out.println("3--" + a1.show(d));//"A and D" System.out.println("4--" + a2.show(b));//"B and A" System.out.println("5--" + a2.show(c));//"B and A" System.out.println("6--" + a2.show(d));//"A and D" System.out.println("7--" + b.show(b));//"B and B" System.out.println("8--" + b.show(c));//"B and B" System.out.println("9--" + b.show(d));//"A and D" } } /** * * 四舍五入 ROUND_UP:远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。 ROUND_DOWN:趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。 ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。 ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。 HALF_UP:最近数字舍入(5进)。这是我们最经典的四舍五入。 HALF_DOWN:最近数字舍入(5舍)。在这里5是要舍弃的。 HAIL_EVEN:银行家舍入法。 * */ /** * clone()方法存在缺陷,并不会将对象的所有属性的全部拷贝过来,而是选择性的拷贝。规则如下 基本类型拷贝其值 对象则拷贝地址引用,也就是说此时新对象与原来对象是公用该实例变量。 String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有对象保持不变。 使用序列化来实现对象的深拷贝。在内存中通过字节流的拷贝是比较容易实现的。把母对象写入到一个字节流中,再从字节流中将其读出来,这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝。 * */ class CloneUtils{ @SuppressWarnings("unchecked") public static <T extends Serializable>T clone(T obj){ T cloneObj = null; try { //写入字节流中 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(obs); obs.close(); //分配内存,写入原始对象,生成新的对象 ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); cloneObj = (T) ois.readObject(); ois.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return cloneObj; } } /** * static * Java把内存分为栈内存和堆内存,其中栈内存用来存放一些基本类型的变量、数组和对象的引用,堆内存主要存放一些对象。static所蕴含“静态”的概念表示着它是不可恢复的,即在那个地方,你修改了,他是不会变回原样的,你清理了,他就不会回来了。 static修饰的方法我们称之为静态方法,我们通过类名对其进行直接调用。由于他在类加载的时候就存在了,它不依赖于任何实例,所以static方法必须实现,也就是说他不能是抽象方法abstract。 static局限 只能调用static变量 只能调用static方法 不能以任何形式引用this、super static变量在定义时必须要进行初始化,且初始化时间要早于非静态变量。 * */ /** * 代码块 * 分为四种 普通代码块 静态代码块 (static),同步代码块(synchronized),构造代码块 * new 一个对象的时候总是先执行构造代码,再执行构造函数 * 构造函数使用场景。 初始化实例变量。利用编译器将构造代码块添加到每个构造函数中。 初始化实例环境。封装逻辑实现部分。 执行顺序为: 静态代码块 > 构造代码块 > 构造函数 * */ class TestBlock{ /** * 构造代码块 * */ { System.out.println("构造代码块"); } /** * 静态代码块 * */ static { System.out.println("静态代码块"); } /** * 无参数代码块 * */ public TestBlock(){ System.out.println("执行无参数构造器"); } } /** * 所有类都继承超类 Object, Object中有equals() 进行内容比较 * instanceof 的作用是判断其左边对象是否为其右边类的实例 * == 是判断俩个对象的内存地址 * */ /** * String * StringBuffer 和 String 一样是用来存储字符串的,内部实现不同,所有的范围不同 * 对于StringBuffer而言,在处理字符串时,若是对其进行修改操作,并不会产生一个新的字符串对象,所以内存使用方面优于 String * StringBuffer 的使用方面它更侧重于对字符串的变化,例如 追加 ,修改 , 删除 * StringBulider 也是一个可变的字符串对象,线程不安全 * String b = "a"; * b+ = "b"; 等同于 * b = new StringBuffer(b).append("b").toString(); * */ /** * final * 编译期常量 * 运行时初始化 * final数据 final方法 final类 final参数 * */ /** * 异常exception * 为何要使用异常 * 确保我们程序的健壮性,提高系统可用 * 异常情形是阻止当前方法或者作用域继续执行的问题 * * Error类 和 Exception 类的父类都是 throwable 类 * Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。 * 常见的error类 * 异常类名 LinkageError 动态链接失败 VirtualMachineError 虚拟机错误 AWTError AWT错误 * * Exception类又分为运行时异常(Runtime Exception)和受检查的异常(Checked Exception ),运行时异常;ArithmaticException,IllegalArgumentException, * 编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用try。。。catch捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。 * * 1. 运行时异常 * ArithmeticException 数学运算异常,比如除数为零的异常 * * IndexOutOfBoundsException 下标越界异常,比如集合、数组等 * * ArrayIndexOutOfBoundsException 访问数组元素的下标越界异常 * * StringIndexOutOfBoundsException 字符串下标越界异常 * * ClassCaseException 类强制转换异常 * * NullpointerException 当程序试图访问一个空数组中的元素,或访问一个空对象中的方法或变量时产生的异常。 * * 2.常见的非运行时异常 * ClassNotFoundException 指定类或借口不存在 * IllegalAccessException 非法访问异常 * Ioexception 输入输出异常 * FileNotFoundException 找不到指定文件异常 * ProtocolException 网络协议异常 * SocketException socke操作异常 * MalformedURLException 统一资源定位符(URL)的格式不正确的异常 * */ class ThrowException{ static void throwOne(int i) throws ArithmeticException{ if(i == 0) throw new ArithmeticException("i值为零"); //用throw 抛出一个异常 } public static void main(String[] args) { try { throwOne(0); } catch (ArithmeticException e) { // TODO: handle exception System.out.println("已捕获到异常错误: "+e.getMessage()); } } } /** * 数组 性能优先考虑数组 Arrays.copy 属于浅拷贝 * 数组 转 list Arrays.asList() * asList 返回的是 一个长度 不可变的列表 .数组是多长,转换成的列表就有多长 .无法通过add,remove 来增加或者减少其长度 * */ class TestArray{ public static void main(String[] args) { String[] array_01 = {"张三","李四","王五"}; String[] array_02 = new String [10]; List<String> list = new ArrayList<String>(); list = Arrays.asList(array_01); } } //集合大家庭 /** * Collection接口 List接口 有序的Collection,实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。 ArrayList ArrayList动态数组,擅长于随机访问。同时ArrayList是非同步的。 LinkedList 双向链表 Vector 同步 Stack set接口 不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。实现了Set接口的集合有:EnumSet、HashSet、TreeSet。 EnumSet 是枚举的专用Set。所有的元素都是枚举类型。 HashSet HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。它内部元素的顺序是由哈希码来决定的,所以它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。 TreeSet 基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现。它是使用元素的自然顺序对元素进行排序,或者根据创建Set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。 Map接口 实现map的有:HashMap、TreeMap、HashTable、Properties、EnumMap。 HashMap 如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构。 TreeMap 键以某种排序规则排序,内部以red-black(红-黑)树数据结构实现,实现了SortedMap接口 HashTable 也是以哈希表数据结构实现的,解决冲突时与HashMap也一样也是采用了散列链表的形式,不过性能比HashMap要低。 * */ //hashCode
package characteristic;
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.text.ParseException;import java.util.ArrayList;import java.util.Arrays;import java.util.List;
/** * 封装三大好处 良好的封装减少耦合 类内部的结构可以自由修改(无须修改客户代码) 可以对成员进行精确控制(年龄范围,性别控制等) 隐藏信息,实现细节(对象的属性私有化) protected关键字 尽可能隐藏,但是允许子类的成员访问。 指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。 public 公有的 * */class Person {protected String name;protected int age = 5;protected String sex; public Person() {// TODO Auto-generated constructor stubSystem.out.println("父类------" + name);}
public Person(int age) {System.out.println(this.age);this.age = age;System.out.println("父类------" + age);}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "父类-----" + name;}public String getName(){return name;}public void setName(String name){this.name = name;}public static void main(String[] args) throws ParseException {}}
/** 通过继承(is-a)实现代码的复用。继承特点 子类拥有父类非private的属性和方法子类可以拥有自己的属性和方法子类可以用自己的方式实现父类的方法(重写) *//** * 构造器 只能被调用,不能被继承,super()调用父类的构造器。子类会默认调用父类的构造器。如果没有默认的父类构造器,子类必须显示调用指定父类的构造器,而且必须在子类构造器中的第一行代码实现调用。 * */class Husband extends Person {private String name;private int age;public Husband() { // TODO Auto-generated constructor stub// 调用父类super(4); System.out.println("Husband Constrctor.....");}public String toString(){setName("123"); //调用父类的setName();return super.toString(); //调用父类的toString方法}public static void main(String[] args) {Husband husband = new Husband();System.out.println(husband.getClass().getName());System.out.println(husband.toString());}}
/** * 向上转型 专用类型向较通用类型转换,所以总是安全的。 可能带来属性和方法的丢失。 * */class PersonDisplay{public void display(){System.out.println("Play Person");}/** * 重载 * */static void display(PersonDisplay personDisplay){personDisplay.display();}}
/** 多态的实现 条件(继承、重写、 向上转型) 实现形式(继承、接口)当子类重写父类的方法被调用时,只有对象继承链中的最末端的方法才会被调用 1.方法多态 2.引用多态 * */class HusbandDisplay extends PersonDisplay{public void display(){System.out.println("Play Husband");}public static void main(String[] args) { //HusbandDisplay husbandDisplay = (HusbandDisplay) new PersonDisplay();//husbandDisplay.display();PersonDisplay display = new HusbandDisplay(); //向下转型 当子类重写父类的方法 display.display(); //指向子类的父类引用调用 display() 方法时,必调用子类display()方法 //Person.display(husbandDisplay); 向上转型}}
class A { public String show(D obj) { return ("A and D"); }
public String show(A obj) { return ("A and A"); }
}
class B extends A{ public String show(B obj){ return ("B and B"); }
public String show(A obj){ return ("B and A"); } }
class C extends B{
}
class D extends B{
}
/** * 其实在继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)*/class Test { public static void main(String[] args) { //B 是继承 A A a1 = new A(); A a2 = new B(); B b = new B(); //C 与 D 继承 B C c = new C(); D d = new D(); System.out.println(b.getClass()); System.out.println("1--" + a1.show(b));//"A and A" System.out.println("2--" + a1.show(c));//"A and A" System.out.println("3--" + a1.show(d));//"A and D" System.out.println("4--" + a2.show(b));//"B and A" System.out.println("5--" + a2.show(c));//"B and A" System.out.println("6--" + a2.show(d));//"A and D" System.out.println("7--" + b.show(b));//"B and B" System.out.println("8--" + b.show(c));//"B and B" System.out.println("9--" + b.show(d));//"A and D" }}
/** * * 四舍五入ROUND_UP:远离零方向舍入。向绝对值最大的方向舍入,只要舍弃位非0即进位。ROUND_DOWN:趋向零方向舍入。向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。ROUND_CEILING:向正无穷方向舍入。向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。ROUND_FLOOR:向负无穷方向舍入。向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。HALF_UP:最近数字舍入(5进)。这是我们最经典的四舍五入。HALF_DOWN:最近数字舍入(5舍)。在这里5是要舍弃的。HAIL_EVEN:银行家舍入法。 * */
/** * clone()方法存在缺陷,并不会将对象的所有属性的全部拷贝过来,而是选择性的拷贝。规则如下
基本类型拷贝其值对象则拷贝地址引用,也就是说此时新对象与原来对象是公用该实例变量。String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有对象保持不变。使用序列化来实现对象的深拷贝。在内存中通过字节流的拷贝是比较容易实现的。把母对象写入到一个字节流中,再从字节流中将其读出来,这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝。 * */class CloneUtils{@SuppressWarnings("unchecked")public static <T extends Serializable>T clone(T obj){T cloneObj = null;try {//写入字节流中ByteArrayOutputStream out = new ByteArrayOutputStream();ObjectOutputStream obs = new ObjectOutputStream(out);obs.writeObject(obs);obs.close();//分配内存,写入原始对象,生成新的对象ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());ObjectInputStream ois = new ObjectInputStream(ios);cloneObj = (T) ois.readObject();ois.close();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}return cloneObj;}}
/** * static * Java把内存分为栈内存和堆内存,其中栈内存用来存放一些基本类型的变量、数组和对象的引用,堆内存主要存放一些对象。static所蕴含“静态”的概念表示着它是不可恢复的,即在那个地方,你修改了,他是不会变回原样的,你清理了,他就不会回来了。static修饰的方法我们称之为静态方法,我们通过类名对其进行直接调用。由于他在类加载的时候就存在了,它不依赖于任何实例,所以static方法必须实现,也就是说他不能是抽象方法abstract。static局限 只能调用static变量只能调用static方法不能以任何形式引用this、superstatic变量在定义时必须要进行初始化,且初始化时间要早于非静态变量。 * */
/** * 代码块 * 分为四种 普通代码块 静态代码块 (static),同步代码块(synchronized),构造代码块 * new 一个对象的时候总是先执行构造代码,再执行构造函数 * 构造函数使用场景。 初始化实例变量。利用编译器将构造代码块添加到每个构造函数中。 初始化实例环境。封装逻辑实现部分。 执行顺序为: 静态代码块 > 构造代码块 > 构造函数 * */class TestBlock{/** * 构造代码块 * */{System.out.println("构造代码块");}/** * 静态代码块 * */static {System.out.println("静态代码块");}/** * 无参数代码块 * */public TestBlock(){System.out.println("执行无参数构造器");}}
/** * 所有类都继承超类 Object, Object中有equals() 进行内容比较 * instanceof 的作用是判断其左边对象是否为其右边类的实例 * == 是判断俩个对象的内存地址 * */
/** * String * StringBuffer 和 String 一样是用来存储字符串的,内部实现不同,所有的范围不同 * 对于StringBuffer而言,在处理字符串时,若是对其进行修改操作,并不会产生一个新的字符串对象,所以内存使用方面优于 String * StringBuffer 的使用方面它更侧重于对字符串的变化,例如 追加 ,修改 , 删除 * StringBulider 也是一个可变的字符串对象,线程不安全 * String b = "a"; * b+ = "b"; 等同于 * b = new StringBuffer(b).append("b").toString(); * */
/** * final * 编译期常量 * 运行时初始化 * final数据 final方法 final类 final参数 * */
/** * 异常exception * 为何要使用异常 * 确保我们程序的健壮性,提高系统可用 * 异常情形是阻止当前方法或者作用域继续执行的问题 * * Error类 和 Exception 类的父类都是 throwable 类 * Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和和预防,遇到这样的错误,建议让程序终止。 * 常见的error类 * 异常类名 LinkageError 动态链接失败 VirtualMachineError 虚拟机错误 AWTError AWT错误 * * Exception类又分为运行时异常(Runtime Exception)和受检查的异常(Checked Exception ),运行时异常;ArithmaticException,IllegalArgumentException, * 编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。而受检查的异常,要么用try。。。catch捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。 * * 1. 运行时异常 * ArithmeticException 数学运算异常,比如除数为零的异常 * * IndexOutOfBoundsException 下标越界异常,比如集合、数组等 * * ArrayIndexOutOfBoundsException 访问数组元素的下标越界异常 * * StringIndexOutOfBoundsException 字符串下标越界异常 * * ClassCaseException 类强制转换异常 * * NullpointerException 当程序试图访问一个空数组中的元素,或访问一个空对象中的方法或变量时产生的异常。 * * 2.常见的非运行时异常 * ClassNotFoundException 指定类或借口不存在 * IllegalAccessException 非法访问异常 * Ioexception 输入输出异常 * FileNotFoundException 找不到指定文件异常 * ProtocolException 网络协议异常 * SocketException socke操作异常 * MalformedURLException 统一资源定位符(URL)的格式不正确的异常 * */
class ThrowException{static void throwOne(int i) throws ArithmeticException{if(i == 0)throw new ArithmeticException("i值为零"); //用throw 抛出一个异常}public static void main(String[] args) { try { throwOne(0);} catch (ArithmeticException e) {// TODO: handle exception System.out.println("已捕获到异常错误: "+e.getMessage()); }}}
/** * 数组 性能优先考虑数组 Arrays.copy 属于浅拷贝 * 数组 转 list Arrays.asList() * asList 返回的是 一个长度 不可变的列表 .数组是多长,转换成的列表就有多长 .无法通过add,remove 来增加或者减少其长度 * */class TestArray{public static void main(String[] args) {String[] array_01 = {"张三","李四","王五"};String[] array_02 = new String [10];List<String> list = new ArrayList<String>();list = Arrays.asList(array_01);}}
//集合大家庭/** * Collection接口
List接口
有序的Collection,实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
ArrayList
ArrayList动态数组,擅长于随机访问。同时ArrayList是非同步的。
LinkedList
双向链表
Vector
同步
Stack
set接口
不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。实现了Set接口的集合有:EnumSet、HashSet、TreeSet。
EnumSet
是枚举的专用Set。所有的元素都是枚举类型。
HashSet
HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。它内部元素的顺序是由哈希码来决定的,所以它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。
TreeSet
基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现。它是使用元素的自然顺序对元素进行排序,或者根据创建Set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
Map接口
实现map的有:HashMap、TreeMap、HashTable、Properties、EnumMap。
HashMap
如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构。
TreeMap
键以某种排序规则排序,内部以red-black(红-黑)树数据结构实现,实现了SortedMap接口
HashTable
也是以哈希表数据结构实现的,解决冲突时与HashMap也一样也是采用了散列链表的形式,不过性能比HashMap要低。 * */
//hashCode