Set
Set继承于Collection接口,是一个不允许出现重复元素,并且无序的集合,主要有HashSet和TreeSet两大实现类。
Set集合框架结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-666TXAgG-1636942816281)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115092250475.png)]
-
set中的常用方法:
public interface Set<E> extends Collection<E> { A:添加功能 boolean add(E e); boolean addAll(Collection<? extends E> c); B:删除功能 boolean remove(Object o); boolean removeAll(Collection<?> c); void clear(); C:长度功能 int size(); D:判断功能 boolean isEmpty(); boolean contains(Object o); boolean containsAll(Collection<?> c); boolean retainAll(Collection<?> c); E:获取Set集合的迭代器: Iterator<E> iterator(); F:把集合转换成数组 Object[] toArray(); <T> T[] toArray(T[] a); //判断元素是否重复,为子类提高重写方法 boolean equals(Object o); int hashCode(); }
HashSet
HashSet底层使用了HashMap
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lM6TczIH-1636942816284)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115093449371.png)]
(1) HashSet实现了Set接口,所以Set的方法都可以使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SkxySJfK-1636942816285)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115093708718.png)]
(2) HashSet add()方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JV2uNQct-1636942816286)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115094309743.png)]
查看源码可以看到HashSet实现集合元素不重合本质上是使用HashMap的key—将加进来的元素都当作是map的key,value是一个固定的object,源码如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1OtQsZUV-1636942816287)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115094443228.png)]
TreeSet
从名字上可以看出,此集合的实现和树结构有关。与HashSet集合类似,TreeSet也是基于Map来实现,具体实现TreeMap(后面讲解),其底层结构为红黑树(特殊的二叉查找树);
与HashSet不同的是,TreeSet具有排序功能,分为自然排序(123456)和自定义排序两类,默认是自然排序;在程序中,我们可以按照任意顺序将元素插入到集合中,等到遍历时TreeSet会按照一定顺序输出–倒序或者升序;
(1) 与HashSet类似,HashTree实现了Set接口故Set方法都有
TreeSet元素排序
(1)首先进行简单的对象比较,String Integer
import java.util.*;
import static java.util.Objects.hash;
public class practice {
public static void main(String[] args) {
TreeSet<String> treeSetString = new TreeSet<String>();
treeSetString.add("a");
treeSetString.add("z");
treeSetString.add("d");
treeSetString.add("b");
System.out.println("字母顺序:" + treeSetString.toString());
TreeSet<Integer> treeSetInteger = new TreeSet<Integer>();
treeSetInteger.add(1);
treeSetInteger.add(24);
treeSetInteger.add(23);
treeSetInteger.add(6);
System.out.println(treeSetInteger.toString());
System.out.println("数字顺序:" + treeSetString.toString());
}
}
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLa5ddwl-1636942816288)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115100803032.png)]
(2)如果是自定义对象
public class App{
private String name;
private Integer age;
public App(){}
public App(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static void main(String[] args ){
System.out.println( "Hello World!" );
}
}
public class TreeSetTest {
public static void main(String[] agrs){
customSort();
}
//自定义排序顺序:升序
public static void customSort(){
TreeSet<App> treeSet = new TreeSet<App>();
//排序对象:
App app1 = new App("hello",10);
App app2 = new App("world",20);
App app3 = new App("my",15);
App app4 = new App("name",25);
//添加到集合:
treeSet.add(app1);
treeSet.add(app2);
treeSet.add(app3);
treeSet.add(app4);
System.out.println("TreeSet集合顺序为:"+treeSet);
}
}
输出结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aoTmIYK2-1636942816288)(C:\Users\HJY\AppData\Roaming\Typora\typora-user-images\image-20211115101104328.png)]
通过查看源码发现,在TreeSet调用add方法时,会调用到底层TreeMap的put方法,在put方法中会调用到compare(key, key)方法,进行key大小的比较;
在比较的时候,会将传入的key进行类型强转,所以当我们自定义的App类进行比较的时候,自然就会抛出异常,因为App类并没有实现Comparable接口;
将app实现conparable接口:
public class App implements Comparable<App>{
private String name;
private Integer age;
public App(){}
public App(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
//自定义比较:先比较name的长度,在比较age的大小;
public int compareTo(App app) {
//比较name的长度:
int num = this.name.length() - app.name.length();
//如果name长度一样,则比较年龄的大小:
return num == 0 ? this.age - app.age : num;
}
@Override
public String toString() {
return "App{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
关于实现compareTo方法的说明:
结果返回大于0时,方法前面的值大于方法中的值;
结果返回等于0时,方法前面的值等于方法中的值;
结果返回小于0时,方法前面的值小于方法中的值;
本文参考:Java集合–Set(基础) - 简书 (jianshu.com)
;
}
}
关于实现compareTo方法的说明:
```undefined
结果返回大于0时,方法前面的值大于方法中的值;
结果返回等于0时,方法前面的值等于方法中的值;
结果返回小于0时,方法前面的值小于方法中的值;