知识网图:
集合类体系结构
1.Collection集合(接口)
1.1 概述
-
是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
-
JDK 不提供此接口的任何直接实现.它提供更具体的子接口(如Set和List)实现
1.2 Collection常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素(指定的对象而非索引,因为Collection定义的是共性的内容) |
boolean removeIf(Object o) | 根据条件进行移除 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中元素的个数 |
1.3 Collection集合遍历
1.3.1 迭代器遍历
-
Iterator<E> iterator(): 返回此集合中元素的迭代器,通过集合对象的iterator()方法得到
-
迭代器中常用方法:hasNext(): 判断当前位置是否有元素可以被取出; next(): 获取当前位置的元素,将迭代器对象移向下一个索引位置;
-
注意:迭代器遍历完毕后指针不复位;循环中只能用一次next()方法;迭代器遍历时不能使用集合的方法进行增加或删除(只能使用迭代器的remove()方法: 删除迭代器对象当前指向的元素 )
1.3.2 增强for遍历
-
它是JDK5之后出现的,其内部原理是一个Iterator迭代器
-
实现Iterable接口的类才可以使用迭代器和增强for(所有单列集合和数组)
-
简化数组和Collection集合的遍历
-
格式(快捷键:集合名.for)
for(集合/数组中元素的数据类型 变量名 : 集合/数组名) {
// 已经将当前遍历到的元素封装到变量中了,直接使用变量即可}
1.3.3 Lambda表达式遍历(forEach方法)
-
格式:集合名.forEach( s -> sout(s) );
1.4 List集合
1.4.1 List集合的概述与特点
-
List集合的概述
-
有序集合,这里的有序指的是存取顺序
-
用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
-
与Set集合不同,列表通常允许重复的元素
-
-
List集合的特点:存取有序,可以重复,有索引
1.4.2 List集合的特有方法
方法名 | 描述 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素(可插入重复元素和null) |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
1.4.3 List集合的子类及其特点
-
ArrayList集合
底层是数组结构实现,查询修改快、增删慢
线程不安全,效率高
空参创建的集合开始时默认初始长度为0,添加第一个元素后长度才为10
ArrayList自动扩容机制,新的容量为原有容量的基础上扩容1.5倍(容量>>1,右移一位,除以2),若不够则扩容为需要添加的内容的长度
-
LinkedList集合
底层是链表结构实现,查询慢、增删快
-
Vector集合
底层是数组(初始容量为10),线程安全效率低
LinkedList特有方法:
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
Vector特有方法:
方法名 | 说明 |
---|---|
public void addElement(E e) | 将指定的元素添加到此列表的末尾,将其大小增加1。 |
public void insertElementAt(E obj, int index) | 在指定的index插入元素 |
removeElementAt(int index) | 删除指定索引处的元素 |
removeAllElements() | 删除所有元素 |
setElementAt(E obj, int index) | 修改指定索引处的元素为obj |
fistElement()/lastElement()/elementAt(int index) | 获取第一个元素/获取最后一个元素/获取指定索引处的元素 |
1.5 Set集合(基本操作继承自Collection)
1.5.1 Set集合概述及其特点
-
不可以存储重复元素
-
无序,存取顺序不一致
-
没有索引,不能使用普通for循环遍历
1.5.2 Set集合子类及其特点
-
HashSet(底层是哈希表):存取无序,元素不重复,无索引
-
LinkedHashSet(底层是哈希表+双向链表,HashSet的子类):存取有序,元素不重复,无索引
-
TreeSet(底层是红黑树,实质是TreeMap集合):可排序,元素不重复,无索引
1.5.3 哈希表结构
JDK1.8之前:数组+链表
JDK1.8之后:数组+红黑树(链表长度超过8,数组长度大于等于64时,链表自动转换为红黑树 )
注:上图步骤5处在1.8之后,新元素会直接挂在老元素的下方
1.5.4 TreeSet集合
特有排序:
-
可以将元素按照规则进行排序(数值默认升序,字符默认ASCII表值升序,字符串则是挨个比较)
-
TreeSet():根据其元素的自然排序进行排序
-
TreeSet(Comparator comparator) :根据指定的比较器进行排序
-
-
自然排序(Comparable):
-
使用空参构造创建TreeSet集合:用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
-
自定义的Student类实现Comparable接口:自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
-
重写接口中的compareTo方法:重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
//用户类
public class Teacher {
private String name;
private int age;
public Teacher() {
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
-
选择器排序(Compartor):
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
//测试类
public class MyTreeSet4 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
@Override
public int compare(Teacher o1, Teacher o2) {
//o1表示现在要存入的那个元素
//o2表示已经存入到集合中的元素
//主要条件
int result = o1.getAge() - o2.getAge();
//次要条件
result = result == 0 ? o1.getName().compareTo(o2.getName()) : result;
return result;
}
});
//创建老师对象
Teacher t1 = new Teacher("zhangsan",23);
Teacher t2 = new Teacher("lisi",22);
Teacher t3 = new Teacher("wangwu",24);
Teacher t4 = new Teacher("zhaoliu",24);
//把老师添加到集合
ts.add(t1);
ts.add(t2);
ts.add(t3);
ts.add(t4);
//遍历集合
for (Teacher teacher : ts) {
System.out.println(teacher);
}
}
}
2.数据结构
2.1 栈结构(先进后出)
2.2 队列结构(先进先出,查询慢,增删快)
2.3 数组结构(查询快,增删慢)
2.4 二叉树(任意一个节点的度要小于等于2 )
2.4.1 二叉查找树(左子树上所有节点的值都小于根节点的值;右子树上所有节点的值都大于根节点的值 )
2.4.2 平衡二叉树(二叉树左右两个子树的高度差不超过1)
平衡二叉树旋转
左旋:
-
就是将根节点的右侧往左拉,原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点
右旋:
就是将根节点的左侧往右拉,原先的左子节点变成新的父节点,并把多余的右子节点出让,给已经降级的根节点当左子节点
平衡二叉树旋转的四种情况
-
左左(一次右旋解决)
-
左左: 当根节点左子树的左子树有节点插入,导致二叉树不平衡
-
如何旋转: 直接对整体进行右旋即可
-
-
左右(局部左旋,整体右旋)
-
左右: 当根节点左子树的右子树有节点插入,导致二叉树不平衡
-
如何旋转: 先在左子树对应的节点位置进行左旋,在对整体进行右旋
-
-
右右(一次左旋)
-
右右: 当根节点右子树的右子树有节点插入,导致二叉树不平衡
-
如何旋转: 直接对整体进行左旋即可
-
-
右左(局部右旋,整体左旋)
-
右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡
-
如何旋转: 先在右子树对应的节点位置进行右旋,在对整体进行左旋
-
2.5 红黑树 (满足红黑规则的二叉查找树)
红黑规则:(节点红或黑,根和叶(Nil)为黑,若红子为黑(两红不相连),点到叶节点路径上黑同)
-
每一个节点或是红色的,或者是黑色的
-
根节点必须是黑色
-
如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
-
如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连 的情况)
-
对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
红黑数添加节点时默认为红色,提高效率
3.泛型
3.1 概念
-
泛型的介绍
泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制
-
泛型的好处
-
把运行时期的问题提前到了编译期间
-
避免了强制类型转换
-
-
泛型的定义格式
-
<类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如: <E> <T>
-
<类型1,类型2…>: 指定多种类型的格式,多种类型之间用逗号隔开.例如: <E,T> <K,V>
-
-
特点
1.泛型中不能写基本数据类型
2.指定泛型后,传递的数据只能是该泛型或其子类型
3.不写泛型默认为Object
3.2 泛型类
-
定义格式:修饰符 class 类名<类型> { }
3.3 泛型方法
-
定义格式:修饰符 <类型> 返回值类型 方法名(类型 变量名) { }
3.4 泛型接口(具体泛型可以在定义实现类或实现类对象时指定)
-
定义格式:修饰符 interface 接口名<类型> { }
3.5 类型通配符
-
类型通配符: <?>
-
ArrayList<?>: 表示元素类型未知的ArrayList,它的元素可以匹配任何的类型
-
但是并不能把元素添加到ArrayList中了,获取出来的也是父类类型
-
-
类型通配符上限: <? extends 类型>
-
ArrayListList <? extends Number>: 它表示的类型是Number或者其子类型
-
-
类型通配符下限: <? super 类型>
-
ArrayListList <? super Number>: 它表示的类型是Number或者其父类型
-
4. Map集合(双列集合)
4.1 Map集合特点
-
双列集合,一个键对应一个值
-
存取无序,键不重复,无索引
4.2 Map集合的成员方法
方法名 | 说明 |
---|---|
V put(K key,V value) | 添加/覆盖元素(当添加时键存在了,则进行覆盖,并返回被覆盖的值) |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
V get(Object key) | 根据键获取值 |
Set<K> keySet() | 获取所有键的集合 |
Collection<V> values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
4.3 Map集合遍历
4.3.1 键找值
-
步骤
-
获取所有键的集合。用keySet()方法实现
-
遍历键的集合,获取到每一个键。用增强for实现
-
根据键去找值。用get(Object key)方法实现
-
4.3.2 键值对
-
步骤
-
获取所有键值对对象的集合
-
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
-
-
遍历键值对对象的集合,得到每一个键值对对象
-
用增强for实现,得到每一个Map.Entry
-
-
根据键值对对象获取键和值
-
用getKey()得到键
-
用getValue()得到值
-
-
4.4 HashMap集合
特点:
-
HashMap底层是哈希表结构的
-
依赖hashCode方法和equals方法保证键的唯一
-
如果键要存储的是自定义类对象,需要重写hashCode和equals方法
4.5 TreeMap集合(排序方法同TreeSet)
特点:
-
TreeMap底层是红黑树结构
-
依赖自然排序或者比较器排序,对键进行排序
-
如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
5. 可变参数
-
可变参数介绍
-
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
-
方法的参数类型已经确定,个数不确定,我们可以使用可变参数
-
-
可变参数定义格式
修饰符 返回值类型 方法名(数据类型… 变量名) { }
-
可变参数的注意事项
-
这里的变量其实是一个数组
-
如果一个方法有多个参数,包含可变参数,可变参数要放在最后,且只能有一个
-
6. 不可变集合
方法介绍
-
在List、Set、Map接口中,都存在of方法,可以创建一个不可变的集合
-
这个集合不能添加,不能删除,不能修改,创建Set和Map集合时元素不能重复,键不能重复
-
但是可以结合集合的带参构造,实现集合的批量添加
-
-
在Map接口中,还有一个ofEntries方法可以提高代码的阅读性
-
首先会把键值对封装成一个Entry对象,再把这个Entry对象添加到集合当中
-
创建Map集合时只能存储20个参数,即10个键值对
-
若创建键值对数超过10个,则使用Map的ofEntries()方法,传入的是键值对对象,需要使用entrySet()方法先获取所有键值对对象,简单的可以直接使用copyOf()(java 10)
-
7.Stream流
-
Stream流的三类方法
-
获取Stream流
-
创建一条流水线,并把数据放到流水线上准备进行操作
-
创建单列集合的Stream流直接调用stream()
-
创建双列集合的Stream流需要先使用keySet()或entrySet()方法转为单列集合再调用stream()方法
-
创建数组的Stream流需要使用Arrays.stream()方法
-
若是创建的是一堆零散的数据的Stream流使用Stream.of()方法
-
-
中间方法
-
流水线上的操作
-
一次操作完毕之后,还可以继续进行其他操作
-
-
终结方法
-
一个Stream流只能有一个终结方法
-
是流水线上的最后一个操作
-
-
7.1 生成Stream流的方法
-
生成Stream流的方式
-
Collection体系集合
使用默认方法stream()生成流, default Stream<E> stream()
-
Map体系集合
把Map转成Set集合,间接的生成流
-
数组
通过Arrays中的静态方法stream生成流
-
同种数据类型的多个数据
通过Stream接口的静态方法of(T... values)生成流
-
7.2 Stream流中间操作方法
方法名 | 说明 |
---|---|
Stream<T> filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Stream<T> limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据(获取前几个) |
Stream<T> skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流(跳过前几个) |
static <T> Stream<T> concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream<T> distinct() | 返回由该流的不同元素(根据Object.equals(Object) )组成的流(若是其它引用数据类型,需要重写hashCode()和equals()方法) |
map(Function<? super T,? extends R> mapper) | 转换流中数据为指定类型 |
7.3 Stream的终结方法
注:执行完此方法之后,Stream流将不能再执行其他操作
方法名 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行操作 |
long count() | 返回此流中的元素数 |
7.4 Stream的收集操作
-
方法名 说明 R collect(Collector collector) 把结果收集到集合中 -
工具类Collectors提供了具体的收集方式
方法名 说明 public static <T> Collector toList() 把元素收集到List集合中 public static <T> Collector toSet() 把元素收集到Set集合中 public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中,keyMapper为键的生成规则,valueMapper为值的生成规则