Java——Set集合类


前言

List:可重复,有序
Set:唯一,无序
常用的子类: HashSet(去重复), TreeSet(可排序),LinkedHashSet(有序)


一、HashSet

1.底层的实现HashMap

在这里插入图片描述
常用方法与List相似,但是没有下标使用的方法
在这里插入图片描述

2.HashSet原理

底层实现: HashMap, HashSet的元素存在HashMap的key上, >

当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准

HashSet 怎么判断这个元素是否存在? 集合中有这个元素, 集合元素与添加元素是同一个元素?

首先判断添加元素的hashCode() 与Set集合中的元素的hashCode() 是否一样, 如果不一样, 直接添加,

如果hashCode() 值在集合中存在, 调用equals() 如果equals() 返回false, 直接添加, 如果返回true, 不会添加

使用HashSet保存自定义的类对象, 这个类一定要重写 hashCode() 与equals()

3.Collection集合(List/Set)的遍历遍历集合: 把集合中的元素一个一个拿出来

List: 集合, 有下标

第一种方式: fori(普通for循环)

for (int i = 0; i <list.size() ; i++) {
      //调用get()
      System.out.println(list.get(i));
  }

第二种方式: 迭代器

//1.得到当前集合对象的迭代器对象
Iterator iter = list.iterator();
//循环遍历
while(iter.hasNext()){
//获取下一个元素,并且移动迭代器指针   next()
System.out.println(iter.next());

}

第三种方式: forEach(增强for循环)

for(Object obj:list){
System.out.println(obj);
}

Set集合: 没有下标, 不能使用fori循环, 只能使用迭代器遍历,或者增强for循环

遍历Collection集合,JDK提供迭代器: Iterator接口, 用于遍历集合

使用迭代器步骤:

​ 1) 得到当前集合对象的迭代器对象: 集合对象.iterator() 往后获取元素

​ 2) 编写while循环, 调用迭代器对象的方法来遍历
在这里插入图片描述
List结合获取Iterator接口的子接口: ListIterator, 既可以往后获取元素, 也可以往前获取元素
在这里插入图片描述
JDK简化迭代器遍历, 提供了forEach循环: 底层使用迭代器

for(数据类型 变量:集合对象/数组){ //每循环一次,从集合/数组拿一个元素赋值给变量
    
    
}

注意:

如果使用迭代器遍历List集合, 在迭代器循环里面,对集合进行删除操作,会报:

java.util.ConcurrentModificationException 并发修改的异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBxHP2TD-1650415068691)(assets/image-20220414205551010.png)]
在这里插入图片描述
在这里插入图片描述

如果使用迭代器的remove() 没有问题
实际开发中, 使用迭代器,删除元素,一定调用的迭代器的remove() 去删除

二、TreeSet

1.特点

TreeSet集合是Set接口的一个实现类,底层依赖于TreeMap,是一种基于红黑树的实现,其特点为:

  1. 元素唯一
  2. 元素没有索引
  3. 使用元素的自然排序对元素进行排序,或者根据创建 TreeSet 时提供的Comparator比较器进行排序,具体取决于使用的构造方法:
    判断元素是否存在,调用hashCode()–>equlas()
    算法,数据结构可视化网站
public TreeSet():								根据其元素的自然排序进行排序
public TreeSet(Comparator<E> comparator):    根据指定的比较器进行排序

在这里插入图片描述

在这里插入图片描述
compareTo方法的实现规则:

返回 0,表示 this == obj。//则不会添加新对象
​返回正数,表示 this> obj //添加到原来对象的右边
返回负数,表示 this < obj // 添加到原来对的左边

使用Comparable 这种方式: 排序方式 已经写死, 动态比较无法实现: 有时需要安装年龄, 有时需要是学号,… 扩展性不好

​ 2) 获取指定Comparator比较器 创建TreeSet时, 才指定排序方式, new TreeSet(Comparator对象), 比Comparable 扩展性好
在这里插入图片描述

返回 0,表示 this == obj。//则不会添加新对象
返回正数,表示 this> obj //添加到原来对象的右边
返回负数,表示 this < obj // 添加到原来对的左边
如果元素的类没有实现Comparable接口, 或者new TreeSet 指定Comparator, 往TreeSet添加元素,抛异常:
在这里插入图片描述

2.演示

案例演示自然排序(20,18,23,22,17,24,19):

public static void main(String[] args) {
	//无参构造,默认使用元素的自然顺序进行排序
	TreeSet<Integer> set = new TreeSet<Integer>();
	set.add(20);
	set.add(18);
  	set.add(23);
  	set.add(22);
  	set.add(17);
  	set.add(24);
  	set.add(19);
  	System.out.println(set);
}

控制台的输出结果为:
[17, 18, 19, 20, 22, 23, 24]

案例演示比较器排序(20,18,23,22,17,24,19):

public static void main(String[] args) {
  	//有参构造,传入比较器,使用比较器对元素进行排序
  	TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {
    	@Override
    	public int compare(Integer o1, Integer o2) {
      		//元素前 - 元素后 : 升序
      		//元素后 - 元素前 : 降序
      		return o2 - o1;
    	}
  	});
  	set.add(20);
  	set.add(18);
  	set.add(23);
  	set.add(22);
  	set.add(17);
  	set.add(24);
  	set.add(19);
  	System.out.println(set);
}

控制台的输出结果为:
[24, 23, 22, 20, 19, 18, 17]

三、排序算法

我们会使用数组来存储多个数据,有时候我们要将数组中的元素进行排序。比如原始数组为{5, 1, 3, 2},排序后为{1, 2, 3, 5}。常见排序算法有:选择排序,冒泡排序,快速排序等。

1.冒泡排序

冒泡排序原理:相邻元素比较,大的往后放
在这里插入图片描述

2.代码演示

public static void main(String[] args) {
    int[] arr = new int[] {55, 22, 99, 88};
    //功能
    //外层循环用来控制数组循环的圈数
    for (int i = 0; i < arr.length-1; i++) {
        //内层循环用来完成元素值比较,把大的元素值互换到后面
        for (int j = 0; j < arr.length-1-i; j++) {
            if (arr[j] > arr[j+1]) {
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    System.out.println(Arrays.toString(arr));
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值