天天看點

Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合

Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合

Set集合

1.Set集合:

無序(存儲和取出的順序)和唯一

Set接口:的三個子類 HashSet,LinkedHashSet, TreeSet

HashSet:底層資料結構是哈希表,元素無序(存的順序和取的順序不一緻),且不允許重複元素,可以存儲null元素,線程不安全,效率高!

package org.westos.demo1;

import java.util.HashSet;

public class MyTest2 {
    public static void main(String[] args) {
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(100);
        hashSet.add(100);
        hashSet.add(100);
        hashSet.add(200);
        hashSet.add(300);
        hashSet.add(400);
        hashSet.add(500);
        hashSet.add(500);
        hashSet.add(500);
        System.out.println(hashSet);

        //String類和Integer類中都重寫了hashCode()和equals()方法,故列印的不是位址值
        System.out.println("===============================");
        for (Integer integer : hashSet) {
            System.out.println(integer);
        }
    }
}
  
           

HashSet保證元素唯一性

HashSet 底層資料結構是哈希表. HashSet 不是線程安全的 集合元素可以是 null

哈希表:是一個元素為連結清單的數組,綜合了數組和連結清單的優點 (像新華字典一樣)

Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合
代碼:
public class MyTest {
    public static void main(String[] args) {
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("張三",23));
        hashSet.add(new Student("張三", 23));
        hashSet.add(new Student("李四", 24));
        hashSet.add(new Student("王五", 25));
        hashSet.add(new Student("趙六", 26));
        hashSet.add(new Student("趙六", 26));
        hashSet.add(new Student("田七", 27));
        for (Student student : hashSet) {
            System.out.println(student.getName()+"==="+student.getAge());
        }

        //當我們往hashset集合存儲對象的時候,會調用對象的hashCode方法,算出一個值,這個值就是确定這個對象放到表中的位置。
        //那假如有兩個對象,算出的位置值是一樣的,就會調用equals()方法,去比較兩個對象的位址值是否一樣,如果不一樣那就存儲進去,形成連結清單結構

        //為了減少碰撞,我們應該合理的去重寫hashCode方法,來減少碰撞(減少調用euquals方法的次數)盡量是元素在哈希表中橫向排列,減少連結清單的形成
    }
}

           
Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合

​ 當往hashset集合存儲對象的時候,會調用對象的hashCode方法,算出一個值,這個值就是确定這個對象放到表中的位置。

​ 假如有兩個對象,算出的位置值是一樣的,就會調用equals()方法,去比較兩個對象的位址值是否一樣,如果不一樣那就存儲進去,形成連結清單結構

​ 為了減少碰撞,我們應該合理的去重寫hashCode方法,來減少碰撞(減少調用euquals方法的次數)盡量是元素在哈希表中橫向排列,減少連結清單的形成。

結論:HashSet 保證元素唯一性是靠元素重寫hashCode()和equals()方法來保證的,如果不重寫則無法保證。

HashSet集合可以使用疊代器來周遊

代碼:
package org.westos.demo5;

import java.util.HashSet;
import java.util.Iterator;

public class MyTest1 {
    public static void main(String[] args) {
        HashSet<Integer> integers = new HashSet<>();
        integers.add(100);
        integers.add(200);
        integers.add(300);
        //使用疊代器來周遊set集合
        Iterator<Integer> iterator = integers.iterator();
        while (iterator.hasNext()) {
            Integer next = iterator.next();
            System.out.println(next);
        }
    }
}

           

LinkedHashSet集合

LinkedHashSet底層的資料結構是連結清單和哈希表

連結清單保證有序 哈希表保證元素唯一

LinkedHashSet集合的特點:元素有序 , 并且唯一

代碼:
public class MyTest {
    public static void main(String[] args) {
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("張三");
        linkedHashSet.add("李四");
        linkedHashSet.add("王五");
        linkedHashSet.add("趙六");
        linkedHashSet.add("田七");
        linkedHashSet.add("劉八");

        linkedHashSet.add("張三");
        linkedHashSet.add("李四");
        linkedHashSet.add("王五");
        linkedHashSet.add("趙六");
        linkedHashSet.add("田七");
        linkedHashSet.add("劉八");
        for (String s : linkedHashSet) {
            System.out.println(s);
        }
    }
}

           
Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合

TreeSet集合

TreeSet集合的特點: 元素唯一,并且可以對元素進行排序

排序:

a: 自然排序 使用的是無參構造

注意:使用TreeSet集合進行元素的自然排序,那麼對元素有要求,要求這個元素

必須實作Comparable接口 否則無法進行自然排序

Comparable接口中需要重寫comparaTo方法, 保證元素的唯一性是靠compareTo方法的傳回值來确定如果傳回0 表示兩個元素相等,則不重複存儲

​ b: 使用比較器排序

​ 到底使用的是哪一種的排序取決于,構造方法.

