Java集合进阶(上)
集合
集合在Java开发中应用极为广泛,它其实就是一些常用的数据结构的包装类,分为单列集合(Collecton接口类,例如LinkdeList集合)和双列集合(Map接口类,例如HashMap集合)两种
Collection
Collecion集合体系结构与方法
体系结构
⭐List接口类集合:有序(取出),可重复(集合值),有索引,就是可变数组和链表一类
⭐Set接口类集合:无序,不可重复,无索引,类似于高中数学中的集合
API
Collection通用遍历方法
❀迭代器遍历
什么是迭代器?
迭代器就是一个指向起始地址的指针,循环移动该指针获取其值可以遍历集合
如何遍历集合?
先要了解迭代器的三个方法
遍历代码
public class iterator {
public static void main(String[] args) {
//构造集合并加入元素
Collection<String> list=new ArrayList<>();
list.add("123");
list.add("456");
list.add("789");
list.add("0");
//迭代器遍历
Iterator<String> iterator=list.iterator(); //获取迭代器对象
while(iterator.hasNext()){ //循环条件,即迭代器指向存在元素
String element=iterator.next(); //获取迭代器指向的元素,并指针后移一位
//iterator.remove(); //要删除可用
System.out.println(element);
}
}
}
迭代器注意点
总结
增强for遍历
话不多说直接代码理解
for (String element : list) { System.out.println(element); }
Lambda表达式遍历 (忘记lambda表达式可见Lambda表达式的应用)
list.forEach( element -> System.out.println(element));
Collection集合总结
List集合
List集合是是Collection的第一个子类
API
List遍历
列表迭代器
列表迭代器是List在Collection继承下独有的方法,不同于普通迭代器,列表迭代器可以增加元素,还可以前移迭代器
代码示例
List<String> list1=new ArrayList<>(); ListIterator<String> stringListIterator = list1.listIterator(); //获取列表迭代器 while(stringListIterator.hasNext()){ stringListIterator.remove(); //删除元素 stringListIterator.add("123"); //添加元素 System.out.println(stringListIterator.next()); }
ArrayList
作为List的实现类,ArrayList其实就是可变数组,在数组的基础上增加了扩容机制
代码实现可见 动态数组的实现
LinkedList
LinkedList是List的另一个实现类,其本质是双向链表,在Java中应用极其多
代码实现可见双向链表的实现(Java)-CSDN博客
泛型
为了统一集合中元素的数据类型,泛型出现了!!!
简单来说就是用字母 T 来定义一个不确定数据类型的模板,T代表的是 任意类型
不过Java中的泛型为伪泛型,只在编译时检查元素是否符合集合泛型类型,集合里面元素一律按Object储存,取出元素时会自动强转为泛型指定类型
用< >的就是泛型,List集合就是泛型接口
代码示例
List<String> list1=new ArrayList<>();
泛型类,方法与接口
同C++中泛型一样, 看得懂就行(除非你要当造轮子的大佬)❀ ,不写代码示例偷懒咯
Set集合
Set集合是Collection接口的第二个子类,类似为高中数学中的集合,无序,不可重复,无索引
遍历方法及API
同Collection,偷懒❀
HashSet
本质为数组+链表+红黑树(也是哈希表的组成)
无序(入取),不重复,无索引
底层原理
HashSet集合的底层数据结构是什么
⭐JDK8之前:数组+链表
⭐JDK8之后:数组+链表+红黑树
HashSet添加元素过程
⭐先获取HashCode值,再确定元素添加位置,再直接尾插链表
HashSet为什么存取顺序不同
⭐HashSet存元素时按照HashCode,取元素时从数组左遍历到右边
HashSet为什么无索引
⭐多种数据结构组合,难以确定索引
HashSet利用什么机制去重的
⭐重写HashCode与equals方法,哈希碰撞发生概率小
LinkedHashSet
继承了HashSet,并使用双向链表使元素拥有顺序
TreeSet
本质为红黑树,会为元素自动排序(可自定义规则)
TreeSet的排序规则
TreeSet自定义排序规则
为了解决自定义类的排序规则问题,Java提供了多种自定义排序规则方法
⭐方法一:实现Comparable 接口
实现Comparable接口后重写排序方法
代码示例
public class Student implements Comparable<Student>{ //实现泛型接口并指定数据类型
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//规范2
//姓名属性的获取(get)
public String getName() {
return name;
}
//姓名属性的更改(set)
public void setName(String name) {
this.name = name;
}
//年龄属性的获取(get)
public int getAge() {
return age;
}
//年龄属性的改变(set)
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}//重写规则方法
@Override
public int compareTo(Student o) { //o代表treeSet已有元素
return this.age-o.age; //定义比较规则
}
}
自定义比较规则:this.age-o.age 代表升序排列,反之o.age-this.age代表降序排列,就是C++的比较器原理
this.age-o.age: 当插入元素时,会将插入元素与集合内每一个元素进行compareTo比较得到return值,当return值(即this.age-o.age)为正数时代表当前元素排在已有元素右边,最大值的return值一定全为正(即this.age > o.age),故最大值排最右边,显然为升序排序(个人理解,表达能力不行,谅解❀,形成自己的理解是最好的)
⭐方法二:构造时指定排序
原理一样,这个直接使用带比较规则的构造函数即可,直接看代码示例
TreeSet<String> treeSet=new TreeSet<>((add,exist) -> { return add.length()-exist.length(); });