Java學習之路(八):Set

Set集合概述以及特色:

  • set 是一個不包含重複元素的collection
  • set只是一個接口,通常使用它的子類HashSet,LinkedHashSet,TreeSet

HashSet

  • 此類是Set接口的實現類,有哈希表支持
  • 它不保證set的迭代順序,特別是不保證順序的恆久不變
  • 此類容許使用null元素

咱們通常使用HashSet來去重:java

  • 咱們須要重寫累的hashCode()和equals()方法

HashSet去重的依據:面試

  首先會比較hashCode(),若是不同則存進去,若是同樣的話,調用equals()方法進行比較,若是返回True就不存儲,false存儲數組

面試題:爲何自動生成hashCode的時候有個31的數?less

31是一個質數,質數是能被1和本身自己整除的數,沒有公約數

31剛恰好,既不大也不小

31這個數好算,2的五次方-1,至關於向左移5位-1
答案

案例:產生10個1-20之間的隨機數要求隨機數不能重複dom

package l1;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

public class Demo01 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Set<Integer> set = new HashSet<Integer>();
        Random rd = new Random();
        while(set.size()!=10){
            int r = rd.nextInt(21);  //生成1-20之間的隨機數
            if(r!=0){
                set.add(r);
            }
        }
        System.out.println(set);
        
        
    }

}

 案例:從鍵盤讀取一行輸入,去掉重複字符並打印ide

package l2;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Demo2 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入一行內容");
        String line = sc.nextLine();
        
        //將字符串轉化爲字符數組
        char[] ch = line.toCharArray();
        
        Set<Character> set = new HashSet<Character>();
        for(char a:ch){
            set.add(a);
        }
        
        System.out.println(set);
    }

}

 

 案例:使用HashSet()過濾List集合中的重複的元素函數

package l3;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Demo3 {

    public static void main(String[] args) {
        List<String> li = new ArrayList<String>();
        li.add("A");
        li.add("B");
        li.add("A");
        li.add("A");
        Set<String> set = new HashSet<String>();
        set.addAll(li);
        System.out.println(set);

    }

}

 

 LinkedHashSet的概述和使用

  • LinkedHashSet是一個具備可預知迭代順序的Set接口
  • 內部實現是使用哈希表和連接列表
  • LinkedHashSet的特色是能夠保證怎麼存就怎麼取
  • LinkedHashSet是set集合中惟一一個能保證怎麼存就怎麼取的集合對象
  • LinkedHashSet是HashSet的子類,因此也是保證元素惟一的,實現原理和HashSet同樣

TreeSet的概述和使用 

  • TreeSet是一個能夠用於排序的集合、
  • TreeSet給予TreeMap的NavigableSet實現
  • TreeSet的排序方法有兩種:
    • 使用元素的天然順序Comparable對元素進行排序
    • 使用構造方法的Comparator進行排序

使用TreeSet 存儲自定義對象:ui

注意:使用TreeSet存儲自定義對象是會出現異常:xxxx cannot be cast to java.lang.Comparablethis

  • 若是想用TreeSet存儲自定義對象,這個對象必需要實現Comparable接口
  • 此接口強行堆實現它的每一個類的對象進行排序
  • 這種排序被稱爲天然排序,類的compareTo方法被成爲它的天然比較方法
  • 當compareTo方法返回0的時候,集合只會保留一個元素
  • 當compareTo方法返回正數的時候,集合怎麼存就怎麼取
  • 當compareTo方法返回負數的時候,集合會倒序存儲

TreeSet存儲自定義對象並遍歷

package lesson0001;

import java.util.Set;
import java.util.TreeSet;

public class Demo1 {

    public static void main(String[] args) {

        Set<Student> set = new TreeSet<Student>();
        set.add(new Student(1,"n1"));
        set.add(new Student(2,"n2"));
        set.add(new Student(3,"n3"));
        for(Student std:set){
            System.out.println(std);
        }
    }

}

class Student implements Comparable{
    private int age;
    private String name;
    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 String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Student(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }
    @Override
    public int compareTo(Object arg0) {
        return 1;
    }
}

 

以上是最簡單的一個例子,而後呢,咱們如今須要實現:spa

  TreeSet存儲自定義對象而且遍歷,並且要按照姓名長度,字母,年齡順序排序

  • 經過比較字符串的compareTo比較大小
  • 排序按照unicode碼的大小進行排序
  • 防止名字相同,但年齡不一樣的Bug
package lesson0002;

import java.util.Set;
import java.util.TreeSet;

