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

歡迎訪問 生活随笔!

生活随笔

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

java

java8 迭代set集合_JavaSE(八)集合之Set

發(fā)布時間:2024/7/19 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java8 迭代set集合_JavaSE(八)集合之Set 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2.2、HashSet特點

不能保證元素的排列順序,順序可能和添加的順序不同,順序也有可能發(fā)生變化。

HashSetf不是同步的,如果多個線程同時來訪問一個 HashSet,假設(shè)有兩個或者兩個以上線程同時修改了HashSet 集合時,則必須通過代碼來保證其同步。

集合元素值可以是 null。

2.3、HashSet如何保證元素唯一性的原理

當我們想要創(chuàng)建一個集合,該集合里面的元素都具有唯一性時。會遇到兩種情況:

1)元素為String類型,可以直接用Hashset集合來創(chuàng)建

2)String類重寫了hashCode()和equals()方法,所以,它就可以把內(nèi)容相同的字符串去掉,只留下一個。

思路圖:

3)HashSet保證元素唯一性的原理

我們使用Set集合都是需要去掉重復(fù)元素的,如果在存儲的時候逐個equals()比較, 效率較低,哈希算法提高了去重復(fù)的效率, 降低了使用equals()方法的次數(shù)

當HashSet調(diào)用add()方法存儲對象的時候, 先調(diào)用對象的hashCode()方法得到一個哈希值, 然后在集合中查找是否有哈希值相同的對象

如果沒有哈希值相同的對象就直接存入集合

如果有哈希值相同的對象, 就和哈希值相同的對象逐個進行equals()比較,比較結(jié)果為false就存入, true則不存。

4)將自定義類的對象存入HashSet去重復(fù)

類中必須重寫hashCode()和equals()方法

hashCode():?屬性相同的對象返回值必須相同, 屬性不同的返回值盡量不同(提高效率)

equals(): 屬性相同返回true, 屬性不同返回false,返回false的時候存儲。

在開發(fā)中并不要我們?nèi)?#xff0c;比如使用eclipse開發(fā)中,在類上面 Alt+Shift+s ,再點h,就能生成相對應(yīng)的重寫的hashCode()和equls()方法了。那我們就來分析一下,該怎么寫的。

/*注意:這里是一個Student類:里面有name和age屬性。

* 為什么是31?

* 1,31是一個質(zhì)數(shù),質(zhì)數(shù)是能被1和自己本身整除的數(shù)

* 2,31這個數(shù)既不大也不小

* 3,31這個數(shù)好算,2的五次方-1,2向左移動5位*/@Overridepublic inthashCode() {

finalint prime = 31;int result = 1;

result= prime * result +age;

result= prime * result + ((name == null) ? 0: name.hashCode());returnresult;

}

@Overridepublicboolean equals(Object obj) {if (this == obj) //調(diào)用的對象和傳入的對象是同一個對象

return true; //直接返回true

if (obj == null) //傳入的對象為null

return false; //返回false

if (getClass() != obj.getClass()) //判斷兩個對象對應(yīng)的字節(jié)碼文件是否是同一個字節(jié)碼

return false; //如果不是直接返回false

Person other = (Person) obj; //向下轉(zhuǎn)型

if (age != other.age) //調(diào)用對象的年齡不等于傳入對象的年齡

return false; //返回false

if (name == null) { //調(diào)用對象的姓名為null

if (other.name != null) //傳入對象的姓名不為null

return false; //返回false

} else if (!name.equals(other.name)) //調(diào)用對象的姓名不等于傳入對象的姓名

return false; //返回false

return true; //返回true

}

細說hashCode和equals方法

2.4、一個案例來說明問題

