一.Set系列集合特点
1.无序:存取顺序不一致
2.重复性:不可重复,可以用于去重操作
3.无索引:不可以使用for循环遍历,无法通过索引获取元素,可以通过foreach和Ierator接口遍历
二.Set集合的实现类特点
HashSet:无序、不重复、无索引
LinkedHashSet:有序、不重复、无索引
TreeSet:可排序、不重复、无索引
由于Set是Collection的接口(接口无法被实例化),继承于Collection,所以Set接口中的方法基本上与Collection的相同。
三.Collection接口
方法声明 | 功能描述 |
boolean add(Object o) | 向集合中添加一个元素 |
boolean addAll(Collection c) | 将指定集合c中的所有元素添加到该集合中 |
void clear() | 删除该集合中的所有元素 |
boolean remove(Object o) | 删除该集合中指定的元素 |
boolean removeAll(Collection c) | 删除该集合中包含指定集合c中的所有元素(set集合中只能通过对象删除,set中没有索引) |
boolean isEmpty() | 判断该集合是否为空 |
boolean contains(Object o) | 判断该集合中是否包含某个元素 |
boolean containsAll(Collection c) | 判断该集合中是否包含指定集合c中的所有元素 |
Iterator iterator() | 返回在该集合的元素上进行迭代的迭代器(Iterator),用于遍历该集合所有元素 |
int size() | 获取该集合元素个数 |
Stream<E> stream() | 将集合源转换为有序元素的流对象(JDK 8新方法) |
四.储存Set集合和遍历
1.储存:使用add接口添加字符串
2.遍历:
(1.)迭代器
public static void main(String[] args) {
// 创建set集合对象
Set<String> s=new HashSet<>();
// 添加元素
s.add("123");
s.add("123"); //这个会被删除,set集合不可重复
s.add("456");
s.add("789");
// 迭代器遍历
Iterator<String> it=s.iterator();
while (it.hasNext()){ //判断当前指向的位置是否有元素
String str = it.next();
System.out.println(str);
}
}
(2)增强for
public static void main(String[] args) {
// 创建set集合对象
Set<String> s=new HashSet<>();
// 添加元素
s.add("123");
s.add("123"); //这个会被删除,set集合不可重复
s.add("456");
s.add("789");
// 增强for
for (String string : s) {
System.out.println(string);
}
}
(3)foreach
public static void main(String[] args) {
// 创建set集合对象
Set<String> s=new HashSet<>();
// 添加元素
s.add("123");
s.add("123"); //这个会被删除,set集合不可重复
s.add("456");
s.add("789");
// foreach
s.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
}
运行结果:
五.HashSet
- HashSet底层原理
- HashSet集合底层采取哈希表存储数据
- 哈希表是一种对于增删改查数据性能都较好的结构
- 创建一个默认长度16,默认加载因为0.75的数组,数组名table
- 根据元素的哈希值跟数组的长度计算出应存入的位置
- 判断当前位置是否为null,如果是null直接存入
- 如果当前位置不为null,表示有元素,则调用equals方法比较属性值
- 在集合中存储的是自定义对象,必须要重写hashCode
2.Hash值
- 根据hashCode方法算出来的int类型的整数
- 一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值
3.Hash值特点
- 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
- 如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
4HashSet去重
public class Student {
private String stuNo;
private String stuName;
private int stuAge;
private int stuScore;
private Object Integer;
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
public int getStuScore() {
return stuScore;
}
public void setStuScore(int stuScore) {
this.stuScore = stuScore;
}
public Student(String stuNo, String stuName, int stuAge,int stuScore) {
this.stuNo = stuNo;
this.stuName = stuName;
this.stuAge = stuAge;
this.stuScore = stuScore;
}
@Override
public boolean equals(Object o) { //重写equals方法
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return stuAge == student.stuAge && stuScore == student.stuScore && Objects.equals(stuNo, student.stuNo) && Objects.equals(stuName, student.stuName) && Objects.equals(Integer, student.Integer);
}
@Override
public int hashCode() {
return Objects.hash(stuNo, stuName, stuAge, stuScore, Integer);
}//重写hashCode方法
public void printInfo() {
System.out.println("学号: " + stuNo +"姓名:"+stuName+"年龄:"+stuAge+"成绩:"+stuScore);
}
}
测试类:
public static void main(String[] args) {
Student stu1 = new Student("001", "张三", 19, 90);
Student stu2 = new Student("002", "李四", 20, 91);
Student stu3 = new Student("002", "李四", 20, 91);//与第二个相同通过重写hashcode和equals方法进行去重
Set<Student> stus = new HashSet<>();
//true代表添加成功,false代表没有添加成功
System.out.println(stus.add(stu1));//true
System.out.println(stus.add(stu2));//true
System.out.println(stus.add(stu3));//false
}
运行结果:
六.LinkedHashSet
- LinkedHashSet底层原理
- LinkedHashSet存储和取出的元素顺序一致
- LinkedHashSet使用双链表数据结构同来记录存储顺序(双链表的每一个节点都会存储上个节点和下个节点的地址)
2.LinkedHashSet的特点
- LinkedHashSet打印时和添加时的顺序是一样的
- 去重:与HashSet相似(需要重写equals和hashCode)
- 遍历:与HashSet相似(Iterator ,增强for,foreach)
- 数据去重优先选择HashSet,如果存取需要有序才使用LinkedHashSet
七.TreeSet
- TreeSet的特点
- 不重复、无索引、可排序
- 可排序:按照元素的默认规则(由大到小)排序
- TreeSet增删改查性能比较好
2.TreeSet遍历
- Iterator
- 增强for
- forEach
3.TressSet排序
- 匿名内部类
public static void main(String[] args) {
// TODO Auto-generated method stub
Student stu1=new Student("001", "张三", 20, 95);
Student stu2=new Student("002", "李四", 19, 92);
Student stu3=new Student("003", "王五", 22, 98);
Student stu4=new Student("004", "赵六", 21, 93);
Student stu5=new Student("005", "江晋义", 23, 97);
Student stu6=new Student("006", "裴承家", 20, 90);
Student stu7=new Student("007", "傅柏辰", 20, 92);
Student stu8=new Student("008", "林雨晨", 18, 100);
Set<Student> se1=new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getStuScore()-o2.getStuScore();//从小到大排序规则
}
});
se1.add(stu1);
se1.add(stu2);
se1.add(stu3);
se1.add(stu4);
se1.add(stu5);
se1.add(stu6);
se1.add(stu7);
se1.add(stu8);
for (Student student : se1) {//集合遍历
student.printInfo();
}
}
- 外部类
-
public class Comp implements Comparator<Student> {//调用Comparator接口 @Override public int compare(Student arg0, Student arg1) { // TODO 自动生成的方法存根 return arg1.getStuAge()-arg0.getStuAge();//从大到小排序规则 } } //测试类 public static void main(String[] args) { // TODO Auto-generated method stub Student stu1=new Student("001", "张三", 20, 95); Student stu2=new Student("002", "李四", 19, 92); Student stu3=new Student("003", "王五", 22, 98); Student stu4=new Student("004", "赵六", 21, 93); Student stu5=new Student("005", "江晋义", 23, 97); Student stu6=new Student("006", "裴承家", 20, 90); Student stu7=new Student("007", "傅柏辰", 20, 92); Student stu8=new Student("008", "林雨晨", 18, 100); Comp comp=new Comp(); Set<Student> se2=new TreeSet<>(comp); se2.add(stu1); se2.add(stu2); se2.add(stu3); se2.add(stu4); se2.add(stu5); se2.add(stu6); se2.add(stu7); se2.add(stu8); for (Student student : se2) { student.printInfo(); } } }
第一次写博客,如果有错误的地方欢迎大家提出来,都可以互相交流学习!