1.集合体系结构分为单列集合Collection和双列集合MapList系列集合添加的元素是有序存和取的顺序一样、可重复、有索引Set系列集合添加的元素是无序、不重复、无索引2.CollectionCollection是单列集合的祖宗接口它的功能是全部单列集合都可以继续使用的。Collection是一个接口不能直接创建对象只能创建实现类的对象比如ArrayList。2.1基本方法Collection里面定义的方法是共性的方法所以不能通过索引对元素进行删除只能通过元素的对象进行删除。contains方法的底层是依赖equals方法进行判断是否存在的。如果集合中存储的是自定义对象也想通过equals来判断是否包含那在JavaBean中要重写equals方法。2.2Collection的遍历方式1迭代器遍历--特点迭代器不依赖索引--迭代器在Java中的类Iterator迭代器是集合专用的遍历方式--Collection集合获取迭代器--Iterator中常用的方法IteratorString it c.iterator();//创建指针 while (it.hasNext()) {//判断是否有元素 String s it.next();//获取元素移动指针 System.out.println(s); }细节--报错NoSuchElementException--迭代器遍历完毕指针不会复位--循环中只能使用一次next方法--迭代器遍历时不能用集合的方法进行增加或者删除。如果实在要删除可以使用迭代器里面的方法remove进行删除2增强for遍历底层就是迭代器为了简化迭代器的代码书写的是jdk5之后出现的其内部原理就是一个iterator迭代器。所有的单列集合和数组才可以用增强for进行遍历。/** * 基本格式 * for(元素的数据类型 变量名数组或集合{ * * } * 修改增强for中的变量不会改变集合中原本的元素 */ for(String s:c){ System.out.println(s); }3Lambda表达式遍历/** * 底层原理自己会遍历集合依次得到每一个元素 * 将得到的元素交给accept方法s表示依次得到的每一个元素 */ c.forEach(new ConsumerString() { Override public void accept(String s) { System.out.println(s); } }); //替换为lambda表达式 c.forEach(s- System.out.println(s));3.List集合3.1基本方法Collection的方法List都继承了但是List有索引remove方法删除元素的细节继承了Collection的remove方法和自己的remove方法在调用方法的时候如果方法出现重载现象优先调用实参类型和形参类型一致的方法如果实在要通过元素进行删除可以手动装箱把数据编程包装类。3.2遍历方式1迭代器遍历2列表迭代器遍历独有的listIterator()迭代器和迭代器差不多使用方法一致但是额外增加了一个方法可以使用add方法添加元素3增强for遍历4Lambda表达式遍历5普通for循环4.ArrayList集合1利用空参创建的集合在底层创建一个默认长度为0的数组2添加第一个元素时底层会创建一个新的长度为10的数组3存满时会扩容1.5倍也就是15--接着再存满时持续扩容4如果一次添加多个元素1.5倍还放不下则新创建数组的长度以实际为准5.LinkedList集合1底层数据结构是双链表查询慢增删快但是如果操作的是首尾元素速度也是极快的2LinkedList本身有很多直接操作首尾元素的特有API6.泛型深入6.1泛型基本概述泛型是jdk5中引入的特性可以在编译阶段约束操作的数据类型并进行检查。泛型格式数据类型注意泛型只能支持引用数据类型泛型的好处1统一数据类型 2把运行时期的问题提前到了编译时间避免了强制类型转换可能出现的异常因为在编译阶段类型就能确定下来拓展Java中的泛型是伪泛型解释编译的时候检查添加的字符串是否符合泛型如果不是直接编译报错细节1泛型中不写基本数据类型2指定泛型的具体类型后传递数据时可以传入该类类型或者其子类类型3如果不写成泛型默认类型是Object6.2泛型的使用泛型可以在很多地方进行定义类后面泛型类方法上面泛型方法接口后面泛型接口1泛型类使用场景当一个类中某个变量的数据类型不确定时就可以定义带有泛型的类格式修饰符 class 类名类型{} 不确定类型时可以把类型写成E就表示是不确定类型此处的E可以理解为变量但是不是用来记录数据的而是记录数据的类型2泛型方法使用场景方法中形参类型不确定的时候可以使用类名后面定义的泛型所有方法都能使用或者在方法申明上定义自己的泛型只有本方法可以使用格式修饰符 类型 返回值类型 方法名类型 变量名{}3泛型接口格式修饰符 interface 接口名类型{}使用方式1实现类给出具体类型 2实现类延续泛型创建对象时再确定6.3泛型的继承和通配符泛型不具备继承性但是数据具备继承性public class test{ public static void main(String[] args) { ArrayListYe list1 new ArrayList(); ArrayListFu list2 new ArrayList(); ArrayListZi list3 new ArrayList(); method(list1); //因为泛型不具备继承性 method(list2);//报错 method(list3);//报错 //以下方式不会报错--因为数据可以继承 list1.add(new Ye()); list1.add(new Fu()); list1.add(new Zi()); } public static void method(ArrayListYe list){ } //如果使用E泛型写的话那任何类型的数据都可以装配进去 public staticE void method2(ArrayListE list){ } } class Ye{} class Fu extends Ye{} class Zi extends Fu{}使用通配符解决以上问题? extends E:表示可以传递E或者E所有的子类类型? super E:表示可以传递E或者E所有的父类类型应用场景1.如果在定义类、方法、接口的时候如果类型不确定就可以定义泛型类、泛型方法、泛型接口2.如果类型不确定但是能指定以后只能传递某个继承体系中的就可以使用泛型的通配符7.Set集合Set集合的特点无序、不重复、无索引Set接口中的方法上基本与Collection的API一致7.1HashSet无序、不重复、无索引HashSet集合底层是采取哈希表存储数据。哈希表是一种对于增删改查数据性能都比较好的结构在jdk8之前哈希表是由数组链表组成的在jdk8开始哈希表是由数组链表红黑树组成的哈希值哈希值对象整数的表现形式哈希值是根据hashCode方法算出来的int类型的整数该方法定义在Object类中所有对象都可以调用默认使用地址值进行计算一般情况下会重写hashCode方法利用对象内部的属性值计算哈希值对象的哈希值特点如果没有重写hashCode方法不同对象计算出的哈希值是不同的如果已经重写hashCode方法不同的对象只要属性值相同计算出的哈希值就是一样的在小部分情况下不同的属性值或者不同的地址值计算出来的哈希值也有可能一样哈希碰撞hashSet的底层原理jdk8以后当链表长度超过8且数组长度大于等于64时自动转换为红黑树如果集合中存储的是自定义对象必须要重写hashCode和equals方法7.2LinkedHashSet有序、不重复、无索引底层原理底层数据结构依然是哈希表知识每个元素又额外的多了一个双链表的机制记录存储顺序。7.3TreeSet可排序、不重复、无索引底层原理TreeSet集合底层是基于红黑树的数据结构实现排序的增删改查性能都比较好TreeSet默认的规则对于数值类型Integer、double默认找从小到大的顺序进行排序对于字符、字符串类型按照字符在ASCII码表中的数字升序进行排序TreeSet的两种比较方式方式一默认排序/自然排序Javabean类实现Comparable接口指定比较规则方式二比较器排序创建TreeSet对象时候传递比较器Comparable指定规则使用规则默认使用第一种如果第一种不能满足当前需求就使用第二种8.双列集合特点1双列集合一次需要存一对数据分别为键和值2键不能重复值可以重复3键和值是一一对应的每一个键只能找到自己对应的值4键值这个整体称之位键值对Map常见APIMap是双列集合的顶层接口它的功能是全部双列集合都可以继承使用的put添加元素的时候如果键不存在那么直接把键值对对象添加到map集合当中方法返回null。如果键存在那么原有的键值对对象被覆盖会把被覆盖的值进行返回。Map的遍历方式1键找值map.keySet();获取键集合map.get(key);获取值2键值对SetMap.EntryString, String entries map.entrySet();获取键值对对象String key entry.getKey(); String value entry.getValue();获取键和值3Lambda表达式8.1HashMapHashMap的特点1HashMap是Map里面的一个实现类2没有额外需要学习的特有方法直接使用Map里面的方法就可以了3特点都是由键决定的无序、不重复、无索引4hashMap和hashSet的底层原理是一样的都是哈希表结构的依赖hashCode和equals方法保证键的唯一性。如果键存储的是自定义对象需要重写hashCode和equals方法如果值存储的是自定义对象不需要重写hashCode和equals方法8.2LinkedHashMap特点1由键决定有序存和取的顺序一样、不重复、无索引2原理底层数据结构是哈希表只是每个键值对元素额外多了一个双链表的机制记录存储顺序8.3TreeMap特点1TreeMap跟TreeSet底层原理一样都是红黑树结构的2由键决定特性不重复、无索引、可 排序对键进行排序3默认按照键的从小到大进行排序也可以自己规定键的排序规则书写两种排序规则1实现Comparable接口指定比较规则2创建集合时进行传递Comparator比较器对象指定比较规则9.Collectionsjava.util.Collections是集合类工具。作用Collections不是集合而是集合的工具类常用API10.不可变集合应用场景1如果某个数据不能被修改把它防御性地拷贝到不可变集合中是个很好的实践。2或者当集合对象被不可信的库调用时不可变形式是安全的。在List、Set、Map接口中都存在静态的of方法可以获取一个不可变的集合。一旦创建无法修改、添加、删除只能进行查询操作。三个方法的细节List直接使用Set元素不能重复Map元素不能重复、键值对数量最多10个超过十个用ofEntries方法。jdk10之后还可以使用copyof的方法
Java-集合进阶
1.集合体系结构分为单列集合Collection和双列集合MapList系列集合添加的元素是有序存和取的顺序一样、可重复、有索引Set系列集合添加的元素是无序、不重复、无索引2.CollectionCollection是单列集合的祖宗接口它的功能是全部单列集合都可以继续使用的。Collection是一个接口不能直接创建对象只能创建实现类的对象比如ArrayList。2.1基本方法Collection里面定义的方法是共性的方法所以不能通过索引对元素进行删除只能通过元素的对象进行删除。contains方法的底层是依赖equals方法进行判断是否存在的。如果集合中存储的是自定义对象也想通过equals来判断是否包含那在JavaBean中要重写equals方法。2.2Collection的遍历方式1迭代器遍历--特点迭代器不依赖索引--迭代器在Java中的类Iterator迭代器是集合专用的遍历方式--Collection集合获取迭代器--Iterator中常用的方法IteratorString it c.iterator();//创建指针 while (it.hasNext()) {//判断是否有元素 String s it.next();//获取元素移动指针 System.out.println(s); }细节--报错NoSuchElementException--迭代器遍历完毕指针不会复位--循环中只能使用一次next方法--迭代器遍历时不能用集合的方法进行增加或者删除。如果实在要删除可以使用迭代器里面的方法remove进行删除2增强for遍历底层就是迭代器为了简化迭代器的代码书写的是jdk5之后出现的其内部原理就是一个iterator迭代器。所有的单列集合和数组才可以用增强for进行遍历。/** * 基本格式 * for(元素的数据类型 变量名数组或集合{ * * } * 修改增强for中的变量不会改变集合中原本的元素 */ for(String s:c){ System.out.println(s); }3Lambda表达式遍历/** * 底层原理自己会遍历集合依次得到每一个元素 * 将得到的元素交给accept方法s表示依次得到的每一个元素 */ c.forEach(new ConsumerString() { Override public void accept(String s) { System.out.println(s); } }); //替换为lambda表达式 c.forEach(s- System.out.println(s));3.List集合3.1基本方法Collection的方法List都继承了但是List有索引remove方法删除元素的细节继承了Collection的remove方法和自己的remove方法在调用方法的时候如果方法出现重载现象优先调用实参类型和形参类型一致的方法如果实在要通过元素进行删除可以手动装箱把数据编程包装类。3.2遍历方式1迭代器遍历2列表迭代器遍历独有的listIterator()迭代器和迭代器差不多使用方法一致但是额外增加了一个方法可以使用add方法添加元素3增强for遍历4Lambda表达式遍历5普通for循环4.ArrayList集合1利用空参创建的集合在底层创建一个默认长度为0的数组2添加第一个元素时底层会创建一个新的长度为10的数组3存满时会扩容1.5倍也就是15--接着再存满时持续扩容4如果一次添加多个元素1.5倍还放不下则新创建数组的长度以实际为准5.LinkedList集合1底层数据结构是双链表查询慢增删快但是如果操作的是首尾元素速度也是极快的2LinkedList本身有很多直接操作首尾元素的特有API6.泛型深入6.1泛型基本概述泛型是jdk5中引入的特性可以在编译阶段约束操作的数据类型并进行检查。泛型格式数据类型注意泛型只能支持引用数据类型泛型的好处1统一数据类型 2把运行时期的问题提前到了编译时间避免了强制类型转换可能出现的异常因为在编译阶段类型就能确定下来拓展Java中的泛型是伪泛型解释编译的时候检查添加的字符串是否符合泛型如果不是直接编译报错细节1泛型中不写基本数据类型2指定泛型的具体类型后传递数据时可以传入该类类型或者其子类类型3如果不写成泛型默认类型是Object6.2泛型的使用泛型可以在很多地方进行定义类后面泛型类方法上面泛型方法接口后面泛型接口1泛型类使用场景当一个类中某个变量的数据类型不确定时就可以定义带有泛型的类格式修饰符 class 类名类型{} 不确定类型时可以把类型写成E就表示是不确定类型此处的E可以理解为变量但是不是用来记录数据的而是记录数据的类型2泛型方法使用场景方法中形参类型不确定的时候可以使用类名后面定义的泛型所有方法都能使用或者在方法申明上定义自己的泛型只有本方法可以使用格式修饰符 类型 返回值类型 方法名类型 变量名{}3泛型接口格式修饰符 interface 接口名类型{}使用方式1实现类给出具体类型 2实现类延续泛型创建对象时再确定6.3泛型的继承和通配符泛型不具备继承性但是数据具备继承性public class test{ public static void main(String[] args) { ArrayListYe list1 new ArrayList(); ArrayListFu list2 new ArrayList(); ArrayListZi list3 new ArrayList(); method(list1); //因为泛型不具备继承性 method(list2);//报错 method(list3);//报错 //以下方式不会报错--因为数据可以继承 list1.add(new Ye()); list1.add(new Fu()); list1.add(new Zi()); } public static void method(ArrayListYe list){ } //如果使用E泛型写的话那任何类型的数据都可以装配进去 public staticE void method2(ArrayListE list){ } } class Ye{} class Fu extends Ye{} class Zi extends Fu{}使用通配符解决以上问题? extends E:表示可以传递E或者E所有的子类类型? super E:表示可以传递E或者E所有的父类类型应用场景1.如果在定义类、方法、接口的时候如果类型不确定就可以定义泛型类、泛型方法、泛型接口2.如果类型不确定但是能指定以后只能传递某个继承体系中的就可以使用泛型的通配符7.Set集合Set集合的特点无序、不重复、无索引Set接口中的方法上基本与Collection的API一致7.1HashSet无序、不重复、无索引HashSet集合底层是采取哈希表存储数据。哈希表是一种对于增删改查数据性能都比较好的结构在jdk8之前哈希表是由数组链表组成的在jdk8开始哈希表是由数组链表红黑树组成的哈希值哈希值对象整数的表现形式哈希值是根据hashCode方法算出来的int类型的整数该方法定义在Object类中所有对象都可以调用默认使用地址值进行计算一般情况下会重写hashCode方法利用对象内部的属性值计算哈希值对象的哈希值特点如果没有重写hashCode方法不同对象计算出的哈希值是不同的如果已经重写hashCode方法不同的对象只要属性值相同计算出的哈希值就是一样的在小部分情况下不同的属性值或者不同的地址值计算出来的哈希值也有可能一样哈希碰撞hashSet的底层原理jdk8以后当链表长度超过8且数组长度大于等于64时自动转换为红黑树如果集合中存储的是自定义对象必须要重写hashCode和equals方法7.2LinkedHashSet有序、不重复、无索引底层原理底层数据结构依然是哈希表知识每个元素又额外的多了一个双链表的机制记录存储顺序。7.3TreeSet可排序、不重复、无索引底层原理TreeSet集合底层是基于红黑树的数据结构实现排序的增删改查性能都比较好TreeSet默认的规则对于数值类型Integer、double默认找从小到大的顺序进行排序对于字符、字符串类型按照字符在ASCII码表中的数字升序进行排序TreeSet的两种比较方式方式一默认排序/自然排序Javabean类实现Comparable接口指定比较规则方式二比较器排序创建TreeSet对象时候传递比较器Comparable指定规则使用规则默认使用第一种如果第一种不能满足当前需求就使用第二种8.双列集合特点1双列集合一次需要存一对数据分别为键和值2键不能重复值可以重复3键和值是一一对应的每一个键只能找到自己对应的值4键值这个整体称之位键值对Map常见APIMap是双列集合的顶层接口它的功能是全部双列集合都可以继承使用的put添加元素的时候如果键不存在那么直接把键值对对象添加到map集合当中方法返回null。如果键存在那么原有的键值对对象被覆盖会把被覆盖的值进行返回。Map的遍历方式1键找值map.keySet();获取键集合map.get(key);获取值2键值对SetMap.EntryString, String entries map.entrySet();获取键值对对象String key entry.getKey(); String value entry.getValue();获取键和值3Lambda表达式8.1HashMapHashMap的特点1HashMap是Map里面的一个实现类2没有额外需要学习的特有方法直接使用Map里面的方法就可以了3特点都是由键决定的无序、不重复、无索引4hashMap和hashSet的底层原理是一样的都是哈希表结构的依赖hashCode和equals方法保证键的唯一性。如果键存储的是自定义对象需要重写hashCode和equals方法如果值存储的是自定义对象不需要重写hashCode和equals方法8.2LinkedHashMap特点1由键决定有序存和取的顺序一样、不重复、无索引2原理底层数据结构是哈希表只是每个键值对元素额外多了一个双链表的机制记录存储顺序8.3TreeMap特点1TreeMap跟TreeSet底层原理一样都是红黑树结构的2由键决定特性不重复、无索引、可 排序对键进行排序3默认按照键的从小到大进行排序也可以自己规定键的排序规则书写两种排序规则1实现Comparable接口指定比较规则2创建集合时进行传递Comparator比较器对象指定比较规则9.Collectionsjava.util.Collections是集合类工具。作用Collections不是集合而是集合的工具类常用API10.不可变集合应用场景1如果某个数据不能被修改把它防御性地拷贝到不可变集合中是个很好的实践。2或者当集合对象被不可信的库调用时不可变形式是安全的。在List、Set、Map接口中都存在静态的of方法可以获取一个不可变的集合。一旦创建无法修改、添加、删除只能进行查询操作。三个方法的细节List直接使用Set元素不能重复Map元素不能重复、键值对数量最多10个超过十个用ofEntries方法。jdk10之后还可以使用copyof的方法