千鋒教育Java入門全套視頻教程(java核心技術(shù),適合java零基礎(chǔ),Java

Set集合的基礎(chǔ)知識
?特點:
1.無序性:set集合是無序的
2.不重復:set集合是不可以重復的
遍歷方法:
foreach,迭代器
Set和List一樣屬于接口,無法直接創(chuàng)建實例化對象,需要實現(xiàn)類來set接口。
一.HashSet
HashSet實現(xiàn)Set接口,底層由HashMap來實現(xiàn),為哈希表結(jié)構(gòu),新增元素相當于HashMap的key,value默認為一個固定的Object。
當有元素插入的時候,會計算元素的hashCode值,將元素插入到哈希表對應的位置中來;
它繼承于AbstractSet,實現(xiàn)了Set, Cloneable, Serializable接口。
(1)HashSet繼承AbstractSet類,獲得了Set接口大部分的實現(xiàn),減少了實現(xiàn)此接口所需的工作,實際上是又繼承了AbstractCollection類;
(2)HashSet實現(xiàn)了Set接口,獲取Set接口的方法,可以自定義具體實現(xiàn),也可以繼承AbstractSet類中的實現(xiàn);
(3)HashSet實現(xiàn)Cloneable,得到了clone()方法,可以實現(xiàn)克隆功能;
(4)HashSet實現(xiàn)Serializable,表示可以被序列化,通過序列化去傳輸,典型的應用就是hessian協(xié)議。
具有如下特點:
不允許出現(xiàn)重復因素;
允許插入Null值;
元素無序(添加順序和遍歷順序不一致);
線程不安全,若2個線程同時操作HashSet,必須通過代碼實現(xiàn)同步;
這里我們可以思考一下如果對List容器中的元素去重?),可以使用HashSet呦~
這里我就淺淺舉一個例子:
public class SetDemo {
??????private List<Integer> list = new ArrayList<>();
???@BeforeAll
??????public void setup() {
?????????????set.add(1);
?????????????set.add(1);
?????????????set.add(2);
?????????????set.add(2);
?????????????set.add(3);
?????????????set.add(3);
??????}
??????@Test
??????public void test01() {
?????????????List<Integer> tmp = new ArrayList<>(new HashSet<Integer>(list));
?????????????System.out.println(tmp);
??????}
}
這里要注意哦,前面說了set集合是不可以重復的,但是ArrayList是可以存放重復元素的。一定要注意區(qū)分哦??
最后輸出的是123。
?為了更好的理解,我在這里再舉一個例子,首先我們新建一個Set集合放入元素
public class SetDemo {
???private Set<Integer> set = new HashSet<>();
??????@BeforeAll
??????public void setup() {
?????????????set.add(1);
?????????????set.add(1);
?????????????set.add(2);
?????????????set.add(4);
?????????????set.add(5);
?????????????set.add(3);
??????}
}
然后我會分別使用foreach和迭代器來遍歷
?//foreach
???@Test
??????public void test02() {
?????????????for(Integer e: set) {
????????????????????System.out.println(e);
?????????????}
??????}
???//使用迭代器
??????@Test
??????public void test03() {
?????????????Iterator<Integer> it = set.iterator();
?????????????while(it.hasNext()) {
????????????????????System.out.println(it.next());
?????????????}
??????}???
由于HashSet中只能存儲不重復的對象,所以輸出時會自動把重復的元素去重。
二.TreeSet
從名字上可以看出,此集合的實現(xiàn)和樹結(jié)構(gòu)有關(guān)。與HashSet集合類似,TreeSet也是基于Map來實現(xiàn),具體實現(xiàn)TreeMap,其底層結(jié)構(gòu)為紅黑樹(特殊的二叉查找樹);
與HashSet不同的是,TreeSet具有排序功能,分為自然排序(123456)和自定義排序兩類,默認是自然排序;在程序中,我們可以按照任意順序?qū)⒃夭迦氲郊现?,等到遍歷時TreeSet會按照一定順序輸出--倒序或者升序;
它繼承AbstractSet,實現(xiàn)NavigableSet, Cloneable, Serializable接口。
(1)與HashSet同理,TreeSet繼承AbstractSet類,獲得了Set集合基礎(chǔ)實現(xiàn)操作;
(2)TreeSet實現(xiàn)NavigableSet接口,而NavigableSet又擴展了SortedSet接口。這兩個接口主要定義了搜索元素的能力,例如給定某個元素,查找該集合中比給定元素大于、小于、等于的元素集合,或者比給定元素大于、小于、等于的元素個數(shù);簡單地說,實現(xiàn)NavigableSet接口使得TreeSet具備了元素搜索功能;
(3)TreeSet實現(xiàn)Cloneable接口,意味著它也可以被克??;
(4)TreeSet實現(xiàn)了Serializable接口,可以被序列化,可以使用hessian協(xié)議來傳輸;
具有如下特點:
對插入的元素進行排序,是一個有序的集合(主要與HashSet的區(qū)別);
允許插入Null值;
不允許插入重復元素;
線程不安全。
同樣,這里我也會寫一個例子,首先我們新建一個學生類(隨便什么都行)來實現(xiàn)
package com.zking.list;
public class Student implements Comparable<Student>{
??????private Integer id;
??????private String name;
??????private int age;
??????/**
???????* get和set方法
???????* @param id
???????*/
??????public Integer getId() {
?????????????return id;
??????}
??????public void setId(Integer id) {
?????????????this.id = id;
??????}
??????public String getName() {
?????????????return name;
??????}
??????public void setName(String name) {
?????????????this.name = name;
??????}
??????public int getAge() {
?????????????return age;
??????}
??????public void setAge(int age) {
?????????????this.age = age;
??????}
?
??????/**
???????* hashCode()方法
???????*/
??????@Override
??????public int hashCode() {
?????????????final int prime = 31;
?????????????int result = 1;
?????????????result = prime * result + age;
?????????????result = prime * result + ((id == null) ? 0 : id.hashCode());
?????????????result = prime * result + ((name == null) ? 0 : name.hashCode());
?????????????return result;
??????}
?
??????/**
???????* equals()方法
???????*/
??????@Override
??????public boolean equals(Object obj) {
?????????????if (this == obj)
????????????????????return true;
?????????????if (obj == null)
????????????????????return false;
?????????????if (getClass() != obj.getClass())
????????????????????return false;
?????????????Student other = (Student) obj;
?????????????if (age != other.age)
????????????????????return false;
?????????????if (id == null) {
????????????????????if (other.id != null)
???????????????????????????return false;
?????????????} else if (!id.equals(other.id))
????????????????????return false;
?????????????if (name == null) {
????????????????????if (other.name != null)
???????????????????????????return false;
?????????????} else if (!name.equals(other.name))
????????????????????return false;
?????????????return true;
??????}
??????@Override
??????public String toString() {
?????????????return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
??????}
??????public Student(Integer id, String name, int age) {
?????????????super();
?????????????this.id = id;
?????????????this.name = name;
?????????????this.age = age;
??????}
??????public int compareTo(Student o) {
?????????????if(this.getAge()-o.getAge()==0) {
????????????????????return this.getId()-o.getId();
?????????????}
?????????????return this.getAge() - o.getAge();
??????}
}
記得一定要寫hashCode()和equals()方法??
然后再使用ThreeSet
private Set<Integer> set = new HashSet<>();
??????@Test
??????public void test01() {
?????????????TreeSet<Student> stu = new TreeSet<>();
?????????????stu.add(new Student(1,"莉莉", 18));
?????????????stu.add(new Student(1,"莉莉", 18));
?????????????stu.add(new Student(2,"嘿嘿", 19));
?????????????stu.add(new Student(4,"大壯", 10));
?????????????stu.add(new Student(7,"小米", 18));
?????????????stu.add(new Student(5,"妮妮", 20));
?????????????stu.add(new Student(3,"帆帆", 30));?????????
?????????????for(Student s: stu) {
????????????????????System.out.println(s);
?????????????}
??????}