package com.zyh.domain;public classPerson {privateString name;private intage;public Person(String name,intage) {this.name =name;this.age =age;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}/** 為什么是31?

* 1,31是一個質(zhì)數(shù),質(zhì)數(shù)是能被1和自己本身整除的數(shù)

* 2,31這個數(shù)既不大也不小

* 3,31這個數(shù)好算,2的五次方-1,2向左移動5位*/@Overridepublic inthashCode() {

finalint prime = 31;int result = 1;

result= prime * result +age;

result= prime * result + ((name == null) ? 0: name.hashCode());returnresult;

}

@Overridepublicboolean equals(Object obj) {if (this == obj) //調(diào)用的對象和傳入的對象是同一個對象

return true; //直接返回true

if (obj == null) //傳入的對象為null

return false; //返回false

if (getClass() != obj.getClass()) //判斷兩個對象對應(yīng)的字節(jié)碼文件是否是同一個字節(jié)碼

return false; //如果不是直接返回false

Person other = (Person) obj; //向下轉(zhuǎn)型

if (age != other.age) //調(diào)用對象的年齡不等于傳入對象的年齡

return false; //返回false

if (name == null) { //調(diào)用對象的姓名為null

if (other.name != null) //傳入對象的姓名不為null

return false; //返回false

} else if (!name.equals(other.name)) //調(diào)用對象的姓名不等于傳入對象的姓名

return false; //返回false

return true; //返回true

}

@OverridepublicString toString() {return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

Person

package com.zyh.Collection.set;

import com.zyh.domain.Person;

import java.util.HashSet;public classHashSetDemo_0010 {/*HashSet集合存儲自定義對象并遍歷。如果對象的成員變量值相同即為同一個對象

注意了:

你使用的是HashSet集合,這個集合的底層是哈希表結(jié)構(gòu)。

而哈希表結(jié)構(gòu)底層依賴:hashCode()和equals()方法。

如果你認為對象的成員變量值相同即為同一個對象的話,你就應(yīng)該重寫這兩個方法。

如何重寫呢?不同擔心,自動生成即可。*/

public static voidmain(String[] args) {

HashSet hs = new HashSet<>();

hs.add(new Person("boy",10));

hs.add(new Person("girl",34));

hs.add(new Person("girl",34));

hs.add(new Person("boy",10));

hs.add(new Person("person",10));

hs.add(new Person("boy",10));

hs.add(new Person("person",10));

hs.add(new Person("boy",10));

hs.add(new Person("girl",34));//遍歷集合

for(Person p : hs){

System.out.println(p.getName()+":"+p.getAge());

}

}

}

HashSetDemo_0010

三、LinkedHashSet

3.1、LinkedHashSet概述

1)LinkedHashSet是HashSet的子類,LinkedHashSet 集合也是根據(jù)元素的 hashCode 值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,這樣使得元素看起來是以插入的順序保存的。

也就是說,當遍歷?LinkedHashSet 將會按照添加元素順序來訪問集合里的元素。

2)LinkedHashSet是通過用一個鏈表的實現(xiàn)來擴展HashSet,從而支持了對HashSet中的元素的排序。所以LinkedHashSet可以按照元素插入時的順序進行提取。

3)LinkedHashSet 需要維護元素的插入順序,因此性能略低于 HashSet 的性能,但在迭代訪問 Set 里的全部元素時將有很好的性能,因為它以鏈表來維護內(nèi)部順序。

雖然 LinkedHashSet 使用了鏈表記錄集合元素的添加順序,但 LinkedhasHSet依然是 HashSet,因此它依然不允許集合元素重復(fù)。

4)LinkedHashSet只能按照先后順序來進行排序,TreeSet則是按照比較器給的比較規(guī)則進行從小到大排序。其實現(xiàn)也就是借助于TreeMap。

3.2、LinkedHashSet的特點

一是:保證元素唯一。二是:可以保證怎么存就怎么取

3.3、SortedSet接口與TreeSet類

SortedSet接口是Set接口的子接口,除了擁有Set集合的一些基本特點之外,還提供了排序的功能。

TreeSet類就是SortedSet接口的實現(xiàn)類

四、TreeSet

4.1、TreeSet概述

1)TreeSet繼承與實現(xiàn)關(guān)系

TreeSet 是一個有序的集合,它的作用是提供有序的Set集合。它繼承于AbstractSet抽象類,實現(xiàn)了NavigableSet, Cloneable, java.io.Serializable接口。

TreeSet 繼承于AbstractSet,所以它是一個Set集合,具有Set的屬性和方法。

TreeSet 實現(xiàn)了NavigableSet接口,意味著它支持一系列的導(dǎo)航方法。比如查找與指定目標最匹配項。

TreeSet 實現(xiàn)了Cloneable接口,意味著它能被克隆。

