Set接口
Set是一個不能包含重復元素的Collection,它模擬了數學集抽象,Set接口僅包含從Collection繼承的方法,并添加禁止重復元素的限制,Set還為equals和hashCode操作的行為添加了一個更強的契約,允許Set實例有意義地進行比較,即使它們的實現類型不同,如果兩個Set實例包含相同的元素,則它們是相等的。
Java平臺包含三個通用的Set實現:HashSet、TreeSet和LinkedHashSet。將其元素存儲在哈希表中的HashSet是性能最佳的實現,但它不能保證迭代的順序。TreeSet將其元素存儲在紅黑樹中,根據元素的值對其元素進行排序,它比HashSet慢得多。LinkedHashSet實現為哈希表,其中有一個鏈表,根據它們插入集合的順序(插入順序)對其元素進行排序,LinkedHashSet讓它的客戶端避免了HashSet提供的未指定的、通常混亂的排序,但代價只稍微高一點。
這是一個簡單但有用的Set語法,假設你有一個Collection,c,并且你想要創建另一個包含相同元素的Collection,但會刪除所有重復項,下面的一行代碼就可以解決這個問題。
CollectionnoDups = new HashSet (c);
它的工作原理是創建一個Set(根據定義,它不能包含重復項),初始化包含c中的所有元素,它使用Collection接口部分中描述的標準轉換構造函數。
或者,如果使用JDK 8或更高版本,你可以使用聚合操作輕松收集到Set:
c.stream() .collect(Collectors.toSet()); // no duplicates
這是一個稍長的示例,它將名稱Collection累積到TreeSet中:
Setset = people.stream() .map(Person::getName) .collect(Collectors.toCollection(TreeSet::new));
以下是第一個語法的次要變體,它在刪除重復元素時保留了原始集合的順序:
CollectionnoDups = new LinkedHashSet (c);
以下是封裝前面的語法的泛型方法,返回與傳遞的相同的泛型類型的Set。
public staticSet接口基礎操作Set removeDups(Collection c) { return new LinkedHashSet (c); }
size操作返回Set中的元素數(其基數),isEmpty方法完全符合你的想法,add方法將指定的元素添加到Set(如果它尚不存在)并返回一個布爾值,指示是否添加了元素。類似地,remove方法從Set中刪除指定的元素(如果存在)并返回一個布爾值,指示元素是否存在,iterator方法在Set上返回Iterator。
以下程序打印出其參數列表中的所有不同單詞,提供了該程序的兩個版本,第一個使用JDK 8聚合操作,第二個使用for-each構造。
使用JDK 8聚合操作:
import java.util.*; import java.util.stream.*; public class FindDups { public static void main(String[] args) { SetdistinctWords = Arrays.asList(args).stream() .collect(Collectors.toSet()); System.out.println(distinctWords.size()+ " distinct words: " + distinctWords); } }
使用for-each構造:
import java.util.*; public class FindDups { public static void main(String[] args) { Sets = new HashSet (); for (String a : args) s.add(a); System.out.println(s.size() + " distinct words: " + s); } }
現在運行該程序的任一版本。
java FindDups i came i saw i left
生成以下輸出:
4 distinct words: [left, came, saw, i]
請注意,代碼始終引用Collection通過其接口類型(Set)而不是其實現類型,這是一個強烈推薦的編程實踐,因為它使你可以靈活地僅通過更改構造函數來更改實現。如果用于存儲集合的變量或用于傳遞它的參數中的任何一個被聲明為Collection的實現類型而不是其接口類型,必須更改所有這些變量和參數才能更改其實現類型。
此外,無法保證生成的程序能夠正常運行,如果程序使用原始實現類型中存在但未在新實現類型中存在的任何非標準操作,則程序將失敗,僅通過其接口引用集合可防止你使用任何非標準操作。
前面示例中Set的實現類型是HashSet,它不保證Set中元素的順序,如果你希望程序按字母順序打印單詞列表,只需將Set的實現類型從HashSet更改為TreeSet,進行這個簡單的單行更改會導致前一個示例中的命令行生成以下輸出。
java FindDups i came i saw i left 4 distinct words: [came, i, left, saw]Set接口批量操作
批量操作特別適合于Set,應用時,它們執行標準的集代數運算,假設s1和s2是Set,批量操作是這樣做的:
s1.containsAll(s2) — 如果s2是s1的子集,則返回true(如果set s1包含s2中的所有元素,則s2是s1的子集)。
s1.addAll(s2) — 將s1轉換為s1和s2的并集(兩個集合的并集是包含任一集合中包含的所有元素的集合)。
s1.retainAll(s2) — 將s1轉換為s1和s2的交集(兩個集合的交集是僅包含兩個集合共有的元素的集合)。
s1.removeAll(s2) — 將s1轉換為s1和s2的(非對稱)差集(例如,s1減s2的差集就是包含s1中所有元素但不包含s2中的所有元素的集)。
若要非破壞性地計算兩個集合的并集、交集或差集(不修改任何一個集合),調用者必須在調用適當的批量操作之前復制一個集合,以下是由此產生的語法。
Setunion = new HashSet (s1); union.addAll(s2); Set intersection = new HashSet (s1); intersection.retainAll(s2); Set difference = new HashSet (s1); difference.removeAll(s2);
前面的語法中的結果集的實現類型是HashSet,如前所述,它是Java平臺中最好的全能Set實現,但是,任何通用的Set實現都可以替代。
讓我們重溫一下FindDups程序,假設你想知道參數列表中的哪些單詞只出現一次,哪些單詞出現多次,但你不希望重復打印出任何重復項,這種效果可以通過生成兩個集合來實現 — 一個集合包含參數列表中的每個單詞,另一個集合僅包含重復項。僅出現一次的單詞是這兩組的差集,我們知道如何計算,以下是生成的程序的樣子。
import java.util.*; public class FindDups2 { public static void main(String[] args) { Setuniques = new HashSet (); Set dups = new HashSet (); for (String a : args) if (!uniques.add(a)) dups.add(a); // Destructive set-difference uniques.removeAll(dups); System.out.println("Unique words: " + uniques); System.out.println("Duplicate words: " + dups); } }
當使用前面使用的相同參數列表運行時(i came i saw i left),程序產生以下輸出。
Unique words: [left, saw, came] Duplicate words: [i]
不太常見的集代數運算是對稱差集 — 包含在兩個指定集合中但不同時包含在兩個集合中的元素的集合,以下代碼非破壞性地計算兩個集合的對稱差集。
SetSet接口數組操作symmetricDiff = new HashSet (s1); symmetricDiff.addAll(s2); Set tmp = new HashSet (s1); tmp.retainAll(s2); symmetricDiff.removeAll(tmp);
除了對其他任何Collection執行的操作之外,數組操作不會對Set執行任何特殊操作,Collection接口部分介紹了這些操作。
上一篇:Collection接口 下一篇:List接口文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73096.html
集合接口 核心集合接口封裝了不同類型的集合,如下圖所示,這些接口允許獨立于其表示的細節來操縱集合,核心集合接口是Java集合框架的基礎,如下圖所示,核心集合接口形成層次結構。 showImg(https://segmentfault.com/img/bVbntJW?w=402&h=146); Set是一種特殊的Collection,SortedSet是一種特殊的Set,依此類推,另請注意,層次結構...
List接口 List是一個有序的Collection(有時稱為序列),列表可能包含重復元素,除了從Collection繼承的操作之外,List接口還包括以下操作: 位置訪問 — 根據列表中的數字位置操縱元素,這包括get、set、add、addAll和remove等方法。 搜索 — 搜索列表中的指定對象并返回其數字位置,搜索方法包括indexOf和lastIndexOf。 迭代 — 擴展Ite...
SortedSet接口 SortedSet是一個Set,它按升序維護其元素,根據元素的自然順序或根據SortedSet創建時提供的Comparator進行排序,除了常規的Set操作外,SortedSet接口還提供以下操作: 范圍視圖 — 允許對已排序集進行任意范圍操作。 端點 — 返回有序集合中的第一個或最后一個元素。 比較器訪問 — 返回用于對集合進行排序的Comparator(如果有)。 ...
Map接口 Map是將鍵映射到值的對象,map不能包含重復的鍵:每個鍵最多可以映射一個值,它模擬數學函數抽象。Map接口包括基本操作的方法(如put、get、remove、containsKey、containsValue、size和empty),批量操作(如putAll和clear)和集合視圖(如keySet、entrySet和values)。 Java平臺包含三個通用Map實現:HashMap...
泛型類型 泛型類型是通過類型參數化的泛型類或接口,修改以下Box類以演示此概念。 一個簡單的Box類 首先檢查一個對任何類型的對象進行操作的非泛型Box類,它只需要提供兩個方法:set,它將一個對象添加到box中,get,它將檢索它: public class Box { private Object object; public void set(Object object) ...
閱讀 772·2021-10-09 09:58
閱讀 641·2021-08-27 16:24
閱讀 1723·2019-08-30 14:15
閱讀 2384·2019-08-30 11:04
閱讀 2067·2019-08-29 18:43
閱讀 2170·2019-08-29 15:20
閱讀 2716·2019-08-26 12:20
閱讀 1616·2019-08-26 11:44