Java Set集合及其子類HashSet與LinkedHashSet詳解
前言:
java.util.Set
接口和 java.util.List
接口一樣,同樣繼承自 Collection
接口,它與 Collection
接口中的方法基本一致,并沒有對 Collection
接口進行功能上的擴充,只是比 Collection
接口更加嚴格了。與 List
接口不同的是, Set
接口中元素無序,并且都會以某種規(guī)則保證存入的元素不出現(xiàn)重復。Set
集合有多個子類,這里我們介紹其中的 java.util.HashSet
、 java.util.LinkedHashSet
這兩個集合。
tips:Set集合取出元素的方式可以采用:迭代器、增強for。
一、HashSet集合介紹
java.util.HashSet
是Set
接口的一個實現(xiàn)類,它所存儲的元素是不可重復的,并且元素都是無序的(即存取順序不一致)。java.util.HashSet
底層的實現(xiàn)其實是一個java.util.HashMap
支持。
HashSet
是根據(jù)對象的哈希值來確定元素在集合中的存儲位置,因此具有良好的存取和查找性能。保證元素唯一性的方式依賴于:hashCode
與equals
方法。
我們先來使用一下Set集合存儲,看下現(xiàn)象,再進行原理的講解:
public class HashSetDemo { public static void main(String[] args) { //創(chuàng)建 Set集合 HashSet<String> set = new HashSet<String>(); //添加元素 set.add(new String("cba")); set.add("abc"); set.add("bac"); set.add("cba"); //遍歷 for (String name : set) { System.out.println(name); } } }
輸出結果如下,說明集合中不能存儲重復元素:
cba
abc
bac
tips:根據(jù)結果我們發(fā)現(xiàn)字符串"cba"只存儲了一個,也就是說重復的元素set集合不存儲。
二、HashSet集合存儲數(shù)據(jù)的結構(哈希表)
1.什么是哈希表呢?
在JDK1.8之前,哈希表底層采用數(shù)組+鏈表實現(xiàn),即使用鏈表處理沖突,同一hash值的鏈表都存儲在一個鏈表里。但是當位于一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查找的效率較低。而JDK1.8中,哈希表存儲采用數(shù)組+鏈表+紅黑樹實現(xiàn),當鏈表長度超過閾值(8)時,將鏈表轉換為紅黑樹,這樣大大減少了查找時間。
簡單的來說,哈希表是由數(shù)組+鏈表+紅黑樹(JDK1.8增加了紅黑樹部分)實現(xiàn)的,
如下圖所示:
看到這張圖就有人要問了,這個是怎么存儲的呢?
為了方便大家的理解我們結合一個存儲流程圖來說明一下:
總而言之,JDK1.8引入紅黑樹大程度優(yōu)化了HashMap的性能,那么對于我們來講保證HashSet集合元素的唯一,其實就是根據(jù)對象的hashCode和equals方法來決定的。如果我們往集合中存放自定義的對象,那么保證其唯一,就必須復寫hashCode和equals方法建立屬于當前對象的比較方式。
三、HashSet存儲自定義類型元素
給HashSet中存放自定義類型元素時,需要重寫對象中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的對象唯一。
創(chuàng)建自定義Student類:
public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } 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; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
public class HashSetDemo2 { public static void main(String[] args) { //創(chuàng)建集合對象 該集合中存儲 Student類型對象 HashSet<Student> stuSet = new HashSet<Student>(); //存儲 Student stu = new Student("張三", 43); stuSet.add(stu); stuSet.add(new Student("李四", 66)); stuSet.add(new Student("張三", 43)); stuSet.add(new Student("王五", 23)); stuSet.add(stu); for (Student stu2 : stuSet) { System.out.println(stu2); } } }
執(zhí)行結果:
Student [name=李四, age=66]
Student [name=張三, age=43]
Student [name=王五, age=23]
四、LinkedHashSet
我們知道HashSet保證元素唯一,可是元素存放進去是沒有順序的,那么我們要保證有序,怎么辦呢?
在HashSet下面有一個子類java.util.LinkedHashSet
,它是鏈表和哈希表組合的一個數(shù)據(jù)存儲結構。
演示代碼如下:
public class LinkedHashSetDemo { public static void main(String[] args) { Set<String> set = new LinkedHashSet<String>(); set.add("bbb"); set.add("aaa"); set.add("abc"); set.add("bbc"); Iterator<String> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
結果:
bbb
aaa
abc
bbc
到此這篇關于Java Set集合及其子類HashSet與LinkedHashSet詳解的文章就介紹到這了,更多相關Java Set集合 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot中實現(xiàn)訂單30分鐘自動取消的三種方案分享
在電商和其他涉及到在線支付的應用中,通常需要實現(xiàn)一個功能:如果用戶在生成訂單后的一定時間內未完成支付,系統(tǒng)將自動取消該訂單,本文將詳細介紹基于Spring Boot框架實現(xiàn)訂單30分鐘內未支付自動取消的幾種方案,并提供實例代碼,需要的朋友可以參考下2023-10-10SpringBoot 使用 FTP 操作文件的過程(刪除、上傳、下載文件)
這篇文章主要介紹了SpringBoot 使用 FTP 操作文件,主要包括配置ftp服務器,上傳、刪除、下載文件操作,本文結合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-12-12Java Fluent Mybatis實戰(zhàn)之構建項目與代碼生成篇上
Java中常用的ORM框架主要是mybatis, hibernate, JPA等框架。國內又以Mybatis用的多,基于mybatis上的增強框架,又有mybatis plus和TK mybatis等。今天我們介紹一個新的mybatis增強框架 fluent mybatis2021-10-10SpringBoot切面實現(xiàn)token權限校驗詳解
這篇文章主要介紹了SpringBoot切面實現(xiàn)token權限校驗詳解,要實現(xiàn)權限校驗,首先數(shù)據(jù)表和實體類上需要有權限字段,我的表中permission和gender是通過外鍵約束permission表和gender表實現(xiàn)枚舉的,因為可拓展性更好,需要的朋友可以參考下2024-01-01