TreeSet 實現(xiàn)了java.io.Serializable接口,意味著它支持序列化。

TreeSet是基于TreeMap實現(xiàn)的。TreeSet中的元素支持2種排序方式:自然排序 或者 根據(jù)創(chuàng)建TreeSet 時提供的 Comparator (比較器排序)進行排序。這取決于使用的構(gòu)造方法。

TreeSet為基本操作(add、remove 和 contains)提供受保證的 log(n) 時間開銷。

另外,TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。

2)存儲對象

TreeSet存儲對象的時候, 可以排序, 但是需要指定排序的算法。

Integer能排序(有默認順序), String能排序(有默認順序), 自定義的類存儲的時候出現(xiàn)異常(沒有順序)

如果想把自定義類的對象存入TreeSet進行排序, 那么必須實現(xiàn)Comparable接口

在類上implement Comparable

重寫compareTo()方法

在使用TreeSet存儲對象的時候, add()方法內(nèi)部就會自動調(diào)用compareTo()方法進行比較, 根據(jù)比較結(jié)果使用二叉樹形式進行存儲

3)Tree的構(gòu)造方法

//默認構(gòu)造函數(shù)。使用該構(gòu)造函數(shù),TreeSet中的元素按照自然排序進行排列。

TreeSet()//創(chuàng)建的TreeSet包含collection

TreeSet(Collection extends E>collection)//指定TreeSet的比較器

TreeSet(Comparator super E>comparator)//創(chuàng)建的TreeSet包含set

TreeSet(SortedSet set)

4)TreeSet與Collection的關(guān)系

TreeSet繼承于AbstractSet,并且實現(xiàn)了NavigableSet接口。

TreeSet的本質(zhì)是一個"有序的,并且沒有重復(fù)元素"的集合,它是通過TreeMap實現(xiàn)的。TreeSet中含有一個"NavigableMap類型的成員變量"m,而m實際上是"TreeMap的實例"。

4.2、TreeSet原理

1)特點

TreeSet是用來排序的, 可以指定一個順序, 對象存入之后會按照指定的順序排列

2)使用方式

2.1)自然順序(Comparable)

TreeSet類的add()方法中會把存入的對象提升為Comparable類型

調(diào)用對象的compareTo()方法和集合中的對象比較

根據(jù)compareTo()方法返回的結(jié)果進行存儲

2.2)比較器順序(Comparator)

創(chuàng)建TreeSet的時候可以制定 一個Comparator

如果傳入了Comparator的子類對象, 那么TreeSet就會按照比較器中的順序排序

add()方法內(nèi)部會自動調(diào)用Comparator接口中compare()方法排序

調(diào)用的對象是compare方法的第一個參數(shù),集合中的對象是compare方法的第二個參數(shù)

2.3)兩種方式的區(qū)別

TreeSet構(gòu)造函數(shù)什么都不傳, 默認按照類中Comparable的順序(沒有就報錯ClassCastException)

TreeSet如果傳入Comparator, 就優(yōu)先按照Comparator

4.3、圖解TreeSet的排序原理

4.3.1、環(huán)境

我們創(chuàng)建了一個Person類和一個測試類TreeSetDemo_0010類