public class Demo1 {

    public static void main(String[] args) {

        Set<Student> set = new TreeSet<Student>();
        set.add(new Student(1,"aaaa"));
        set.add(new Student(5,"aaaa"));
        set.add(new Student(2,"aaaa"));
        set.add(new Student(1,"aaa"));
        set.add(new Student(1,"aa"));
        for(Student std:set){
            System.out.println(std);
        }
        
    }

}
main代碼
package lesson0002;

public class Student implements Comparable<Student> {
    private int age;
    private String name;
    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;
    }
    

    public Student(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public int compareTo(Student o) {
        int length = this.name.length() - o.name.length();
        int num = length == 0?this.name.compareTo(o.name):length;
        return num == 0?this.age-o.age:num;
    }
    @Override
    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
    

    
}
Student類

 

TreeSet除了這種自定義排序意外還能夠定義一種自定義排序:比較器(Comparator)

package lesson0003;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

//比較器排序


public class Demo1 {

    public static void main(String[] args) {

        Set<String> set = new TreeSet<String>(new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                
                int num = o1.compareTo(o2);//默認的從小到大
                num = num==0?1:num;  //若是相同返回1,即保存同名的元素
                return num;
            }
        });
        
        
        set.add("aaa");
        set.add("bbb");
        set.add("ccc");
        set.add("aaa");
        set.add("aa");
        for(String s:set){
            System.out.println(s);
        }
    }

}

 

TreeSet的總結

TreeSet是用來排序的,能夠指定一個順序,對象存入以後會按照指定的順序排序

TreeSet的排序方式有兩種:

  • 天然排序
  • 比較器順序

天然順序:

  1. TreeSet類的add方法會把存入的對象提高爲Comparable類型
  2. 調用對象的compareTo方法進行比較
  3. 根據compareTo方法返回的結果進行一個存儲

比較器順序:

  1. 建立TreeSet的時候能夠定製一個Comparator
  2. 若是傳入了Comparator的子類對象,那麼TreeSet就會按照比較器的規則比較
  3. add方法內部會調用Comparator接口中的compare方法排序
  4. 調用的對象是compare方法的第一個參數,集合中的對象是compare方法的第二個參數

天然排序和比較器排序的區別:

  • TreeSet構造函數什麼都不傳,默認按照類中的Comparable的排序
  • TreeSet若是傳入Comparator,就優先按照Comparator(即,比較器排序要優先)

練習題案例:

1.在一個集合中存儲了無序而且重複的字符串,讓其有序,並且不能去除重複

我上面例子中,比較器排序的那個例子就是
答案

 

2.從鍵盤輸入多個整數,直到輸入quit時結束輸入。把全部輸入的整數倒敘排列打印

package lesson0004;

import java.util.Comparator;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Demo01 {

    public static void main(String[] args) {
        
        Set<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {
                // TODO Auto-generated method stub
                return (o2-o1)==0?1:(o2-o1);
//                return o2-o1;
            }
        });
        
        Scanner sc = new Scanner(System.in);
        while(true){
            String str = sc.nextLine();
            if("quit".equals(str)){
                break;
            }else{
                set.add(Integer.parseInt(str));
            }
        }
        for(Integer i:set){
            System.out.println(i);
        }

        
        
    }

}
答案

 

 

 

3.鍵盤錄入學生信息按照總分排序後輸出在控制檯

package lesson0005;

import java.util.Comparator;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Demo1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Set<Student> set = new TreeSet<Student>();
        
        Scanner sc = new Scanner(System.in);
        while(true){
            System.out.println("請按照格式輸入學生信息(學生名:年齡:成績)");
            String line = sc.nextLine();
            if("quit".equals(line)){
                break;
            }else{
                String name = line.split(":")[0];
                int age = Integer.parseInt(line.split(":")[1]);
                int score = Integer.parseInt(line.split(":")[2]);
                set.add(new Student(name,age,score));
            }
        }
        for(Student std:set){
            System.out.println(std);
        }
        
        
    }

}
答案:main
package lesson0005;

public class Student implements Comparable<Student> {

    private String name;
    private int age;
    private int score;
    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 getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
    }
    public Student() {
        super();
    }
    public Student(String name, int age, int score) {
        super();
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public int compareTo(Student o) {
        int num = o.score - this.score;
        num =  num==0?this.name.compareTo(o.name):num;
        num =  num==0?(this.age-o.age):num;
        return num==0?1:num;
    }
    
    
    
}
答案:Student類
相關文章
相關標籤/搜索