日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java集合(五):Set集

發布時間:2023/11/30 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java集合(五):Set集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上一講中介紹了散列映射表HashMap和樹映射表TreeMap,知道了HashMap的底層實現機制。這一講將介紹Set接口和實現類:HashSet和TreeSet。由于HashSet的實現是基于HashMap的,TreeSet的實現是基于TreeMap的,所以這里不做過多底層的討論,畢竟這部分已經在Java集合(四):Map映射中討論過了。

1 散列表與Set接口

鏈表和數組可以按照人們的意愿排列元素的順序。但是,如果想要查看某個指定的元素,但卻忘了它的位置,就需要訪問所有的元素,直到找到為止。如果集合中的元素很多,將會消耗很長時間。如果不在意元素的順序,可以有幾種能夠快速查找元素的數據結構。但是缺點是不能控制元素的順序。它們將按照有利于其操作目的的原則組織數據。

有一種常見的數據結構,就是散列表(hash table)。散列表可以根據每個對象計算一個整數,稱為散列碼(hash code)。不同的對象產生不同的散列碼。

在Java中,散列表用鏈表數組實現。每個列表稱為桶,這個已經在Map映射中介紹了。

散列表的特點就是:元素沒有順序,元素不能重復。

Set接口的定義如下:

public interface java.util.Set<E> extends java.util.Collection<E> {public abstract int size();public abstract boolean isEmpty();public abstract boolean contains(java.lang.Object);public abstract java.util.Iterator<E> iterator();public abstract java.lang.Object[] toArray();public abstract <T> T[] toArray(T[]);public abstract boolean add(E);public abstract boolean remove(java.lang.Object);public abstract boolean containsAll(java.util.Collection<?>);public abstract boolean addAll(java.util.Collection<? extends E>);public abstract boolean retainAll(java.util.Collection<?>);public abstract boolean removeAll(java.util.Collection<?>);public abstract void clear();public abstract boolean equals(java.lang.Object);public abstract int hashCode();public java.util.Spliterator<E> spliterator(); }這些方法的含義也很簡單。

2 HashSet類

Java集合類庫中提供了HashSet類實現了Set接口。這個類的底層是使用HashMap實現的:

private transient HashMap<E,Object> map;// Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();

我們知道,HashMap是一個鍵值對,而HashSet存儲的不是鍵值對,因此為了使用HashMap存儲HashSet的元素,就需要構造一個鍵值對。可以使用需要存儲在HashSet中的元素作為鍵,而上面的PRESENT作為值,就構成了一個鍵值對,這樣就可以存在HashMap中了。

也就是說,HashSet與HashMap的原理一樣,不同的是HashSet的值都一樣,都是PRESENT。

由于在前一節中已經詳細介紹了HashMap的原理,這里不再敘述了。只說一下HashSet的使用。

下面的代碼從System.in中讀取單詞,然后將它們添加到HashSet中,再打印出所有的單詞。由于HashSet中不存儲相同的元素,所以打印出來的單詞是不重復的。運行這個程序時使用下面的命令行:

java SetTest < alice.txt

這樣就把alice.txt作為輸入,程序就會讀取所有的單詞。代碼如下:

import java.util.*;public class SetTest {public static void main(String[] args){Set<String> words = new HashSet<>(); // HashSet implements Setlong totalTime = 0;Scanner in = new Scanner(System.in);while (in.hasNext()){String word = in.next();long callTime = System.currentTimeMillis();words.add(word);callTime = System.currentTimeMillis() - callTime;totalTime += callTime;}Iterator<String> iter = words.iterator();for (int i = 1; i <= 20 && iter.hasNext(); i++)System.out.println(iter.next());System.out.println(". . .");System.out.println(words.size() + " distinct words. " + totalTime + " milliseconds.");} }

結果如下:

可以看見,一共有5392個不同的單詞。

3 TreeSet類

TreeSet和HashSet類似,不過,它比HashSet有所改進。TreeSet是一個有序集合,可以以任意順序將元素插入到集合中。在對集合進行遍歷時,每個值將自動按照排序后的順序呈現。例如,假設插入三個字符串,然后訪問添加的所有元素:

SortedSet<String> sorter=new TreeSet<>(); sorter.add("B"); sorter.add("A"); sorter.add("C"); for(String s:sorter)System.out.println(s);

結果是:A B C

TreeSet的底層是使用TreeMap實現的,是一個紅黑樹。每次添加一個元素到樹中時,都被放置在正確的排序位置上。因此,迭代器總是以排好序的順序訪問每個元素。

將一個元素添加到樹中要比添加到一個散列表中要慢,但是,與將元素添加到數組中或鏈表中要快。如果樹中一共有n個元素,將元素插入到正確位置的時間為logn。

與TreeMap一樣,構造一個TreeSet也需要一個比較器,可以使用默認的比較器,也可以使用自己的比較器。使用自己的比較器時,需要給TreeSet的構造器傳遞一個Comparator對象。

下面的程序創建了兩個Item對象的樹集。第一個按照部件編號排序,這是Item對象的默認順序。第二個通過使用一個定制的比較器來按照描述信息排序:

import java.util.*;public class TreeSetTest { public static void main(String[] args){ SortedSet<Item> parts = new TreeSet<>();parts.add(new Item("Toaster", 1234));parts.add(new Item("Widget", 4562));parts.add(new Item("Modem", 9912));System.out.println(parts);SortedSet<Item> sortByDescription = new TreeSet<>(newComparator<Item>(){ public int compare(Item a, Item b){ String descrA = a.getDescription();String descrB = b.getDescription();return descrA.compareTo(descrB);}});sortByDescription.addAll(parts);System.out.println(sortByDescription);} }

import java.util.*;/*** An item with a description and a part number.*/ public class Item implements Comparable<Item> {private String description;private int partNumber;/*** Constructs an item.* * @param aDescription* the item's description* @param aPartNumber* the item's part number*/public Item(String aDescription, int aPartNumber){description = aDescription;partNumber = aPartNumber;}/*** Gets the description of this item.* * @return the description*/public String getDescription(){return description;}public String toString(){return "[\n\tdescripion=" + description + ",\n\tpartNumber=" + partNumber +"\n]\n";}public boolean equals(Object otherObject){if (this == otherObject) return true;if (otherObject == null) return false;if (getClass() != otherObject.getClass()) return false;Item other = (Item) otherObject;return Objects.equals(description, other.description) && partNumber == other.partNumber;}public int hashCode(){return Objects.hash(description, partNumber);}public int compareTo(Item other){return Integer.compare(partNumber, other.partNumber);} }

結果如下:



總結

以上是生活随笔為你收集整理的Java集合(五):Set集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。