package com.zyh.domain;public classPerson {privateString name;private intage;public Person(String name,intage) {this.name =name;this.age =age;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}/** 為什么是31?

* 1,31是一個質(zhì)數(shù),質(zhì)數(shù)是能被1和自己本身整除的數(shù)

* 2,31這個數(shù)既不大也不小

* 3,31這個數(shù)好算,2的五次方-1,2向左移動5位*/@Overridepublic inthashCode() {

finalint prime = 31;int result = 1;

result= prime * result +age;

result= prime * result + ((name == null) ? 0: name.hashCode());returnresult;

}

@Overridepublicboolean equals(Object obj) {if (this == obj) //調(diào)用的對象和傳入的對象是同一個對象

return true; //直接返回true

if (obj == null) //傳入的對象為null

return false; //返回false

if (getClass() != obj.getClass()) //判斷兩個對象對應(yīng)的字節(jié)碼文件是否是同一個字節(jié)碼

return false; //如果不是直接返回false

Person other = (Person) obj; //向下轉(zhuǎn)型

if (age != other.age) //調(diào)用對象的年齡不等于傳入對象的年齡

return false; //返回false

if (name == null) { //調(diào)用對象的姓名為null

if (other.name != null) //傳入對象的姓名不為null

return false; //返回false

} else if (!name.equals(other.name)) //調(diào)用對象的姓名不等于傳入對象的姓名

return false; //返回false

return true; //返回true

}

@OverridepublicString toString() {return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

}

Person

package com.zyh.Collection.set;

import com.zyh.domain.Person;

import java.util.TreeSet;public classTreeSetDemo_0010 {public static voidmain(String[] args) {

TreeSet ts = new TreeSet<>();

ts.add(new Person("張三",23));

ts.add(new Person("李四",13));

ts.add(new Person("王五",43));

ts.add(new Person("趙六",33));for(Person p:ts){

System.out.println(p);

}

}

}

TreeSetDemo_0010

當我們直接執(zhí)行的時候,會報錯誤。

Exception in thread "main" java.lang.ClassCastException: com.zyh.domain.Person cannot be cast to java.lang.Comparable

分析:Integer能排序(有默認順序), String能排序(有默認順序), 自定義的類存儲的時候出現(xiàn)異常(沒有順序)

4.3.2、自然排序(Comparable)

我們讓Person實現(xiàn)Comparable接口,重寫compareTo方法

當我們把返回值設(shè)置為1時:

圖解:

當返回值是0時,張三作為二叉樹的根,當我們其他的元素比較時,都返回0表示相同的對象。所以只會存儲張三。

當返回值是-1時,張三作為二叉樹的根,李四和它比較時,返回-1說明,李四小,掛在張三的左邊。王五一進來也和張三比較返回-1,放在張三左邊,在和李四比較返回-1,掛在李四左邊,以此類推。

當返回值是1時。和上面一樣的推理。

2.1)按照年齡排序

分析:

張三作為二叉樹的根,當李四進來的時候,李四的年齡比張三小,掛在張三的左邊。當王五進來的時候,王五的年紀比張三大,所以掛在張三的

右邊。當趙六的進來的時候,和張三比較年齡結(jié)果趙六大,掛在張三的右邊,在和王五比較結(jié)果比王五小,掛在王五的左邊。

結(jié)果排序就是:李四、張三、趙六、王五

2.2)按年齡為主要條件,名字是次要條件

4.3.3、比較器順序(Comparator)

首先我們查看TreeSet的構(gòu)造方法發(fā)現(xiàn)有一個這樣的構(gòu)造方法:

//指定TreeSet的比較器

TreeSet(Comparator super E> comparator)

通過查看它的構(gòu)造方法就知道可以傳入一個比較器。

構(gòu)造一個新的空TreeSet,它根據(jù)指定比較器進行排序。插入到該 set 的所有元素都必須能夠由指定比較器進行相互比較:對于 set 中的任意兩個元素 e1 和e2,執(zhí)行 comparator.compare(e1, e2) 都不得拋出 ClassCastException。

如果用戶試圖將違反此約束的元素添加到 set 中,則 add 調(diào)用將拋出 ClassCastException。

1)TreeSetd的Comparetor比較器實現(xiàn)的二種方法

第一種:寫個類實現(xiàn)Comparator接口

classmyComparator implements Comparator{

@Overridepublic intcompare(Object o1, Object o2) {

Person p1=(Person) o1;

Person p2=(Person) o2;int num =p1.getName().compareTo(p2.getName());//0的話是兩個相同,進行下一個屬性比較

if (num == 0){return new Integer(p1.getAge()).compareTo(newInteger(p2.getAge()));

}returnnum;

}

}

然后在new Set的時候放進去。如

TreeSet ts= new TreeSet(new myComparator());

myComparator

第二種:寫內(nèi)名內(nèi)部類方法

TreeSet ts = new TreeSet(newComparator() {

@Overridepublic intcompare(Object o1, Object o2) {

Person p1=(Person) o1;

Person p2=(Person) o2;int num =p1.getName().compareTo(p2.getName());if (num == 0){return new Integer(p1.getAge()).compareTo(newInteger(p2.getAge()));

}returnnum;

}

});

View Code

總結(jié)

以上是生活随笔為你收集整理的java8 迭代set集合_JavaSE(八)集合之Set的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。