Set:無序,不可以重複。
Set集合集合中的方法和Collection是一緻的。它的取出方式隻有一種。疊代器。
|-HashSet:底層資料結構是哈希表,該集合是線程不同步的。
HashSet集合是如何保證元素唯一性的呢?
通過元素的hashCode方法和equals方法來完成的唯一性的判斷。
如果hashCode值相同,再繼續判斷元素的equals方法是否為true
如果hashCode值不同,不會判斷equals方法。
HashSet的contains和remove依據都是hashCode方法,如果該方法傳回值相同,才判斷equals方法。
|-TreeSet:它可以給Set集合中的元素進行指定方式的排序。也是線程不同步的。
保證元素唯一性的方式:通過比較的結果是否為0.
底層資料結構是:二叉樹。(紅黑樹結構)
排序第一種方式:學生需要進行比較,就必須要讓學生具備比較性。那麼,就需要學生實作Comparable接口,強制讓學生具備比較性。
複寫Comparable接口裡的 int CompareTo()方法,此方法的傳回值有三種,
負數:該元素小于被對比的元素
0,該元素等于被對比的元素
正數:該元素排序的順序大于被對比的元素,即排序越靠後。
讓元素自身具備比較性。隻要讓元素實作java.lang.Comparable接口,覆寫compareTo方法即可。
但是,如果元素自身不具備比較性,或者元素自身具備的比較性,不是所需要的。
比如,學生的自然排序是按年齡排序,現在想要按照學生姓名排序。還可以不改動原有代碼。
這時怎麼辦呢?
排序的第二種方式:自定比較器的方式。
這時可以讓集合自身具備比較性。
可以定義一個類實作java.util.Comparator接口,覆寫compare方法。将該Comparator接口子類對象作為實際參數
傳遞給TreeSet集合構造函數。
下面看一下HashSet的一個例子:
public class HashSetOverView {
public static void main(String[] args) {
HashSet hs = new HashSet();
hs.add(new Person("abc0",20));
hs.add(new Person("abc6",26));
hs.add(new Person("abc1",21));
hs.add(new Person("abc6",26));
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
// System.out.println(hs.contains(new Person("abc6",26)));這樣的話會調用equals方法,删掉相同的人。
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public int hashCode()
{
System.out.println(this.name+"...hashCode");
final int NUMBER = 49;
return name.hashCode()+age*NUMBER;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
throw new ClassCastException("類型不比對");
Person p = (Person)obj;
System.out.println(this.name+" equals run "+p.name);
return this.name.equals(p.name) && this.age==p.age;
}
public String toString()
{
return name+"::"+age;
}
}
HashSetOverView類的main方法執行結果為:
abc0...hashCode
abc6...hashCode
abc1...hashCode
abc6...hashCode
abc6 equals run abc6
abc0--20
abc1--21
abc6--26
下面在看一下TreeSet集合的一個例子是怎樣保持元素有序與唯一性的
package cn.java.collection.set;
import java.util.TreeSet;
/*TreeSet的第一種比較方式,并用資料類型本身的比較方法。需要比較的元素實作compareble接口,并實作其compareTo方法*/
//年齡相等的情況下,用姓名排序
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Student1("lisi0:",30));
ts.add(new Student1("lisixx:",29));
ts.add(new Student1("lisi9:",29));
ts.add(new Student1("lisi8:",38));
ts.add(new Student1("lisixx:",29));
ts.add(new Student1("lisi4:",14));
ts.add(new Student1("lisi7:",27));
System.out.println(ts);
}
}
//讓元素自身具備比較性
class Student1 implements Comparable{
private String name;
private int age;
Student1(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;
}
public int compareTo(Object o) {
Student1 stu=(Student1)o;
int num=new Integer(this.age).compareTo(new Integer(stu.age));
return num==0?this.name.compareTo(stu.name):num;
/*Student stu=(Student)o;
if(this.age>stu.age)
return 1;
if(this.age==stu.age)
return 0;
return 1;*/
}
public String toString() {
return name+this.age;
}
}
上面TreeSetDemo的main方法執行的結果為:
[lisi4:14, lisi7:27, lisi9:29, lisixx:29, lisi0:30, lisi8:38]
此類裡的compareTo方法既是可以決定排序關鍵,也是保證唯一性的關鍵
TreeSet排序的第二種方式:
package cn.java.collection.set;
import java.util.Comparator;
import java.util.TreeSet;
/*
TreeSet:它可以給Set集合中的元素進行指定方式的排序。
保證元素唯一性的方式:通過比較的結果是否為0.
底層資料結構是:二叉樹。
排序的第一種方式:
讓元素自身具備比較性。隻要讓元素實作java.lang.Comparable接口,覆寫compareTo方法即可。
但是,如果元素自身不具備比較性,或者元素自身具備的比較性,不是所需要的。
比如,學生的自然排序是按年齡排序,現在想要按照學生姓名排序。還可以不改動原有代碼。
這時怎麼辦呢?
排序的第二種方式:自定比較器的方式。
這時可以讓集合自身具備比較性。
可以定義一個類實作java.util.Comparator接口,覆寫compare方法。将該Comparator接口子類對象作為實際參數
傳遞給TreeSet集合構造函數。
該對象就是比較器。
*/
public class TreeSetDemo3 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new StudentComparatorByName());
ts.add(new Student1("lisi0:",30));
ts.add(new Student1("lisixx:",29));
ts.add(new Student1("lisi9:",29));
ts.add(new Student1("lisi8:",38));
ts.add(new Student1("lisixx:",29));
ts.add(new Student1("lisi4:",14));
//ts.add(new Student(39));
ts.add(new Student1("lisi7:",27));
System.out.println(ts);
}
}
/*
* 建立一個比較器,實作comparator
*/
class StudentComparatorByName implements Comparator<Student1>{
@Override
public int compare(Student1 s1, Student1 s2) {
Student1 stu=(Student1)s1;
Student1 stu2=(Student1)s2;
int num=stu.getName().compareTo(stu2.getName());
return num==0?new Integer(stu.getAge()).compareTo(new Integer(stu2.getAge())):num;
}
}
//讓元素自身具備比較性
class Student1 implements Comparable{
private String name;
private int age;
Student1(String name,int age){
this.name=name;
this.age=age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Object o) {
Student1 stu=(Student1)o;
if(this.age>stu.age)
return 1;
if(this.age==stu.age)
return 0;
return 1;
}
@Override
public String toString() {
return this.getName()+this.age;
}
}
TreeSet排序的第二種方式執行結果為:
[lisi0:30, lisi4:14, lisi7:27, lisi8:38, lisi9:29, lisixx:29]