一. 集合的诞生
集合是为了弥补数组的不足而存在。
集合相对于数组优势在于:a.集合的长度可以动态改变;b.集合中能够存放多种类型的数据。
二. 集合的家族
Collection接口是所有单值集合的父接口
List接口与Set接口的区别:
一个集合类的对象就一个集合。
Collection中常用的方法
方法名 | 描述 |
---|---|
add(E e) | 确保此 collection 包含指定的元素(可选操作)。 |
clear() | 移除此 collection 中的所有元素(可选操作)。 |
contains(Object o) | 如果此 collection 包含指定的元素,则返回true |
equals(Object o) | 比较此 collection 与指定对象是否相等 |
isEmpty() | 如果此 collection 不包含元素,则返回true。 |
iterator() | 返回在此 collection 的元素上进行迭代的迭代器。 |
remove(Object o) | 从此 collection 中移除指定元素的单个实例,如果存在的话。 |
size() | 返回此 collection 中的元素数。 |
toArray() | 返回包含此 collection 中所有元素的数组。 |
1、List集合有序,可重复)
ArrayList: 和 LinkedList:
①ArrayList: 底层数据结构是数组,查询快,增删慢
。
②LinkedList: 底层数据结构是链表,查询慢,增删快
。
两者共同缺点: 线程不安全,效率高
Vector:
①优点: 底层数据结构是数组,查询快,增删慢。
②缺点: 线程安全,效率低
小结:底层数据结构特点决定其性能特性
---
2、Set集合—(无序,唯一)
- Set接口是Collection的子接口,表示元素无序且不可重复的集合。
(1)HashSet:
底层数据结构是哈希表
。(无序,唯一)
如何来保证元素唯一性?
1、依赖两个方法:hashCode()和equals()
2、HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
具体实现唯一性的比较过程:
1.存储元素时首先会使用hash()算法函数生成一个int类型hashCode散列值,然后已经的所存储的元素的hashCode值比较,如果hashCode不相等,肯定是不同的对象。
2.hashCode值相同,再比较equals方法。
3.equals相同,对象相同。(则无需储存)
(2)LinkedHashSet:
底层数据结构是链表和哈希表
(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一
LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
(3)TreeSet:
底层数据结构是红黑树
。(唯一,有序)
如何保证元素排序的呢?
1、自然排序
2、比较器排序
如何保证元素唯一性的呢?
1、根据比较的返回值是否是0来决定
2、TreeSet底层数据结构采用红黑树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造)
3、自然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列
,返回0说明两个对象相同,不需要存储;
4、比较器排序要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象
,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;
TreeSet实践案例
①在元素类中定义排序规则
import java.util.TreeSet;
//创建学生类实践
public class Student implements Comparable<Student> {
private String stuNum;
private String stuName;
private String stuSex;
private int stuAge;
public Student(String stuNum, String stuName, String stuSex, int stuAge) {
this.stuNum = stuNum;
this.stuName = stuName;
this.stuSex = stuSex;
this.stuAge = stuAge;
}
public String getStuNum() {
return stuNum;
}
public void setStuNum(String stuNum) {
this.stuNum = stuNum;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuSex() {
return stuSex;
}
public void setStuSex(String stuSex) {
this.stuSex = stuSex;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
@Override
public String toString() {
return "Student{" +
"编号'" + stuNum + '\'' +
", 姓名='" + stuName + '\'' +
", 性别='" + stuSex + '\'' +
", 年龄=" + stuAge +
'}';
}
//重写里面的compareTo()方法
@Override
public int compareTo(Student o) {
// compareTo 的参数o表示集合中已经存在的元素
return this.stuAge - o.stuAge;
}
//案例
public static void main(String[] args) {
//TreeSet<Student> ts = new TreeSet<Student>();
TreeSet<Student> ts =new TreeSet<Student>();
Student s1 = new Student("10001", "Lilei", "M", 20);
Student s2 = new Student("10002", "HanMeimei", "F", 19);
Student s3 = new Student("10003", "Lily", "F", 21);
Student s4 = new Student("10004", "Tom", "M", 22);
ts.add(s1); // [s1]
ts.add(s2); // [s2,s1]
ts.add(s3); // [s2,s1,s3]
ts.add(s4); // [s2,s1,s3,s4]
System.out.println(ts);
}
}
- 比较器中我们按年龄排序,输出结果也是按年龄排序
[Student{编号'10002', 姓名='HanMeimei', 性别='F', 年龄=19},
Student{编号'10001', 姓名='Lilei', 性别='M', 年龄=20},
Student{编号'10003', 姓名='Lily', 性别='F', 年龄=21},
Student{编号'10004', 姓名='Tom', 性别='M', 年龄=22}]
给TreeSet集合指定比较器(未继承接口)
import java.util.Comparator;
import java.util.TreeSet;
public class Student {
private String stuNum;
private String stuName;
private String stuSex;
private int stuAge;
public Student(String stuNum, String stuName, String stuSex, int stuAge) {
this.stuNum = stuNum;
this.stuName = stuName;
this.stuSex = stuSex;
this.stuAge = stuAge;
}
public String getStuNum() {
return stuNum;
}
public void setStuNum(String stuNum) {
this.stuNum = stuNum;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuSex() {
return stuSex;
}
public void setStuSex(String stuSex) {
this.stuSex = stuSex;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
@Override
public String toString() {
return "Student{" +
"编号'" + stuNum + '\'' +
", 姓名='" + stuName + '\'' +
", 性别='" + stuSex + '\'' +
", 年龄=" + stuAge +
'}';
}
//案例
public static void main(String[] args) {
//切记这里是Comparator
Comparator<Student> cptr = new Comparator<Student>() {
//o1表示向集合中新增的元素,o2表示集合中已经存在的元素
public int compare(Student o1, Student o2) {
int i = o1.getStuAge() - o2.getStuAge();
return i;
}
};
TreeSet<Student> ts = new TreeSet<Student>(cptr);
Student s1 = new Student("10001", "Lilei", "M", 20);
Student s2 = new Student("10002", "HanMeimei", "F", 19);
Student s3 = new Student("10003", "Lily", "F", 21);
Student s4 = new Student("10004", "Tom", "M", 22);
ts.add(s1); // [s1]
ts.add(s2); // [s2,s1]
ts.add(s3); // [s2,s1,s3]
ts.add(s4); // [s2,s1,s3,s4]
System.out.println(ts);
}
}
- 输出结果
[Student{编号'10002', 姓名='HanMeimei', 性别='F', 年龄=19},
Student{编号'10001', 姓名='Lilei', 性别='M', 年龄=20},
Student{编号'10003', 姓名='Lily', 性别='F', 年龄=21},
Student{编号'10004', 姓名='Tom', 性别='M', 年龄=22}]
注意:小编我在编辑过程将上例中Comparator打错成Comparable导致自定义程序无法出结果,希望大家用比较器也多注意。
补充:Comparable和Comparator区别
- ①
对于Comparable接口来说,被比较对象所属的类需要直接实现Comparable接口,实现该接口的类被赋予一个自然顺序
,而且该自然顺序只有一个,而Comparator是一个比较器接口,被比较对象所属的类不需要直接实现该接口,可以单独写一个比较器类实现该接口,作为比较对象的一个比较器,对于一个类来说,可以实现多个比较器。 - ②
Comparator可以选择对null进行比较,而Comparable不可以。
主要是因为Comparator的比较对象都是compare方法的参数,而Comparable的比较方法compareTo方法需要对象来调用,而对象为null时(null.compareTo(obj)),会出现异常。
Lambda表达式
是JDK1.8新增的表达式语法,实际上就是一个语法糖,用于对接口中的方法进行实现。
代码修改对比
//切记这里是Comparator
Comparator<Student> cptr = new Comparator<Student>() {
//o1表示向集合中新增的元素,o2表示集合中已经存在的元素
public int compare(Student o1, Student o2) {
int i = o1.getStuAge() - o2.getStuAge();
return i;
}
};
TreeSet<Student> ts = new TreeSet<Student>(cptr);
Lambda表达式的应用
//Lambda表达式
TreeSet<Student> ts2 = new TreeSet<Student>((o1,o2)->o1.getStuAge()-o2.getStuAge());
输出结果一样,但是格式更加简洁
May you find the work you are willing to devote to and love it.
非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤️ 分享👥 留言💬thanks!!!
愿你们奔赴在自己的热爱里!