TreeSet集合保證元素唯一性圖解

Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合
1.自然排序:
public 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 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 int compareTo(Student o) {
        int num = this.age - o.age;
        int num2 = num == 0 ? this.name.compareTo(o.name) : num;
        //從小到大
        return  num2;
        //從大到小
        //return -num2;
    }

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

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("張三",33));
        treeSet.add(new Student("李四", 24));
        treeSet.add(new Student("王五", 38));
        treeSet.add(new Student("趙六", 26));
        treeSet.add(new Student("張三", 33));
        treeSet.add(new Student("張三", 33));
        treeSet.add(new Student("王老五", 33));

        for (Student student : treeSet) {
            System.out.println(student.getName()+"==="+student.getAge());
        }
    }
}

           
2.比較器排序:
public class MyTest {
    public static void main(String[] args) {
      /*  構造方法摘要
        TreeSet()
        構造一個新的空 set,該 set 根據其元素的自然順序進行排序。*/


      /*  TreeSet(Comparator < ? super E > comparator)
        構造一個新的空 TreeSet,它根據指定比較器進行排序。*/
        // Comparator 接口 強行對某個對象 collection 進行整體排序 的比較函數。

        //采用比較器排序,根據比較器中的compare()這個方法的傳回值的正負0 來決定元素在二叉樹中放置的位置
        TreeSet<Integer> treeSet = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return a-b;
            }
        });
        treeSet.add(20);
        treeSet.add(20);
        treeSet.add(20);
        treeSet.add(10);
        treeSet.add(200);
        treeSet.add(30000);
        treeSet.add(120);
        treeSet.add(200);
        treeSet.add(20999);
        for (Integer integer : treeSet) {
            System.out.println(integer);
        }
    }
}


           

案例:需求:編寫一個程式,擷取10個1至20的随機數,要求随機數不能重複。

public class MyTest {
    public static void main(String[] args) {
        //需求:編寫一個程式,擷取10個1至20的随機數,要求随機數不能重複。
        Random random = new Random();
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
        while (linkedHashSet.size() < 10) {
            int num = random.nextInt(20) + 1;
            linkedHashSet.add(num);
        }
        System.out.println(linkedHashSet);
    }
}

           

案例:

案例示範:
需求:鍵盤錄入3個學生資訊(姓名, 國文成績, 數學成績, 英語成績), 按照總分從高到低輸出到控制台
           
代碼:
public class Student{
    //姓名,國文成績,數學成績,英語成績
    private String name;
    private int chineseScore;
    private int mathScore;
    private int englishScore;

    public Student() {
    }

    public Student(String name, int chineseScore, int mathScore, int englishScore) {
        this.name = name;
        this.chineseScore = chineseScore;
        this.mathScore = mathScore;
        this.englishScore = englishScore;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getChineseScore() {
        return chineseScore;
    }

    public void setChineseScore(int chineseScore) {
        this.chineseScore = chineseScore;
    }

    public int getMathScore() {
        return mathScore;
    }

    public void setMathScore(int mathScore) {
        this.mathScore = mathScore;
    }

    public int getEnglishScore() {
        return englishScore;
    }

    public void setEnglishScore(int englishScore) {
        this.englishScore = englishScore;
    }

    //提供一個擷取總分的方法
    public int getTotalScore(){
        return chineseScore+mathScore+englishScore;
    }

}

public class MyTest {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                
                int num = s1.getTotalScore() - s2.getTotalScore();
                //考慮同分的情況,總分一樣,并不能說名是同一個學生,還得比較一下姓名
                int num2=num==0?s1.getName().compareTo(s2.getName()):num;
                return -num2;//降序排列
            }
        });
        for (int i = 1; i <= 3; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("請輸入第"+i+"個學生的姓名");
            String name = sc.nextLine();
            System.out.println("請輸入第"+i+"個學生的國文成績");
            int yw = sc.nextInt();
            System.out.println("請輸入第"+i+"個學生的數學成績");
            int sx = sc.nextInt();
            System.out.println("請輸入第" + i + "個學生的英語成績");
            int yy = sc.nextInt();
            //建立學生對象,把錄入的資訊,封裝到學生學生對象裡面
            Student student = new Student(name, yw, sx, yy);
            treeSet.add(student);

        }
        //按照總分高低排序,輸出學生的資訊。
        System.out.println("名次\t姓名\t國文\t數學\t英語\t總分");
        int i=0;
        for (Student student : treeSet) {
            System.out.println((++i)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore()+"\t"+student.getTotalScore());
        }

    }
}

           

.add(student);

}
    //按照總分高低排序,輸出學生的資訊。
    System.out.println("名次\t姓名\t國文\t數學\t英語\t總分");
    int i=0;
    for (Student student : treeSet) {
        System.out.println((++i)+"\t"+student.getName()+"\t"+student.getChineseScore()+"\t"+student.getMathScore()+"\t"+student.getEnglishScore()+"\t"+student.getTotalScore());
    }

}
           

}

Set集合---- HashSet集合、LinedHashSet集合、TreeSet集合