Set集合
- Set集合
特点: 无序,无下标,元素不可重复
方法:全部继承Collection中的方法
- Set集合的方法(全部继承Collection中的方法)
用法 | 解释 |
---|---|
boolean add(E e) | 如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。 |
boolean addAll(Collection<? extends E> c) | 如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。 |
void clear() | 移除此 set 中的所有元素(可选操作)。 |
boolean contains(Object o) | 如果 set 包含指定的元素,则返回 true。 |
boolean containsAll(Collection<?> c) | 如果此 set 包含指定 collection 的所有元素,则返回 true。 |
boolean equals(Object o) | 比较指定对象与此 set 的相等性。 |
int hashCode() | 返回 set 的哈希码值。 |
boolean isEmpty() | 如果 set 不包含元素,则返回 true。 |
Iterator iterator() | 返回在此 set 中的元素上进行迭代的迭代器。 |
boolean remove(Object o) | 如果 set 中存在指定的元素,则将其移除(可选操作)。 |
boolean removeAll(Collection<?> c) | 移除 set 中那些包含在指定 collection 中的元素(可选操作)。 |
boolean retainAll(Collection<?> c) | 仅保留 set 中那些包含在指定 collection 中的元素(可选操作)。 |
int size() | 返回 set 中的元素数(其容量)。 |
Object[] toArray() | 返回一个包含 set 中所有元素的数组。 |
T[] toArray(T[] a) | 返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。 |
- Set接口的使用
public static void main(String[] args) {
Set set = new HashSet();
//添加元素,不可重复,无序
set.add(1);
set.add(2);
set.add(3);
System.out.println("元素个数"+set.size());
System.out.println(set.toString());
//删除
//set.remove(1);
//set.clear();
//遍历
//3.1 增强for
for (Object O: set
) {
Integer integer =(Integer) O;
System.out.println(O);
}
//3.2使用迭代器
Iterator iterator = set.iterator();
while(iterator.hasNext()){
Integer i=(Integer) iterator.next();
System.out.println(i);
}
//判断
System.out.println(set.contains(1));
System.out.println(set.isEmpty());
HashSet
- HashSet实现类的特点
- 基于hashCode计算元素存放位置
- 当存入元素的hash码相同时,会调用equals方法进行确认,如果返回为true,则拒绝后者进入
- 存储结构:数组+链表+红黑树
- HashSet()构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75(加载因子是表示Hsah表中元素的填满的程度,16*0.75=12,容量到了12就开始扩容)。
- HashSet的方法
用法 | 解释 |
---|---|
boolean add(E e) | 如果此 set 中尚未包含指定元素,则添加指定元素。 |
void clear() | 从此 set 中移除所有元素。 |
Object clone() | 返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。 |
boolean contains(Object o) | 如果此 set 包含指定元素,则返回 true。 |
boolean isEmpty() | 如果此 set 不包含任何元素,则返回 true。 |
Iterator iterator() | 返回对此 set 中元素进行迭代的迭代器。 |
boolean remove(Object o) | 如果指定元素存在于此 set 中,则将其移除。 |
int size() | 返回此 set 中的元素的数量(set 的容量)。 |
- HashSet的使用
//添加元素
System.out.println("=============================");
HashSet<String> hashSet = new HashSet();
hashSet.add("张三");
hashSet.add("李四");
hashSet.add("王五");
hashSet.add("老六");
System.out.println("元素个数"+hashSet.size());
System.out.println(hashSet.toString());
//删除元素
System.out.println("=============================");
hashSet.remove("李四");
//hashSet.clear();
//遍历元素
System.out.println("=============================");
//3.1增强for
for (String string:hashSet
) {
System.out.println(string);
}
//3.2使用迭代器Iterator
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断元素
System.out.println("=============================");
System.out.println(hashSet.contains("王五"));
System.out.println(hashSet.isEmpty());
- HashSet的使用2
HashSet<Student> hashSet = new HashSet();
//添加元素
Student s1 =new Student("aaa",15);
Student s2 =new Student("bbb",16);
Student s3 =new Student("ccc",17);
Student s4 =new Student("ccc",17);
hashSet.add(s1);
hashSet.add(s2);
hashSet.add(s3);
//重复的添加不了
hashSet.add(s4);
//存储方式
//1. 根据hashCode计算保存的位置,如果位置为空则直接保存,如果位置不为空执行第二步
//2.执行equals方法,如果返回为true则认为存储的元素重复,不能添加,如果为false则形成链表
hashSet.add(new Student("ddd",20));
System.out.println("元素个数"+hashSet.size());
System.out.println(hashSet.toString());
//删除元素
hashSet.remove(s3);
System.out.println("删除之后"+hashSet.size());
System.out.println(hashSet.toString());
//3.遍历
//3.1使用迭代器Iterator
Iterator iterator =hashSet.iterator();
while (iterator.hasNext()){
System.out.println( iterator.next());
}
//3.2使用增强for
for (Student s:hashSet
) {
System.out.println(s);
}
//判断
System.out.println(hashSet.contains(s2));
System.out.println(hashSet.isEmpty());
Student类中重写的hashCode方法和equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null ) return false;
if(o instanceof Student) {
Student student = (Student) o;
if (this.age == student.age && this.name.equals(student.name))
{
return true;
}
}
return false;
}
@Override
public int hashCode() {
int n1=this.name.hashCode();
//这里+31是因为31是一个质数(只能被1和自身整除的数),可以减少散列冲突2.31能提高执行效率(31*i=(i<<5)-i)i右移5位就是i乘以2的五次方
int n2=this.age+31;
//n1+n2wei 名字和年龄的hashCode编码,有可能名字年龄不一样但是hash编码一样
return n1+n2;
- HashSet的存储结构
TreeSet
- TreeSet实现类的特点
- 基于排列顺序来实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现一个Comparable接口,指定排序规则
- 通过ComparaTo方法来确定死否位重复元素
- 存储结构:红黑树(红黑树是一种含有红黑结点并能自平衡的二叉查找树(左节点小于根节点,右节点大于根节点))
- TreeSet的方法
boolean add(E e) | 将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。 |
boolean addAll(Collection<? extends E> c) | 将指定 collection 中的所有元素添加到此 set 中。 |
E ceiling(E e) | 返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。 |
void clear() | 移除此 set 中的所有元素。 |
Object clone() | 返回 TreeSet 实例的浅表副本。 |
Comparator<? super E> comparator() | 返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 null。 |
boolean contains(Object o) | 如果此 set 包含指定的元素,则返回 true。 |
Iterator descendingIterator() | 返回在此 set 元素上按降序进行迭代的迭代器。 |
NavigableSet descendingSet() | 返回此 set 中所包含元素的逆序视图。 |
E first() | 返回此 set 中当前第一个(最低)元素。 |
E floor(E e) | 返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。 |
SortedSet headSet(E toElement) | 返回此 set 的部分视图,其元素严格小于 toElement。 |
NavigableSet headSet(E toElement, boolean inclusive) | 返回此 set 的部分视图,其元素小于(或等于,如果 inclusive 为 true)toElement。 |
E higher(E e) | 返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。 |
boolean isEmpty() | 如果此 set 不包含任何元素,则返回 true。 |
Iterator iterator() | 返回在此 set 中的元素上按升序进行迭代的迭代器。 |
E last() | 返回此 set 中当前最后一个(最高)元素。 |
E lower(E e) | 返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。 |
E pollFirst() | 获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。 |
E pollLast() | 获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null。 |
boolean remove(Object o) | 将指定的元素从 set 中移除(如果该元素存在于此 set 中)。 |
int size() | 返回 set 中的元素数(set 的容量)。 |
NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) | 返回此 set 的部分视图,其元素范围从 fromElement 到 toElement。 |
SortedSet subSet(E fromElement, E toElement) | 返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。 |
SortedSet tailSet(E fromElement) | 返回此 set 的部分视图,其元素大于等于 fromElement。 |
NavigableSet tailSet(E fromElement, boolean inclusive) | 返回此 set 的部分视图,其元素大于(或等于,如果 inclusive 为 true)fromElement。 |
- TreeSet的使用
简单实现
System.out.println("=============================");
TreeSet<String> treeSet = new TreeSet();
treeSet.add("张三");
treeSet.add("李四");
treeSet.add("王五");
treeSet.add("老六");
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
//删除元素
System.out.println("=============================");
treeSet.remove("李四");
//treeSet.clear();
//遍历元素
System.out.println("=============================");
//3.1增强for
for (String string:treeSet
) {
System.out.println(string);
}
//3.2使用迭代器Iterator
Iterator iterator = treeSet.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//判断元素
System.out.println("=============================");
System.out.println(treeSet.contains("王五"));
System.out.println(treeSet.isEmpty());
- TreeSet的使用2
当我们直接运行下面代码会发现会报出异常
ClassCastException: Gather.Student cannot be cast to java.lang.Comparable
- 这是因为当我创建Student类的对象作为元素时,我们必须实现Comparable接口,因为TreeSet的存储结构是红黑树,必须满足左节点小于根节点,右节点大于根节点,但是现在程序不知道比较什么,是去比较name,还是去比较age,还是两个都要比,所以我们让添加元素对象的类去实现Comparable接口,重写ComparaTo方法,我们自己定义比较规则相比age还name我们自己定义
TreeSet<Student> treeSet = new TreeSet();
//
Student s1 =new Student("aaa",15);
Student s2 =new Student("bbb",16);
Student s3 =new Student("ccc",17);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
所以我们在Student中重写的ComparaTo的代码如下,如果返回值为0则认为是重复元素
public class Student implements Comparable<Student>{
//定义的规则是先比姓名在比年龄
@Override
public int compareTo(Student o) {
int n1=this.getName().compareTo(o.getName());
int n2=this.getAge()-o.getAge();
return n1==0?n2:n1;
}
}
此时在运行就会发现,是按照s1 ,s2,s3,s4的顺序排列,s3和s4的名字一样,所以age小的在前面
TreeSet<Student> treeSet = new TreeSet();
Student s1 =new Student("aaa",15);
Student s2 =new Student("bbb",16);
Student s3 =new Student("ccc",17);
Student s4 =new Student("ccc",20);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
- TreeSet的使用3,Comparator的使用
Comparator:我们通过实现Comparator接口来自己定制比较规则(比较器),与Comparable相似,Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序
public static void main(String[] args) {
//注意这里使用了匿名内部类,new一个接口
TreeSet<Student> treeSet= new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//这里的规则是先比较 age在比name,所以输出时s2排在最后
int n1=o1.getAge()-o2.getAge();
int n2=o1.getName().compareTo(o2.getName());
return n1==0?n2:n1;
}
});
Student s1 =new Student("aaa",15);
Student s2 =new Student("bbb",25);
Student s3 =new Student("ccc",17);
Student s4 =new Student("ccc",20);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
System.out.println("元素个数"+treeSet.size());
System.out.println(treeSet.toString());
}