集合Set(上)

Set

常用方法:直接查看api

HashSet

元素唯一,但是无序(它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变)
案例:创建一个HashSet集合,添加元素(String元素),测试唯一性,无序性

package com.edu_01;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
    public static void main(String[] args) {
        //创建一个HashSet集合
        HashSet<String> set = new HashSet<String>(); 
        //给集合中添加元素
        set.add("hello");
        set.add("java");
        set.add("world");
        set.add("c++");
        set.add("php");
        set.add("hello");
        //遍历集合
        /* HashSet集合特点:
         * 1.元素无序
         * 2.元素唯一*/
        for (String string : set) {
            System.out.println(string);
        }
        //为什么在String类型中不用重写HashCode()和equals()方法
        //因为String类型中,本来就包含了HashCode()和equals()方法
    }
}

如何保证元素的唯一性的呢?
HashSet集合保证元素的唯一性和add()方法相关。
看add()方法的源码,看它的底层依赖什么内容?
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {…}

  • 左边:e.hash == hash
  • 比较对象的哈希值。
  • 右边:((k = e.key) == key || key.equals(k))
  • 左边:(k = e.key) == key
  • 比较对象的地址值。
  • 右边:key.equals(k)
  • 比较的是对象的内容是否相同。默认情况下比较的是地址值

结论:
底层数据结构是哈希表。
哈希表依赖两个方法:hashCode()和equals()

执行流程:
首先判断哈希值是否相同,如果不同,就直接添加到集合。
如果相同,继续执行equals(),看其返回值,
如果是false,就直接添加到集合。
如果是true,说明元素重复不添加。

使用:
如果你看到哈希结构的集合,就要考虑可能需要重写这两个方法。
如果真要重写,自动生成即可。

哈希表结构:是一个元素为链表的数组结构
元素的哈希码值作为索引,元素本身的值作为数组的值存入到数组中
所以在存储过程中,先比较元素的哈希码值是否相同,如果不同,则直接添加,通过重写HashCode()方法,如果元素的哈希码值相同,在通过重写的equals()方法比较元素的地址值或者内容,如果有一个相同则该元素不能够存储

知识点
1.存储String类型的元素,说明元素无序且唯一
2.分析add()方法,保证唯一性的原理(底层依赖于hashCode()和equals()方法,保证了元素的唯一性)
3.存储自定义对象,如何保证元素的唯一性?(存储相同元素,发现无法保证元素的唯一性)
hashcode()方法保证了字符串的哈希码值相同,equals()保证了字符串的地址值和内容相同

public class HashSetDemo {
 public static void main(String[] args) {
  //创建一个HashSet集合
  HashSet<String> set = new HashSet<String>(); 

  //给集合中添加元素
  set.add("hello");
  set.add("java");
  set.add("world");
  set.add("c++");
  set.add("php");
  set.add("hello");
  //遍历集合
  /*HashSet集合特点:
   * 1.元素无序
   * 2.元素唯一*/
  for (String string : set) {
   System.out.println(string);
  }
 }
}

TreeSet

元素唯一,元素有序使用元素的自然顺序对元素进行排序,或者根据创建 set时提供的 Comparator进行排序(比较器排序),具体取决于使用的构造方法。
**底层算法:**二叉树
元素要求: 加入自定义JavaBean

二叉树结构存储数据的规则:
1.当存入第二个元素的时候会与第一个元素做减法,如果差值为负,说明你存的这个元素比之前的小往左边放
2.如差值为正,说明比之前存的值大,往右边放
3:如果值为0,说明相等则不存储
二叉树:根据compareTo()方法的返回值来确定要存入元素的安放位置。
在这里插入图片描述
案例演练:
案例1.创建集合存储Integer类型的元素(20,66,23,22,39,26,19,19,99),分析如何保证元素唯一性,以及排序的规则。
二叉树:根据compareTo()方法的返回值来确定要存入元素的安放位置。

import java.util.TreeSet;
public class TreeSetDemo {
 public static void main(String[] args) {
  /*
   * 1.创建集合存储Integer类型的元素(20,66,23,22,39,26,19,19,99)
   * 2.分析如何保证元素唯一性,以及排序的规则。
   * 3.二叉树(首先讲解二叉树数据结构是怎么存入元素的,根据compareTo()方法的返回值来确定要存入元素的安放位置)*/
  //创建一个TreeSet集合
  /*TreeSet集合特点:
  1.元素唯一   2.元素有序*/
  TreeSet<Integer> ts = new TreeSet<Integer>();
  //给集合中存储元素
  //(20,66,23,22,39,26,19,19,99)
  ts.add(20);
  ts.add(66);
  ts.add(23);
  ts.add(22);
  ts.add(39);
  ts.add(26);
  ts.add(19);
  ts.add(19);
  ts.add(99);
  //遍历集合
  for (Integer integer : ts) {
   System.out.println(integer);
  }
 }
}

案例2.存储字符串并遍历(字母a-z排序)

import java.util.TreeSet;
public class TreeSetDemo2 {
 public static void main(String[] args) {
  //创建一个TreeSet集合
  //当存入字符串的时候,按照字典顺序进行排序
  TreeSet<String> ts = new TreeSet<String>();

  //存入字符串
  ts.add("linzhiling");
  ts.add("amu");
  ts.add("bigbang");
  ts.add("guodegang");

  //遍历集合
  for (String string : ts) {
   System.out.println(string);
  }
 }
}

3.存入学生对象(姓名,年龄),1.按年龄排序,2.姓名排序(自然排序实现Comparable接口,并重写comparaTo()

 import java.util.TreeSet;
 
 public class Student implements Comparable<Student>{
 private String name;
 private int age;
 public Student(String name, int age) {
  super();
  this.name = name;
  this.age = age;
 }
 public Student() {
  super();
  // TODO Auto-generated constructor stub
 }
 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 + "]";
 }
 //实现Comparable接口的同时必须实现这个比较法
 @Override
 public int compareTo(Student s) {
  //就是写的是元素的比较规则,由你自己去动手写出
  //按照学生的年龄进行排序
  /* 两个对象进行比较:
   * s
   * this */
  int num = this.age - s.age;
  //判断年龄是否相同,如果相同比较姓名
  /* 写这个比较规则的时候注意两点:
   * 1.他有主要条件,先按照主要条件进行排序
   * 2.如果主要条件相同,就需要你自己分析出来他的次要条件,再去按照次要条件进行比较 */
  int num2 = num==0?this.name.compareTo(s.name):num;
  return num2;
 	}
 }
发布了62 篇原创文章 · 获赞 55 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Veer_c/article/details/103825477