集合(二):Set : HashSet; LinkedHashSet; TreeSet

集合(二)

Set

    概述及特點:元素唯一,即一個不包含重複元素的 collection。更確切地講,
set 不包含滿足 e1.equals(e2) 的元素對 e1 和 e2,並且最多包含一個 null 元素。

一、HashSet

1、概述及特點

    概述及特點:HashSet 底層數據結構是哈希表,線程不安全,效率高,元素無序(存取順序
不一致),且唯一(元素不可重複),可以是 null。
    哈希表:JDK1.7之前是數組+鏈表,JDK1.8之後爲數組+鏈表+二叉樹

2、HashSet元素唯一性解析及代碼優化

在這裏插入圖片描述

代碼優化

import java.util.HashSet;
import java.util.Objects;

public class Blog1 {
    public static void main(String[] args) {
        //HashSet 之所以能夠保證元素的唯一性,是靠元素重寫 equals()和hashCode()方法來保證的,如果元素不重寫該方法,則不能保證元素的唯一性
        //合理重寫hashCode()方法,可以減少調用equals()的次數,也稱之爲減少碰撞
        //原因:只有當兩個對象hashCode()的返回值相同時,纔會去調用equals()方法,比較成員變量的內容
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("張三",23));
        hashSet.add(new Student("李四",27));
        hashSet.add(new Student("王五",26));
        hashSet.add(new Student("張三",23));
        hashSet.add(new Student("李四",27));
        hashSet.add(new Student("王五",26));
        hashSet.add(new Student("趙六",25));
        hashSet.add(new Student("張三",24));
        hashSet.add(new Student("曾七",23));
        System.out.println(hashSet);
    }
}
class Student{
    String name;
    int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    static int count=1;//統計變量
    @Override
    public boolean equals(Object o) {
        System.out.println("equals()方法執行了"+(count++)+"次");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}	
運行結果:
equals()方法執行了1equals()方法執行了2equals()方法執行了3[Student{name='張三', age=23}, Student{name='李四', age=27}, Student{name='王五', age=26}, Student{name='趙六', age=25}, Student{name='張三', age=24}, Student{name='曾七', age=23}]

Process finished with exit code 0

二、LinkedHashSet

    概述及特點:LinkedHashSet 底層數據結構是鏈表和哈希表,元素有序且唯一,
鏈表保證了有序,哈希表保證了唯一,線程不安全,效率高

三、TreeSet

1、概述及特點

    概述及特點:TreeSet 底層數據結構是二叉樹,元素唯一,且可以對元素進行排序,
              排序:自然排序,比較器排序

二叉樹存儲數據保證元素唯一性且排序原理圖解

在這裏插入圖片描述

2、自然排序

    自然排序:如果TreeSet()採用的是空參構造,那麼採用的就是自然排序,自然排序要求元素必須
實現一個Comparable接口,並實現這個接口中的一個compareTo比較方法,根據此方法的返回值的
正(右邊) 、負(左邊)  0(兩元素相同,不再向集合添加) 來決定元素排列的位置。

演示

import java.util.TreeSet;

public class Blog2 {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("張三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("張三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("趙六",25));
        treeSet.add(new Student("張三",24));
        treeSet.add(new Student("曾七",23));
        //按照年齡從小到大排序
        System.out.println(treeSet);
    }
}
class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student() {
    }

    public Student(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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //重寫比較方法
    @Override
    public int compareTo(Student o) {
        //先比較年齡大小,如果年齡大小一樣,再去比較名字,如果不比較名字,年齡相同的人就存不到集合中去了
        int num=this.age-o.age;
        int num1=num==0?this.name.compareTo(o.name):num;
        return num1;
    }
}
運行結果:
[Student{name='張三', age=23}, Student{name='曾七', age=23}, Student{name='張三', age=24}, Student{name='趙六', age=25}, Student{name='王五', age=26}, Student{name='李四', age=27}]

Process finished with exit code 0

3、比較器排序

比較器排序:採用有參構造,在創建TreeSet對象時,需要傳入一個Comparetor 比較器
        //TreeSet(Comparator < ? super E > comparator)
Comparator<T> 比較器:
        int compare (T o1, T o2);//比較用來排序的兩個參數。

演示

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

public class Blog3 {
    public static void main(String[] args) {
        //傳入比較器方式:1、可以自己創建一個Comparator<T>接口的子類,並實現 compare方法,傳入該接口的子類對象
        //              2、使用匿名內部類,傳入比較器,並實現compare方法
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num=o1.getAge()-o2.getAge();
                int num1=num==0?o1.getName().compareTo(o2.getName()):num;
                return num1;
            }
        });
        treeSet.add(new Student("張三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("張三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("趙六",25));
        treeSet.add(new Student("張三",24));
        treeSet.add(new Student("曾七",23));
        //按照年齡從小到大排序
        System.out.println(treeSet);
    }
}
class Student{
    private String name;
    private int age;

    public Student() {
    }

    public Student(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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
運行結果:
[Student{name='張三', age=23}, Student{name='曾七', age=23}, Student{name='張三', age=24}, Student{name='趙六', age=25}, Student{name='王五', age=26}, Student{name='李四', age=27}]

Process finished with exit code 0

4、例題

//需求:編寫一個程序,獲取10個1至20的隨機數,要求隨機數不能重複,且要對其進行排序
/*-----示例-----*/
import java.util.Random;
import java.util.TreeSet;

public class Blog4 {
    public static void main(String[] args) {
        int number=10;
        Random random = new Random();
        TreeSet<Integer> treeSet = new TreeSet<>();
        //Integer類已經實現Comparable接口,默認從小到大排序
        for (int i = 0; i < number; i++) {
            boolean flag=treeSet.add(random.nextInt(20)+1);//生成隨機數嘗試添加到集合,並獲取是否添加成功的結果
            if(!flag){
                i--;//如果未添加成功,讓i-1,多生成一個隨機數添加嘗試添加到集合
            }
        }
        System.out.println(treeSet);
    }
}
運行結果:
[1, 5, 6, 7, 10, 11, 12, 14, 15, 17]

Process finished with exit code 0

四、Collections工具類

A:Collections類概述:	針對集合操作的工具類
B:Collections常用成員方法
	public static <T> void sort(List<T> list):					排序,默認按照自然順序
	public static <T> int binarySearch(List<?> list,T key):		二分查找
	public static <T> T max(Collection<?> coll):				獲取最大值
	public static void reverse(List<?> list):					反轉集合元素
	public static void shuffle(List<?> list):					隨機打亂元素
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章