集合和数组的区别:
* 长度可变性不同:
* 集合:长度是可以改变的
* 数组:长度是固定不变的
* 元素的数据类型不同:
* 集合:只能存储引用类型数据
* 数组:可以存储基本类型数据,也可以存储引用类型数据
*
* 集合:
* 含义:存储同一种数据类型多个对象的容器
* 分类:
* 单列集合(Collection)
* 含义:存储元素时以"个"为单位
* 双列集合(Map)
* 含义:存储元素时以"对"为单位
*
* Collection接口分类
* List接口
* ArrayList类
* Vector类
* LinkedList类
* Set接口
* HashSet类
* LinkedHashSet类
* TreeSet类
*
* Map接口分类:
* HashMap类
* LinkedHashMap类
* TreeMap类
* Hashtable类
* Properties类
Collection接口
* 接口的特点
* 单列集合的顶级接口
* 接口的位置
* java.util
* 接口的方法
* boolean add(E e)
* 确保此 collection 包含指定的元素(可选操作)。
* void clear()
* 移除此 collection 中的所有元素(可选操作)。
* boolean contains(Object o)
* 如果此 collection 包含指定的元素,则返回 true。
* boolean isEmpty()
* 如果此 collection 不包含元素,则返回 true。
* Iterator<E> iterator()
* 返回在此 collection 的元素上进行迭代的迭代器。
* boolean remove(Object o)
* 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
* int size()
* 返回此 collection 中的元素数
Collection集合的面试题
* 使用多态的形式创建Collection集合对象,而多态的特点主要和方法有关,当多态的对象调用方法,先虚调用父类或父接口中的方法,如果
* 有执行子类或实现类重写后的方法,如果没有,编译报错,在打印集合对象时,其实就是调用集合多态对象的toString(),调用该toString()
* 会先需调用父接口Collection中的toString(),通过查看源码发现Collection接口及其父接口都没有toString(),代码应该编译报错,
* 但实际上并没有报错,为什么?
* 所有的接口都继承Object类抽象形式或者所有的接口都含有Object类中方法的抽象形式
Collection集合通用的遍历方式1:迭代器
*
* Iterator接口
* 接口的特点
* 对 Collection 进行迭代的迭代器。
* 原理:通过单列集合对象获取迭代器对象时,将集合的元素数据存储到迭代器对象中,再针对迭代器对象进行遍历
* 接口的位置
* java.util
* 接口的方法
* boolean hasNext()
* 如果仍有元素可以迭代,则返回 true
* E next()
* 返回迭代的下一个元素。
* void remove()
* 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
迭代器的注意事项:
* 1.迭代器对象只能进行唯一的一轮迭代器,如果多轮迭代,需要每轮重新获取迭代器对象,否则发生没有元素异常NoSuchElementException
* 2.在使用迭代器的过程中,不能针对集合中的元素做任何增删操作,否则发生并发修改异常ConcurrentModificationException
Collection集合通用遍历方式2:增强for
*
* 增强for(JDK5.0)
* 注意:
* 针对迭代器使用的简化方式(本质就是迭代器)
* 格式:
* for (元素数据类型 元素名 : 容器名) {
*
* }
增强for的注意事项:
* 1.增强for的底层其实就是一个迭代器对象
* 2.在使用增强for的过程中,不能针对集合中的元素做任何增删操作,否则发生并发修改异常ConcurrentModificationException
* 3.增强for既可以遍历集合,也可以遍历数组,但是不推荐使用增强for遍历数组
* 原因:使用增强for遍历引用类型数组时,底层会将引用类型数组先转换成Collection集合对象;
* 使用增强for遍历基本类型数组时,底层会将增强for转换为普通for进行遍历
Collection集合通用遍历方式3:Stream流的forEach()
Collection集合通用遍历方式4:forEach()
泛型(JDK5.0):
* 含义:
* 未知的数据类型
* 格式:
* <泛型>
* 注意:
* 1.如果使用泛型,必须在进行类,接口,方法声明的时候声明泛型
* 2.如果使用泛型,必须在合适的时机确认泛型,否则JVM默认确定为Object类型
* 好处:
* 更好的限制数据类型的使用
泛型的基础应用
* 含有泛型的接口,类,方法
*
* 含有泛型的类
* 声明格式:
* public interface 接口名<泛型> {}
* 确认时机:
* 创建类的对象时
* 确认格式:
* 基础JDK6.0(包含)以前,且实现类存在泛型
* 类名<数据类型> 对象名 = new 类名<数据类型>(实参);
* 基础JDK7.0(包含)以后,且实现类存在泛型,新增格式:
* 类名<数据类型> 对象名 = new 实现类类名<>(实参);
* 注意事项:
* 1.确认泛型时,前后<>中的数据类型必须一致,否则编译报错
泛型的基础应用
* 含有泛型的接口,类,方法
*
* 含有泛型的类
* 声明格式:
* public class 类名<泛型> {}
* 确认时机:
* 创建类对象时
* 确认格式:
* 基础JDK6.0(包含)以前,且实现类存在泛型
* 父接口名<数据类型> 实现类对象名 = new 实现类类名<数据类型>(实参);
* 基础JDK7.0(包含)以后,且实现类存在泛型,新增格式:
* 父接口名<数据类型> 实现类对象名 = new 实现类类名<>(实参);
* 实现类不存在泛型:
* 父接口名 实现类对象名 = new 实现类类名(实参);
* 注意事项:
* 1.确认泛型时,前后<>中的数据类型必须一致,否则编译报错
* 2.如果含有泛型的接口含有没有泛型的实现类时,不推荐使用多态形式创建该实现类对象
泛型的基础应用
* 含有泛型的接口,类,方法
*
* 含有泛型的方法
* 声明格式:
* 修饰符 <泛型> 返回类型 方法名 () {}
* 确认时机:
* 调用该方法时
* 确认格式:
* 方法名(实参);
泛型的高级应用:通配符
*
* 通配符:
* 含义:
* 针对含有泛型方法特殊形式的简化
* 前提:
* 该泛型方法的形参列表是一个含有该泛型类或者接口
* 格式:
* 优化前:
* 修饰符 <泛型> 返回类型 方法名 (类名或接口名<泛型> 对象名) {}
* 优化后:
* 修饰符 返回类型 方法名 (类名或接口名<?> 对象名) {}
* 确认时间:
* 调用方法传参时
*
* 通配符的上限和下限
* 通配符上限:
* 格式:<? extends 数据类型>
* 含义:传递的类型必须是该类型本身或者是该类型的子类类型
* 通配符下限:
* 格式:<? super 数据类型>
* 含义:传递的类型必须是该类型本身或者是该类型的父类类型
List接口
* 接口的特点
* 1.List集合都是有序的集合
* 注意:集合的有序性指代存储元素和获取元素的顺序,不是排序的含义
* 有序集合:存储元素的顺序和获取元素的顺序是一致的
* 无序集合:存储元素的顺序和获取元素的数据不是一致的
* 2.List集合都是含有索引的集合
* 集合索引:元素在集合中的位置,从0开始,依次递增,最大的索引长度-1
* 3.List集合都可以存储重复元素
* 4.List集合中索引的实现方式有4种(涉及数据结构)
* 数组结构
* 链表结构
* 队列结构
* 栈结构
* 5.List集合都含有特殊的迭代器
* 接口的位置
* java.util
* 接口的方法
* void add(int index,E element)
* 在列表的指定位置插入指定元素(可选操作)。
* E get(int index)
* 返回列表中指定位置的元素。
* int indexOf(Object o)
* 返回此列表中第一次出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
* int lastIndexOf(Object o)
* 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
* ListIterator<E> listIterator()
* 返回此列表元素的列表迭代器(按适当顺序)。
* E remove(int index)
* 移除列表中指定位置的元素(可选操作)。
* E set(int index,E element)
* 用指定元素替换列表中指定位置的元素(可选操作)。
* List<E> subList(int fromIndex,int toIndex)
* 返回列表中指定的 fromIndex(包括)和 toIndex(不包括)之间的部分视图
List集合的常用方法
* void add(int index,E element)
* 在列表的指定位置插入指定元素(可选操作)。
* E get(int index)
* 返回列表中指定位置的元素。
* int indexOf(Object o)
* 返回此列表中第一次出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
* int lastIndexOf(Object o)
* 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
* ListIterator<E> listIterator()
* 返回此列表元素的列表迭代器(按适当顺序)。
* E remove(int index)
* 移除列表中指定位置的元素(可选操作)。
* E set(int index,E element)
* 用指定元素替换列表中指定位置的元素(可选操作)。
* List<E> subList(int fromIndex,int toIndex)
* 返回列表中指定的 fromIndex(包括)和 toIndex(不包括)之间的部分视图
List集合的遍历方式:6种
* 1.迭代器
* 2.增强for
* 3.Stream流的forEach()
* 4.Iterable接口的forEach()
* 5.List特有迭代器
数组数据结构:
* 含义:
* 其实就是前面学习的对象数组
* 特点:
* 相比链表结构:查询效率高,增删效率低
链表数据结构:
* 含义:
* 其实就是程序中的一个特殊类
* 分类:
* 单向链表
* 链表对象至少含有两个属性:
* 当前元素(数据类型:泛型)
* 下一个链表对象(数据类型:链表类型)
* 双向链表
* 链表对象至少含有三个属性:
* 当前元素(数据类型:泛型)
* 下一个链表对象(数据类型:链表类型)
* 上一个链表对象(数据类型:链表类型)
* 特点:
* 相比数组数据结构:增删效率高,查询效率低
* 注意:
* 链表结构长度越长效率越低
ArrayList类
* 类的特点
* 1.ArrayList集合底层数据结构是数组结构
* 2.ArrayList集合可以存储null元素,在使用ArrayList集合元素之前,先针对元素进行非空校验,防止空指针异常
* 3.ArrayList集合是线程不安全的集合,只适用于单线程程序,如果在多线程中进行使用,需要手动添加线程安全
* 4.ArrayList集合是有序的集合
* 有序集合:存储元素的顺序和获取元素的顺序是一致的
* 5.ArrayList集合是含有索引集合
* 6.ArrayList集合可以存储重复元素
* 7.ArrayList集合适用于List集合的6种遍历方式
* 类的位置
* java.util
* 类的构造器
* public ArrayList()
* 构造一个初始容量为 10 的空列表。
* 类的方法
* 详见Collection接口和List接口的常用方法
* 注意事项:
* 针对多个元素进行查询操作较多的时候
ArrayList集合的源码分析(基于JDK8.0):
* 1.ArrayList集合底层数组的初始容量
* 初始容量是多少取决于创建对象时所选择的构造器
* (1)ArrayList()
* 初始容量:0
* (2)ArrayList(Collection<? extends E> c)
* 初始容量:参数集合的长度
* (3)ArrayList(int initialCapacity)
* 初始容量:自定义
* 2.无参构造器的扩容原理:
* 第一次添加元素时:
* 扩容原理:10
* 后续添加元素时:
* 扩容原理:原来数组长度 + (原来数组长度 >> 1);
* 3.JDK6.0(包含)以前和JDK7.0(包含)以后的区别:
* (1)无参构造器初始容量不同:
* JDK6.0(包含)以前:
* 初始容量:10
* JDK7.0(包含)以后:
* 初始容量:0
* (2)无参构造器的扩容原理不同:
* JDK6.0(包含)以前:
* 扩容原理:(原来数组长度 * 3)/2 + 1;
* JDK7.0(包含)以后:
* 扩容原理:
* 第一次添加元素时:
* 扩容原理:10
* 后续添加元素时:
* 原来数组长度 + (原来数组长度 >> 1);