首页 > 技术文章 > Set详解

Shuangyi 2019-05-29 12:00 原文

Set集合:

  1. 元素不可重复
  2. hashCode 特点:速度快,数组->链表->红黑树
  3. set集合报错元素唯一:
    存储元素(String,Interger,....Student,Person...),必须重写hashCode方法和equals方法
public class Person extends Object {
    @Override
    public int hashCode() {
        return 1;
    }
}


/*
* 哈希值:是一个十进制的整数,由于系统随机给出(就是对象的地址值,是一个逻辑地址,
*                                               是模拟出来得到地址,不是数据实际存储的物理地址)
* 在Object类有一个方法,可以获取对象的哈希值
* int hashCode方法的源码:
*   public native int hashCode();
*   native:代表该方法调用的是本地操作系统的方法
* */
public class Demo03HashCode {
    public static void main(String[] args) {
        //Person类继承了Object类,所以可以使用Object类的hashCode方法
        Person ps1 = new Person();
        int h1 = ps1.hashCode();
        System.out.println(h1);//重写完hashCode 输出 1

        Person ps2 = new Person();
        int h2 = ps2.hashCode();
        System.out.println(h2); //重写完hashCode 输出 1

        System.out.println(ps1);//cn.itcast.demo03.Person@1
        System.out.println(ps2);//cn.itcast.demo03.Person@1
        System.out.println(ps1==ps2);//false
    }

}

HashSet存储自定义类型元素:

public class Person extends Object {
    private String name;
    private int age;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


import java.util.HashSet;
/*
* hashSet存储自定义类型元素
* set集合报错元素唯一:
*    存储元素(String,Interger,....Student,Person...),必须重写hashCode方法和equals方法
* 要求:
*    同名同年龄的人,视为同一个人,只能存储一次
* */
public class Demo03Set02 {
    public static void main(String[] args) {
        //创建HashSet集合存储Person
        HashSet<Person> set = new HashSet<>();
        Person p1 = new Person("小美女",18);
        Person p2 = new Person("小美女",18);
        Person p3 = new Person("小美女",19);
        System.out.println(p1.hashCode());//356573597  | 重写两个方法之后734174878
        System.out.println(p2.hashCode());//1735600054 | 734174878
        //哈希值不同,认为是两个不同的元素
        //没有重写hashCode与equals时,比较的是两个对象地址值
        System.out.println(p1==p2);//false  | false
        System.out.println(p1.equals(p2));//false | true

        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);
        //[Person{name='小美女', age=18},Person{name='小美女', age=18}, Person{name='小美女', age=19}] | [Person{name='小美女', age=18}, Person{name='小美女', age=19}]
    }
}

LinkedHashSet集合:

可变参数:

/*
* 可变参数:是JDK1.5之后出现的新特性
* 使用前提:
*   当方法的参数列表数据类型已经确定,但是参数的个数不确定,就可以使用可变参数
* 使用格式:
*   修饰符 返回值类型 方法名(数据类型...变量名){}
* 可变参数的原理:
*   可变参数底层就是一个数组,根据传递参数个数不同,会创建不同长度的数组,来存储这些参数
*   传递的参数个数,可以是0个(不传递),1,2,...多个
*
* 可变参数注意事项:
*   1.一个方法的参数列表,只能有一个可变参数
*   public static void method(int...a,String...b){ } -> 错误写法
*   2.如果方法的参数有多个,那么可变参数必须写在参数列表的末尾
*   public static void method(int...a,String b,double c){ } -> 错误写法
*   public static void method(String b,double c,int...a){ } ->正确写法
*
* 可变参数特殊写法(终极写法),可接收任意参数:
*   public static void method(Object...obj){ }
* */
public class Demo03VarArgs {
    public static void main(String[] args) {
        //int i = add();
        //int i = add(10);
        int i = add(10,20);
        System.out.println(i);//30
       /* System.out.println(i);*/
        method("xiaobai",1,2,3.3);
    }
    public static void method(Object...obj){
        for (Object o : obj) {
            System.out.print(o+" ");//xiaobai 1 2 3.3 
        }
        System.out.println();
    }

    /*
    * 定义计算0~n个int类型整数的和方法
    * 需求分析:
    *   已知:计算整数的和,数据类型已经确定int
    *   但是参数的个数不确定,不知道要计算几个整数的和,就可以使用可变参数
    * add();就会创建一个长度为0的数组,new int[0]
    * add(10);就会创建一个长度为1的数组,存储传递过来的参数new int[]{10}
    * add(10,20);就会创建一个长度为2的数组,存储传递过来的参数new int[]{10,20}
    * ........
    * */
    public static int add(int...arr){
       // System.out.println(arr);//[I@1540e19d 底层是一个数组
       // System.out.println(arr.length);//0 1 2
        //定义一个初始化变量,来记录累加求和
        int sum = 0;
        //遍历数组,获取数组中的每一个元素
        for (int i : arr) {
            sum += i;
        }
        return sum;
    }
}

推荐阅读