java 集合 Se HashTreeSet

Set是Collection的子接口,與List相對 
Set集合中的元素的特色是1,無序性 2,無下標3,無重複的元素 
Set是個接口,因此沒法直接建立對象,要依賴它的實現類來建立對象 
Set的實現類有兩個,一個是HashSet,另外一個是TreeSet
css

Set<String> set = new HashSet<>(); set.add("c"); set.add("b"); set.add("d"); set.add("a"); set.add("a"); System.out.println(set);

 

輸出的結果是java

[a, b, c, d]//根據輸出結果,咱們能夠看出set 的無序性和無重複性

 

Set的成員方法基本上都是繼承了collection方法 
下面咱們看一下Set的實現類算法

HashSet 
HashSet是set的實現類,底層是由哈希算法實現的 
由於HashSet中能會添加相同的對象,因此HashSet經常被用來去除集合中重複的元素sql

HashSet<String> hashSet = new HashSet<>(); hashSet.add("a"); hashSet.add("b"); hashSet.add("d"); hashSet.add("d"); System.out.println(hashSet);

 

輸出結果是:json

[a, b, d]

根據輸出的結果能夠看出HashSet確實去除了重複的對象,那麼add的底層實現具體是什麼? 
由於HashSet是由哈希算法來實現的,在一個對象要被添加到集合中的時候,會被系統分配一個哈希值,系統首先會根據這個對象的哈希值去和集合中的對象去比較,若是哈希值不一樣就能夠加入,若是不一樣,就去比較倆字符串的值是否同樣,若是同樣就不能加入,所以把重複的對象是沒法加入HashSet的bash

當咱們加入的對象是數據類型不是系統的數據類型,咱們來看一下HashSet如何去除重複的 
先寫一個StudentL類,student有倆變量,一個是名字.一個是年齡markdown

public class Student { private String name; private int age; public Student(String name, int age) { super(); 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 String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }

 

下面咱們在HashSet集合中添加三個Student類的對象ide

HashSet<Student> hashSet = new HashSet<>(); hashSet.add(new Student("張三", 18)); hashSet.add(new Student("李四", age)); hashSet.add(new Student("張三", 18)); System.out.println(hashSet);

 

輸出的結果是:post

[Student [name=張三, age=18], Student [name=張三, age=18], Student [name=李四, age=19]]

 

能夠看出,倆張三都被添加進去了,可是重複的咱們並不想添加進去,爲何會被添加進去呢 
這時由於在建立student的時候,咱們給每一個對象都在堆內存中開闢了一片空間,雖然倆對象中的元素相等,可是他們的地址是不同的,因此係統認爲他們是不一樣的,因此被添加進去了 
若是咱們要讓系統把student中重複的去掉,咱們只能從底層去操做,由於HashSet是系統內部根據比較Hash值來判斷的,而後在調用equals方法來比較的,因此咱們要重寫Object類中的hashCode和equals方法 
由於咱們要對Student類的對象排序,天然是Student類的對象來調用,因此在Student類中進行方法的重寫flex

//重寫hashCode方法 @Override public int hashCode() //這裏返回的是要添加的對象的哈希值 { return 1; } //重寫equals方法 @Override public boolean equals(Object obj) { Student student = (Student)obj; if (student.name.equals(this.name)&&student.age == this.age) { return true; } return false; } }

咱們再次運行,輸出的結果是:

[Student [name=張三, age=18], Student [name=李四, age=19]]

 

此次能夠看出重複的對象已經被去除了.

TreeSet 
TreeSet是Set的一個實現類,底層是由二叉樹實現的 
下面咱們建立一個TreeSet類型的集合,並將幾個整數裝進去

TreeSet<Integer> treeSet = new TreeSet<>(); treeSet.add(10); treeSet.add(8); treeSet.add(15); treeSet.add(11); treeSet.add(8); System.out.println(treeSet);

 

輸出的結果是

[8, 10, 11, 15]//咱們能夠根據輸出的結果看出TreeSet會將對象排序並將重複的刪除了

 

HashSet的做用就是去除重複的對象,而TreeSet的主要做用就是排序 
下面咱們在TreeSet中添加非系統類的對象 
例:在TreeSet中添加四個學生類對象

TreeSet<Student> treeSet = new TreeSet<>(); treeSet.add(new Student("張三", 18)); treeSet.add(new Student("李四", 19)); treeSet.add(new Student("張三", 18)); System.out.println(treeSet); 

 

當咱們運行的時候,會發現系統會報錯,這是由於咱們添加進去的Student類,不是系統類,系統不知道怎麼排序,因此會報錯 
咱們寫系統類之因此係統會排序,是由於系統類中都實現了Comparable接口中的比較的抽象方法,系統在add的時候,要添加的系統對象會調用這個比較方法,進行排序和去除重複的對象 
因此咱們須要在Student類中實現接口,重寫接口中的比較方法

//重寫comparable接口中的抽象方法,主要是把對象的排序的規則寫進去 @Override //要注意的是當返回值爲0的時候,系統就會認爲倆值是同樣的,就不會添加該對象 public int compareTo(Student o) { // TODO Auto-generated method stub int ageNum = this.age - o.age; int nameNum = this.name.compareTo(o.name); //當年齡同樣的時候,咱們就比較倆者的姓名 return ageNum == 0 ? nameNum :ageNum; }

 

運行獲得的結果是:

[Student [name=張三, age=18], Student [name=李四, age=19]]

能夠看出咱們的運行結果已經根據年齡排序了,可是這種方法有一個侷限,若是該類的對象被裝到倆集合中,排序的條件不一樣,這樣的話就無法重寫抽象方法了.

這時候咱們能夠建立每個集合建立一個比較器,用比較器來排序 
咱們這裏要用到接口Comparator中的比較方法,咱們須要給Comparator接口寫一個實現類,在類中重寫抽象方法 compare(),方法中也是用來寫排序的規則的

public class StudentImpl implements Comparator<Student> { @Override public int compare(Student o1,Student o2) { int intNum = o1.getAge() - o2.getAge(); int nameNum = o1.getName().compareTo(o2.getName()); return nameNum == 0 ? intNum :nameNum; } }

 

在實現了comparator接口後,咱們根據其實現類來爲TreeSet建立一個比較器

TreeSet<Student> treeSet = new TreeSet<>(new StudentImpl()); treeSet.add(new Student("張三", 18)); treeSet.add(new Student("李四", 19)); treeSet.add(new Student("張三", 18)); System.out.println(treeSet);

 

這樣輸出的結果是:

[Student [name=張三, age=18], Student [name=李四, age=19]]

這樣即便student類被裝到不少個集合中,而且排序的條件不一樣,咱們也能夠爲每個集合建立一個特有的比較器來比較

相關文章
相關標籤/搜索