一、Set集合概述
Set是Java中的集合框架之一,用来存储一系列的元素。和List不同,Set中的元素不能重复,每个元素是唯一的。
Set有多个实现类,其中最常见的是HashSet和TreeSet。HashSet底层是使用HashMap实现的,而TreeSet则是使用红黑树实现的。HashSet的操作速度比较
快
,但其元素是无序
的;而TreeSet的元素是有序
的,但操作速度相对较慢
。Set的常用方法包括
add()
用来添加元素、remove()
用来删除元素、contains()
用来判断是否包含某个元素、isEmpty()
用来判断集合是否为空、size()
用来获取集合中元素的数量等等。Set是一个很常用的集合框架,常用于需要存储不重复元素的场景中,如去除重复结果、判断两个集合是否相同等等。
二、Set集合特点
set集合的特点:
- 无序 没有修改方法
- 不可重复
由以下代码可以看出:
三、Set集合的遍历
set集合的遍历不像list
集合遍历一样是三种遍历方式了,而是两种:
- foreach
- 迭代器(iterator)
1、foreach
2、iterator
四、set集合的去重
Set集合中的元素不能重复,这就天然地保证了去重的功能。当我们将多个元素添加到Set中时,如果Set中已经存在相同的元素,那么后续添加的相同元素会被自动忽略。
我们为什么要去重,因为如果是添加一个普通的一个元素的话set集合本身是可以去重的,但是如果你是添加一个对象的话他就不能去重了,为什么?因为每个对象他不是同一个地址,所以不能去重,再最后在工作的时候会用别人写的set集合的方法,你不可能叫别人去写,所以是需要自己去写的,所以才需要写set集合的去重。
例如,我们可以创建一个HashSet对象用于去重,然后将多个元素添加进去:
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("cherry");
set.add("apple");
最终的Set中只包含3个元素,分别是"apple"、"banana"和"cherry",而第二个"apple"因为是重复的所以被忽略了。
需要注意的是,元素的去重是基于equals()方法和hashCode()方法来进行的
,如果某个类没有重写这两个方法,不能保证元素能够被正确去重。因此,在创建自己的类并将其存储在Set集合中时,需要注意它的equals()方法和hashCode()方法是否正确实现。
1、元素的去重
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
以上代码会输出1、2、3,表示TreeSet中的元素已经按照升序排序。
输出的结果如下面的一样:
需要注意的是,在使用SortedSet和TreeSet时,元素的排序是基于比较器的,因此需要保证比较器的正确性。另外,在使用TreeSet时,由于它是基于红黑树实现的,所以访问元素的效率比较高。
2、对象的去重
如果是没有进行任何操作就会出现以下的情况:
【重点】
如前面我所说的要去重,是基于equals方法和hashCode方法
五、set集合的排序
Set集合本身的特点是无序
的,即元素的顺序无法保证。如果需要按照某种顺序排序,可以使用SortedSet子接口或TreeSet实现类来实现。
SortedSet是Set接口的子接口,其中的元素可以按照自然顺序或指定顺序进行排序。具体来说,SortedSet要求其中元素必须实现Comparable接口或通过Comparator进行比较。
TreeSet是SortedSet接口的实现类,它是一个基于红黑树的集合,能够保证元素有序。TreeSet提供了多个构造方法,可以用于指定元素的比较器。
例如,我们可以创建一个TreeSet对象,然后将多个元素添加进去,最后通过迭代器进行遍历:
1、自然排序接口(Comparable)
需要我们的类implements Comparable接口:
Comparable是Java中的一个接口,用于比较类的对象的大小关系。它只包含一个方法
compareTo()
,用于比较两个对象之间的大小关系。在实现了Comparable接口的类中,我们可以使用
compareTo()
方法来对对象进行排序和查找操作。此方法返回一个整数值,表示本对象与另一个对象的大小关系。若返回值为0,则表示两个对象相等;若返回值小于0,则表示本对象小于另一个对象;若返回值大于0,则表示本对象大于另一个对象。
例如,我们可以创建一个类Address,实现Comparable接口,然后在其中重写compareTo()
方法:
对象的
/**
*
* @author tgq
*
*/
class Person implements Comparable<Person>{
private int id;
private String name;
private int money;
public Person(int id, String name, int money) {
super();
this.id = id;
this.name = name;
this.money = money;
}
@Override
public int compareTo(Person o) {
// 升序
return this.id - o.id;
// 降序
return o.id - this.id;
}
}
以上代码中,我们对Address类的对象按照city和street进行比较。首先按照city进行比较,如果两个对象的city相等,则按照street进行比较。这样,在使用排序方法对Address类的对象进行排序时,就会按照city和street进行排序。
需要注意的是,使用Comparable接口进行排序时,需要保证被排序的元素类实现了该接口,并且该接口的实现比较器具有可传递性,即如果a > b并且b > c,则a > c。这样可以确保排序的正确性。
2、比较器排序接口(comparator)
Comparator是Java中的一个接口,用于比较类的对象的大小关系。与Comparable不同的是,Comparator独立于被比较的类,可以定义多个比较器,并且可以在使用时动态指定比较器。
Comparator接口只包含一个方法compare(),用于比较两个对象之间的大小关系。此方法返回一个整数值,表示第一个对象与第二个对象的大小关系。若返回值为0,则表示两个对象相等;若返回值小于0,则表示第一个对象小于第二个对象;若返回值大于0,则表示第一个对象大于第二个对象。
1、单个排序
例如,在我们上一个不变的情况下,然后在其中定义多个比较器:
2、多个排序
在原本的基础上做出一点点的改动
需要注意的是,在使用Comparator进行排序时,我们需要保证比较器具有可传递性,即如果a > b并且b > c,则a > c。
这样可以确保排序的正确性。
希望对你们有用!!!